適用于 Python 的 Azure 機密總帳用戶端程式庫 - 1.1.1 版
Azure 機密總帳提供服務,以記錄到不可變、防竄改的總帳。 作為 Azure 機密運算 組合的一部分,Azure 機密總帳會在安全、以硬體為基礎的受信任執行環境中執行,也稱為記憶體保護區。 它是以 Microsoft Research 的 機密聯盟架構為基礎。
| 原始程式碼套件 (PyPI) | 封裝 (Conda) | API 參考檔 | 產品檔
開始使用
安裝套件
使用pip安裝azure-confidentialledger和azure-identity:
pip install azure-identity azure-confidentialledger
azure-identity 用於 Azure Active Directory 驗證,如下所示。
必要條件
- Azure 訂用帳戶
- Python 3.6 版或更新版本
- Azure 機密總帳的執行中實例。
- 機密總帳中已註冊的使用者,通常會在 ARM 資源建立期間指派許可權
Administrator
。
驗證用戶端
使用 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 和識別碼,您可以從 Azure CLI 或 Azure 入口網站取得。 當您擷取這些值時,請取代 下列範例中的 和 "https://my-ledger-id.confidential-ledger.azure.com"
實例 "my-ledger-id"
。 您可能也需要在總帳的 ARM 描述中,將 取代 "https://identity.confidential-ledger.core.azure.com"
為 的主機名稱 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 機密總帳都會在服務中產生不可變的總帳專案。 寫入也稱為交易,會以每次寫入遞增的交易識別碼來唯一識別。 寫入之後,隨時都可以擷取總帳專案。
集合
雖然大部分的使用案例只涉及每個機密總帳的一個集合,但我們會提供集合識別碼功能,以防語意或邏輯上不同的資料群組必須儲存在相同的機密總帳中。
總帳專案會由其 collectionId
擷取。 機密總帳一律會假設為未指定而寫入 collectionId
之專案所決定 collectionId
的常數服務。
使用者
使用者會直接使用機密總帳來管理,而不是透過 Azure 來管理。 使用者可能是 AAD 型,由其 AAD 物件識別碼識別,或以憑證為基礎,由其 PEM 憑證指紋識別。
Receipts
為了強制執行交易完整性保證,Azure 機密總帳會使用 [Merkle 樹狀結構][merkle_tree_wiki] 資料結構來記錄附加至不可變總帳之所有交易區塊的雜湊。 認可寫入交易之後,Azure 機密總帳使用者可以透過機密總帳中產生的專案取得密碼編譯 Merkle 證明或收據,以確認已正確儲存寫入作業。 寫入交易收據是系統已認可對應交易的證明,而且可用來確認專案已有效地附加至總帳。
如需有關 Azure 機密總帳寫入交易收據的詳細資訊,請參閱下列 文章 。
收據驗證
取得寫入交易的收據之後,Azure 機密總帳使用者可以在驗證演算法之後驗證所擷取收據的內容。 驗證的成功是證明與收據相關聯的寫入作業已正確附加至不可變的總帳。
如需 Azure 機密總帳寫入交易收據驗證程式的詳細資訊,請參閱下列 文章 。
應用程式宣告
Azure 機密總帳應用程式可以附加任意資料,稱為應用程式宣告,以寫入交易。 這些宣告代表寫入作業期間執行的動作。 附加至交易時,宣告物件的 SHA-256 摘要會包含在總帳中,並認可為寫入交易的一部分。 這可確保摘要已就地登入,而且無法遭到竄改。
之後,應用程式宣告可以在回條承載中以未摘要形式顯示,對應至新增它們的相同交易。 這可讓使用者利用收據中的資訊,在交易期間重新計算 Azure 機密總帳實例所附加並登入的相同宣告摘要。 宣告摘要可用來作為寫入交易收據驗證程式的一部分,為使用者提供離線方式,以完整驗證所記錄宣告的真實性。
如需應用程式宣告格式和摘要計算演算法的詳細資訊,請參閱下列連結:
如需 CCF 應用程式宣告的詳細資訊,請參閱下列 CCF 檔頁面:
機密運算
Azure 機密運算 可讓您在雲端處理資料時隔離並保護資料。 Azure 機密總帳會在 Azure 機密運算虛擬機器上執行,藉由加密使用中的資料來提供更強的資料保護。
機密聯盟架構
Azure 機密總帳是以 Microsoft Research 的開放原始碼 機密聯盟架構為基礎, (CCF) 。 在 CCF 下,應用程式是由成員聯盟管理,能夠提交提案以修改和管理應用程式作業。 在 Azure 機密總帳中,Microsoft Azure 擁有操作員成員身分識別,可讓它執行治理和維護動作,例如取代機密總帳中的狀況不良節點,以及升級記憶體保護區程式碼。
範例
本節包含涵蓋一般工作的程式碼片段,包括:
附加專案
必須將專案附加至總帳,以不變的方式以竄改方式儲存至 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"]}'
)
擷取總帳專案
取得比最新還舊的總帳專案可能需要一些時間,因為服務正在載入歷程記錄專案,因此會提供輪詢器。
總帳專案是由集合擷取。 傳回的值是在交易識別碼所識別的時間點,包含在指定集合中的值。
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"]}'
)
建立範圍查詢
總帳專案可以擷取到交易識別碼的範圍。 專案只會從預設或指定的集合傳回。
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"]}')
管理使用者
具有 Administrator
許可權的使用者可以直接使用機密總帳本身來管理機密總帳的使用者。 可用的角色 (Reader
唯讀) 、 Contributor
(讀取和寫入) ,以及 Administrator
(讀取、寫入和新增或移除使用者) 。
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 機密 Legder 實例所發出的寫入交易收據。 公用程式可用來離線驗證收據,因為驗證演算法不需要連線到機密總帳或任何其他 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 程式,示範如何將新專案附加至執行中的機密總帳實例、取得認可交易的收據,以及確認收據內容可以在 samples 資料夾下找到: get_and_verify_receipt.py。
非同步 API
此程式庫包含 Python 3.5+ 上支援的完整非同步 API。 若要使用它,您必須先安裝非同步傳輸,例如 aioHTTP。 如需詳細資訊,請參閱 azure 核心檔 。
從 取得 azure.confidentialledger.aio
非同步用戶端。 方法的名稱和簽章與同步用戶端相同。 您可以 在這裡找到範例。
疑難排解
一般
機密總帳用戶端會引發 azure 核心中定義的例外狀況。 例如,如果您嘗試取得不存在的交易, 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)
記錄
此程式庫會使用標準 記錄 程式庫進行記錄。 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 機密總帳用戶端程式庫的常見案例作業。
常見的案例
寫入總帳:
撰寫許多總帳專案,並在之後全部擷取:
使用服務實作的角色型存取控制來管理使用者:
- manage_users.py
- manage_users_async.py (非同步版本)
進階案例
使用集合:
取得總帳寫入的收據:
- get_receipt.py
- get_receipt_async.py (非同步版本)
驗證服務詳細資料:
其他文件
如需有關 Azure 機密總帳的更廣泛檔,請參閱 API 參考檔。 您也可以深入瞭解 Microsoft Research 的開放原始碼 機密聯盟架構。
參與
此專案歡迎參與和提供建議。 大部分的參與都要求您同意「參與者授權合約 (CLA)」,宣告您有權且確實授與我們使用投稿的權利。 如需詳細資料,請前往 https://cla.microsoft.com 。
當您提交提取要求時,CLA Bot 會自動判斷您是否需要提供 CLA,並適當地裝飾 PR (例如標籤、註解)。 請遵循 bot 提供的指示。 您只需要使用我們的 CLA 在所有存放庫上執行此動作一次。
此專案採用了 Microsoft 開放原始碼管理辦法。 如需詳細資訊,請參閱管理辦法常見問題集,如有其他問題或意見,請連絡 opencode@microsoft.com。