跳转到主要内容

Microsoft Azure Confidential Ledger Python客户端库

项目描述

Azure Confidential Ledger Python客户端库

Azure Confidential Ledger提供了一个将日志记录到不可变、防篡改账本的服务的服务。作为Azure Confidential Computing产品组合的一部分,Azure Confidential Ledger在基于硬件的安全可信执行环境中运行,也称为enclaves。它是基于微软研究Confidential Consortium Framework构建的。

源代码 | 包(PyPI) | 包(Conda) | API参考文档 | 产品文档

入门指南

安装软件包

使用pip安装azure-confidentialledgerazure-identity

pip install azure-identity azure-confidentialledger

azure-identity 用于 Azure Active Directory 身份验证,如下所示。

先决条件

  • Azure 订阅
  • Python 3.6 或更高版本
  • Azure 保密账本运行实例。
  • 保密账本中的注册用户,通常在 ARM 资源创建期间分配,具有 管理员 权限。

客户端认证

使用 Azure Active Directory

本文档演示了使用 DefaultAzureCredential 通过 Azure Active Directory 认证到保密账本。然而,ConfidentialLedgerClient 接受任何 azure-identity 凭证。有关其他凭证的更多信息,请参阅 azure-identity 文档。

使用客户端证书

作为 Azure Active Directory 的替代方案,客户端可以选择使用客户端证书通过相互 TLS 进行认证。可以使用 azure.confidentialledger.ConfidentialLedgerCertificateCredential 来实现此目的。

创建客户端

DefaultAzureCredential 将自动处理大多数 Azure SDK 客户端场景。要开始,请设置与您的保密账本注册的 AAD 身份的环境变量。

export AZURE_CLIENT_ID="generated app id"
export AZURE_CLIENT_SECRET="random password"
export AZURE_TENANT_ID="tenant id"

然后,DefaultAzureCredential 将能够认证 ConfidentialLedgerClient

构建客户端还需要您的保密账本的 URL 和 id,您可以从 Azure CLI 或 Azure 门户获取这些值。当您获取这些值后,请将以下示例中的 "my-ledger-id""https://my-ledger-id.confidential-ledger.azure.com" 实例替换为这些值。您可能还需要将 "https://identity.confidential-ledger.core.azure.com" 替换为您的账本的 ARM 描述中的 identityServiceUri 的主机名。

由于保密账本使用安全生成并存储在加密区域中的自签名证书,因此必须首先从保密账本身份服务中检索每个保密账本的签名证书。

from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = DefaultAzureCredential()
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

方便的是,如果提供不存在的文件,ConfidentialLedgerClient 构造函数将检索账本 TLS 证书(并将其写入指定的文件)。用户负责根据需要删除创建的文件。

from azure.confidentialledger import ConfidentialLedgerClient
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path="ledger_certificate.pem"
)

# The ledger TLS certificate is written to `ledger_certificate.pem`.

为了清楚地表明正在使用文件作为账本 TLS 证书,后续示例将明确将账本 TLS 证书写入文件。

关键概念

账本条目和事务

对 Azure 保密账本的每次写入都会在服务中生成一个不可变的账本条目。写入(也称为事务)由随每次写入递增的事务 id 唯一标识。一旦写入,账本条目可以随时检索。

集合

虽然大多数用例只涉及每个保密账本一个集合,但我们提供了集合 id 功能,以便在语义上或逻辑上不同的数据组需要存储在同一个保密账本中。

通过 collectionId 获取账本条目。保密账本将始终假设没有指定 collectionId 的条目使用由服务确定的常量 collectionId

用户

用户直接通过保密账本进行管理,而不是通过 Azure。用户可以是基于 AAD 的,通过他们的 AAD 对象 id 识别,也可以是基于证书的,通过他们的 PEM 证书指纹识别。

收据

为了确保事务完整性,Azure保密账本使用[Merkle树][merkle_tree_wiki]数据结构来记录附加到不可变账本的所有事务块的哈希值。在写事务提交后,Azure保密账本用户可以获得加密的Merkle证明或收据,以验证写入操作是否正确保存。写事务收据是系统已提交相应事务的证明,可用于验证条目是否已有效附加到账本。

有关Azure保密账本写事务收据的更多信息,请参阅以下文章

收据验证

在获得写事务收据后,Azure保密账本用户可以使用验证算法验证获取的收据内容。验证成功是证明与收据关联的写操作已被正确附加到不可变账本的证据。

有关Azure保密账本写事务收据验证过程的更多信息,请参阅以下文章

应用程序声明

Azure保密账本应用程序可以将任意数据(称为应用程序声明)附加到写事务中。这些声明代表写操作期间执行的操作。当附加到事务时,声明对象的SHA-256摘要包含在账本中,并作为写事务的一部分提交。这保证了摘要已原地签名且不可篡改。

稍后,应用程序声明可以在对应于添加它们的同一事务的收据有效负载中以未摘要的形式披露。这允许用户利用收据中的信息重新计算Azure保密账本实例在事务期间附加和签名的同一声明摘要。声明摘要可以用作写事务收据验证过程的一部分,为用户提供离线方式完全验证记录声明的真实性。

有关应用程序声明格式和摘要计算算法的更多详细信息,请参阅以下链接

有关CCF应用程序声明的更多信息,请参阅以下CCF文档页面

保密计算

Azure保密计算允许您在云中处理数据时隔离和保护您的数据。Azure保密账本在Azure保密计算虚拟机上运行,因此通过加密使用中的数据提供了更强的数据保护。

保密联盟框架

Azure保密账本建立在微软研究院开源的保密联盟框架(CCF)之上。在CCF下,应用程序由一个成员联盟管理,这些成员有权提交提案以修改和治理应用程序操作。在Azure保密账本中,微软Azure拥有一个操作成员身份,允许它执行治理和维护操作,如替换保密账本中的不健康节点和升级enclave代码。

示例

本节包含覆盖常见任务的代码片段,包括

附加条目

需要以防篡改的方式不可变存储的数据可以通过将条目附加到账本保存到Azure保密账本。

由于保密账本是分布式系统,罕见的短暂故障可能会导致写入丢失。对于必须保留的条目,建议验证写入是否已持久化。对于不太重要的写入,如果更偏好更高的客户端吞吐量,可以跳过等待步骤。

from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = DefaultAzureCredential()
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

post_entry_result = ledger_client.create_ledger_entry(
        {"contents": "Hello world!"}
    )
transaction_id = post_entry_result["transactionId"]

wait_poller = ledger_client.begin_wait_for_commit(transaction_id)
wait_poller.wait()
print(f'Ledger entry at transaction id {transaction_id} has been committed successfully')

或者,客户端可以在写入账本条目时等待提交。

from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = DefaultAzureCredential()
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

post_poller = ledger_client.begin_create_ledger_entry(
    {"contents": "Hello world again!"}
)
new_post_result = post_poller.result()
print(
    'The new ledger entry has been committed successfully at transaction id '
    f'{new_post_result["transactionId"]}'
)

检索账本条目

由于服务正在加载历史条目,获取比最新条目更旧的条目可能需要一些时间,因此提供了轮询器。

通过集合检索账本条目。返回值是在事务ID标识的时间点指定集合中包含的值。

from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = DefaultAzureCredential()
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

post_poller = ledger_client.begin_create_ledger_entry(
    {"contents": "Original hello"}
)
post_result = post_poller.result()

post_transaction_id = post_result["transactionId"]

latest_entry = ledger_client.get_current_ledger_entry()
print(
    f'Current entry (transaction id = {latest_entry["transactionId"]}) '
    f'in collection {latest_entry["collectionId"]}: {latest_entry["contents"]}'
)

post_poller = ledger_client.begin_create_ledger_entry(
    {"contents": "Hello!"}
)
post_result = post_poller.result()

get_entry_poller = ledger_client.begin_get_ledger_entry(post_transaction_id)
older_entry = get_entry_poller.result()
print(
    f'Contents of {older_entry["entry"]["collectionId"]} at {post_transaction_id}: {older_entry["entry"]["contents"]}'
)

执行范围查询

可以检索一系列事务ID的账本条目。只有从默认或指定的集合中返回条目。

from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = DefaultAzureCredential()
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

post_poller = ledger_client.begin_create_ledger_entry(
    {"contents": "First message"}
)
first_transaction_id = post_poller.result()["transactionId"]

for i in range(10):
    ledger_client.create_ledger_entry(
        {"contents": f"Message {i}"}
    )

post_poller = ledger_client.begin_create_ledger_entry(
    {"contents": "Last message"}
)
last_transaction_id = post_poller.result()["transactionId"]

ranged_result = ledger_client.list_ledger_entries(
    from_transaction_id=first_transaction_id,
    to_transaction_id=last_transaction_id,
)
for entry in ranged_result:
    print(f'Contents at {entry["transactionId"]}: {entry["contents"]}')

管理用户

具有管理员权限的用户可以直接使用保密账本来管理保密账本的用户。可用的角色有读取者(只读)、贡献者(读写)和管理员(读写、添加或删除用户)。

from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = DefaultAzureCredential()
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

user_id = "some AAD object id"
user = ledger_client.create_or_update_user(
    user_id, {"assignedRole": "Contributor"}
)
# A client may now be created and used with AAD credentials (i.e. AAD-issued JWT tokens) for the user identified by `user_id`.

user = ledger_client.get_user(user_id)
assert user["userId"] == user_id
assert user["assignedRole"] == "Contributor"

ledger_client.delete_user(user_id)

# For a certificate-based user, their user ID is the fingerprint for their PEM certificate.
user_id = "PEM certificate fingerprint"
user = ledger_client.create_or_update_user(
    user_id, {"assignedRole": "Reader"}
)

user = ledger_client.get_user(user_id)
assert user["userId"] == user_id
assert user["assignedRole"] == "Reader"

ledger_client.delete_user(user_id)

使用证书身份验证

客户端可以通过相互TLS中的客户端证书而不是通过Azure Active Directory令牌进行身份验证。ConfidentialLedgerCertificateCredential为这类客户端提供。

from azure.confidentialledger import (
    ConfidentialLedgerCertificateCredential,
    ConfidentialLedgerClient,
)
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = ConfidentialLedgerCertificateCredential(
    certificate_path="Path to user certificate PEM file"
)
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

验证写事务收据

客户端可以利用SDK中的收据验证库来验证由Azure保密账本实例发出的写入事务收据。此实用程序可以用于离线完全验证收据,因为验证算法不需要连接到保密账本或任何其他Azure服务。

一旦将新条目附加到账本中(请参阅此示例),就可以获取提交的写入事务的收据。

from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

# Replace this with the Confidential Ledger ID 
ledger_id = "my-ledger-id"

# Setup authentication
credential = DefaultAzureCredential()

# Create a Ledger Certificate client and use it to
# retrieve the service identity for our ledger
identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id=ledger_id
)

# Save ledger service certificate into a file for later use
ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

# Create Confidential Ledger client
ledger_client = ConfidentialLedgerClient(
    endpoint=f"https://{ledger_id}.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

# The method begin_get_receipt returns a poller that
# we can use to wait for the receipt to be available for retrieval 
get_receipt_poller = ledger_client.begin_get_receipt(transaction_id)
get_receipt_result = get_receipt_poller.result()

print(f"Write receipt for transaction id {transaction_id} was successfully retrieved: {get_receipt_result}")

在获取写入事务的收据后,可以调用verify_receipt函数来验证收据是否有效。该函数可以接受一个可选的应用声明列表,以验证收据声明摘要。

from azure.confidentialledger.receipt import (
    verify_receipt,
)

# Read contents of service certificate file saved in previous step.
with open(ledger_tls_cert_file_name, "r") as service_cert_file:
    service_cert_content = service_cert_file.read()

# Optionally read application claims, if any
application_claims = get_receipt_result.get("applicationClaims", None) 

try:
    # Verify the contents of the receipt.
    verify_receipt(get_receipt_result["receipt"], service_cert_content, application_claims=application_claims)
    print(f"Receipt for transaction id {transaction_id} successfully verified")
except ValueError:
    print(f"Receipt verification for transaction id {transaction_id} failed")

一个完整的Python示例程序,展示了如何将新条目追加到运行的保密账本实例中,获取提交事务的收据以及验证收据内容,可以在示例文件夹下找到:get_and_verify_receipt.py

异步API

此库包括一个完整的异步API,支持Python 3.5+。要使用它,您必须首先安装一个异步传输,例如aiohttp。有关更多信息,请参阅azure-core文档

azure.confidentialledger.aio获取异步客户端。方法具有与同步客户端相同的名称和签名。样本可在此处找到:这里

故障排除

通用

保密账本客户端引发在azure-core中定义的异常。例如,如果您尝试获取不存在的交易,则ConfidentialLedgerClient引发ResourceNotFoundError

from azure.core.exceptions import ResourceNotFoundError
from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = DefaultAzureCredential()
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name
)

try:
    ledger_client.begin_get_ledger_entry(
        transaction_id="10000.100000"  # Using a very high id that probably doesn't exist in the ledger if it's relatively new.
    )
except ResourceNotFoundError as e:
    print(e.message)

日志记录

此库使用标准的logging库进行日志记录。HTTP会话的基本信息(URL、标题等)以INFO级别进行记录。

可以通过客户端的logging_enable参数启用详细的DEBUG级别日志记录,包括请求/响应体和未脱敏的标题。

import logging
import sys

from azure.confidentialledger import ConfidentialLedgerClient
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient
from azure.identity import DefaultAzureCredential

# Create a logger for the 'azure' SDK
logger = logging.getLogger('azure')
logger.setLevel(logging.DEBUG)

# Configure a console output
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)

identity_client = ConfidentialLedgerCertificateClient()
network_identity = identity_client.get_ledger_identity(
    ledger_id="my-ledger-id"
)

ledger_tls_cert_file_name = "ledger_certificate.pem"
with open(ledger_tls_cert_file_name, "w") as cert_file:
    cert_file.write(network_identity["ledgerTlsCertificate"])

credential = DefaultAzureCredential()

# This client will log detailed information about its HTTP sessions, at DEBUG level.
ledger_client = ConfidentialLedgerClient(
    endpoint="https://my-ledger-id.confidential-ledger.azure.com",
    credential=credential,
    ledger_certificate_path=ledger_tls_cert_file_name,
    logging_enable=True,
)

同样,即使没有为客户端启用,logging_enable 也可以为单个操作启用详细日志。

ledger_client.get_current_ledger_entry(logging_enable=True)

下一步

更多示例代码

以下代码示例展示了与 Azure 密集型账本客户端库的常见场景操作。

常见场景

高级场景

其他文档

有关 Azure 密集型账本的更多详细文档,请参阅API 参考文档。您还可以了解更多关于微软研究开源的Confidential Consortium Framework

贡献

本项目欢迎贡献和建议。大多数贡献需要您同意贡献者许可协议(CLA),声明您有权并将实际授予我们使用您贡献的权利。有关详细信息,请访问https://cla.microsoft.com

当您提交拉取请求时,CLA-bot 将自动确定您是否需要提供 CLA 并相应地装饰 PR(例如,标签、注释)。只需遵循 bot 提供的说明即可。您只需要在整个使用我们 CLA 的所有存储库中做一次。

本项目采用了微软开源行为准则。有关更多信息,请参阅行为准则常见问题解答或联系opencode@microsoft.com以获取任何其他问题或评论。

发布历史

1.1.1 (2023-08-01)

修复的 Bug

  • begin_wait_for_commit 中允许一些 ResourceNotFoundError 发生,以考虑会话粘性意外丢失的情况。当连接的节点更改且事务尚未完全复制时,可能会发生这些错误。

1.1.0 (2023-05-09)

新增功能

  • 添加 azure.confidentialledger.receipt 模块以用于 Azure 密集型账本写入事务收据验证。
  • 添加 verify_receipt 函数以验证来自收据 JSON 对象的写入事务收据。该函数接受一个可选的、关键字参数的列表,即应用声明参数,可以用于从给定的声明计算声明摘要:如果计算的摘要值与收据中存在的 claimsDigest 值不匹配,则验证会失败。
  • 添加 compute_claims_digest 函数以从应用声明 JSON 对象列表计算声明摘要。
  • 添加示例代码以从正在运行的密集型账本实例获取和验证写入收据。
  • 更新 README 以包含收据验证和应用声明的示例和文档。

其他更改

  • 添加对 Python cryptography 库的依赖(>= 2.1.4
  • 添加对收据验证模型和收据验证公共方法的测试。
  • 为应用程序声明模型和摘要计算公共方法添加测试。

1.0.0 (2022-07-19)

Confidential Ledger 的 GA 数据平面 Python SDK。

修复的 Bug

  • 用户 ID 为证书指纹的不再在请求 URI 中进行 URL 编码。

重大更改

  • 已移除所有模型。现在方法直接返回 JSON。
  • sub_ledger_id 字段现在命名为 collection_id
  • azure.confidentialledger.identity_service 已重命名为 azure.confidentialledger.certificate
  • ConfidentialLedgerIdentityServiceClient 现在是 ConfidentialLedgerCertificateClient
  • post_ledger_entry 已重命名为 create_ledger_entry

其他更改

  • 不再支持 Python 2.7。请使用 Python 3.7 或更高版本。
  • 为某些长时间运行的操作添加了方便的轮询方法。
  • 添加了新的支持 API 版本:2022-05-13

1.0.0b1 (2021-05-12)

  • 这是 Azure Confidential Ledger 库的初始版本。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源分发

azure-confidentialledger-1.1.1.zip (176.9 kB 查看散列)

上传时间

构建分发

azure_confidentialledger-1.1.1-py3-none-any.whl (101.5 kB 查看散列)

上传时间 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面