Condividi tramite


Libreria client del libro mastro riservato di Azure per Python - versione 1.1.1

Il libro mastro riservato di Azure fornisce un servizio per la registrazione in un libro mastro non modificabile e a prova di manomissione. Come parte del portfolio di Confidential Computing di Azure , Il libro mastro riservato di Azure viene eseguito in ambienti di esecuzione attendibili sicuri basati su hardware, noti anche come enclave. Si basa su Confidential Consortium Framework di Microsoft Research.

Codice | sorgentePacchetto (PyPI) | Pacchetto (Conda) | Documentazione | di riferimento sulle APIDocumentazione del prodotto

Introduzione

Installare i pacchetti

Installare azure-confidentialledger e azure-identity con pip:

pip install azure-identity azure-confidentialledger

azure-identity viene usato per l'autenticazione di Azure Active Directory, come illustrato di seguito.

Prerequisiti

  • Una sottoscrizione di Azure
  • Python 3.6 o versione successiva
  • Istanza in esecuzione del libro mastro riservato di Azure.
  • Un utente registrato nel Libro mastro riservato, in genere assegnato durante la creazione di risorse ARM , con Administrator privilegi.

Autenticare il client

Uso di Azure Active Directory

Questo documento illustra l'uso di DefaultAzureCredential per l'autenticazione al libro mastro riservato tramite Azure Active Directory. Accetta tuttavia ConfidentialLedgerClient qualsiasi credenziale azure-identity . Per altre informazioni sulle altre credenziali, vedere la documentazione di azure-identity .

Uso di un certificato client

In alternativa ad Azure Active Directory, i client possono scegliere di usare un certificato client per l'autenticazione tramite TLS reciproco. azure.confidentialledger.ConfidentialLedgerCertificateCredential può essere utilizzato a questo scopo.

Creare un client

DefaultAzureCredential gestirà automaticamente la maggior parte degli scenari client di Azure SDK. Per iniziare, impostare le variabili di ambiente per l'identità di AAD registrata con il libro mastro riservato.

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

DefaultAzureCredential Sarà quindi possibile autenticare .ConfidentialLedgerClient

La creazione del client richiede anche l'URL e l'ID del libro mastro riservato, che è possibile ottenere dall'interfaccia della riga di comando di Azure o dal portale di Azure. Dopo aver recuperato questi valori, sostituire le istanze di "my-ledger-id" e "https://my-ledger-id.confidential-ledger.azure.com" negli esempi seguenti. Potrebbe anche essere necessario sostituire "https://identity.confidential-ledger.core.azure.com" con il nome host da identityServiceUri nella descrizione ARM del libro mastro.

Poiché i ledgger riservati usano certificati autofirmati generati e archiviati in modo sicuro in un'enclave, il certificato di firma per ogni libro mastro riservato deve prima essere recuperato dal servizio di identità del libro mastro riservato.

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
)

In pratica, il ConfidentialLedgerClient costruttore recupererà il certificato TLS libro mastro (e lo scriverà nel file specificato) se viene fornito con un file inesistente. L'utente è responsabile della rimozione del file creato in base alle esigenze.

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`.

Per chiarire che un file viene usato per il certificato TLS libro mastro, gli esempi successivi scriveranno in modo esplicito il certificato TLS del libro mastro in un file.

Concetti chiave

Movimenti contabili e transazioni

Ogni scrittura nel libro mastro riservato di Azure genera una voce libro mastro non modificabile nel servizio. Le scritture, dette anche transazioni, sono identificate in modo univoco dagli ID transazione che aumentano con ogni scrittura. Una volta scritti, le voci contabili possono essere recuperate in qualsiasi momento.

Raccolte

Anche se la maggior parte dei casi d'uso prevede una sola raccolta per libro mastro riservato, viene specificata la funzionalità id raccolta nel caso in cui sia necessario archiviare in modo semantico o logico gruppi di dati diversi nello stesso libro mastro riservato.

Le voci del libro mastro vengono recuperate dal rispettivo collectionId. Il libro mastro riservato presuppone sempre una costante, determinata collectionId dal servizio per le voci scritte senza specificare.collectionId

Utenti

Gli utenti vengono gestiti direttamente con il libro mastro riservato anziché tramite Azure. Gli utenti possono essere basati su AAD, identificati dall'ID oggetto AAD o dal certificato, identificato dall'impronta digitale del certificato PEM.

Receipts

Per applicare garanzie di integrità delle transazioni, un libro mastro riservato di Azure usa una struttura di dati [albero Merkle][merkle_tree_wiki] per registrare l'hash di tutti i blocchi di transazioni aggiunti al libro mastro non modificabile. Dopo il commit di una transazione di scrittura, gli utenti del libro mastro riservato di Azure possono ottenere una prova di merkle crittografica o ricevuta, sulla voce prodotta in un libro mastro riservato per verificare che l'operazione di scrittura sia stata salvata correttamente. Una ricevuta di transazione di scrittura è la prova che il sistema ha eseguito il commit della transazione corrispondente e può essere usato per verificare che la voce sia stata effettivamente aggiunta al libro mastro.

Per altre informazioni sulle ricevute delle transazioni di scrittura riservate di Azure, vedere l'articolo seguente.

Verifica della ricevuta

Dopo aver ricevuto una ricevuta per una transazione di scrittura, gli utenti del libro mastro riservato di Azure possono verificare il contenuto della ricevuta recuperata seguendo un algoritmo di verifica. L'esito positivo della verifica è la prova che l'operazione di scrittura associata alla ricevuta è stata aggiunta correttamente al libro mastro non modificabile.

Per altre informazioni sul processo di verifica per le ricevute delle transazioni di scrittura del libro mastro riservato di Azure, vedere l'articolo seguente.

Attestazioni dell'applicazione

Le applicazioni Libro mastro riservato di Azure possono collegare dati arbitrari, denominati attestazioni dell'applicazione, per scrivere transazioni. Queste attestazioni rappresentano le azioni eseguite durante un'operazione di scrittura. Se associato a una transazione, il digest SHA-256 dell'oggetto attestazioni viene incluso nel libro mastro ed eseguito il commit come parte della transazione di scrittura. Ciò garantisce che il digest sia connesso e non possa essere manomesso.

Successivamente, le attestazioni dell'applicazione possono essere rivelate nel formato non inserito nel payload di ricezione corrispondente alla stessa transazione in cui sono stati aggiunti. Ciò consente agli utenti di sfruttare le informazioni nella ricevuta per calcolare di nuovo lo stesso digest delle attestazioni collegato e connesso dall'istanza del libro mastro riservato di Azure durante la transazione. Il digest delle attestazioni può essere usato come parte del processo di verifica della ricezione delle transazioni di scrittura, offrendo agli utenti un modo offline per verificare completamente l'autenticità delle attestazioni registrate.

Per altre informazioni sul formato delle attestazioni dell'applicazione e sull'algoritmo di calcolo del digest, vedere i collegamenti seguenti:

Per altre informazioni sulle attestazioni dell'applicazione CCF, vedere le pagine della documentazione CCF seguenti:

Confidential computing

Il confidential computing di Azure consente di isolare e proteggere i dati durante l'elaborazione nel cloud. Il libro mastro riservato di Azure viene eseguito in macchine virtuali di Confidential Computing di Azure, offrendo così una protezione dei dati più avanzata con la crittografia dei dati in uso.

Confidential Consortium Framework

Il libro mastro riservato di Azure si basa sul framework CCF (Confidential Consortium Framework) open source di Microsoft Research. In CCF, le applicazioni sono gestite da un consorzio di membri con la possibilità di inviare proposte per modificare e gestire l'operazione dell'applicazione. In Azure Confidential Ledger, Microsoft Azure possiede un'identità membro dell'operatore che consente di eseguire azioni di governance e manutenzione come la sostituzione di nodi non integri nel Libro mastro riservato e l'aggiornamento del codice dell'enclave.

Esempio

Questa sezione contiene frammenti di codice relativi alle attività comuni, tra cui:

Aggiungi voce

I dati che devono essere archiviati in modo non modificabile in modo antimanomissione possono essere salvati in Un libro mastro riservato di Azure aggiungendo una voce al libro mastro.

Poiché Confidential Ledger è un sistema distribuito, rari errori temporanei possono causare la perdita di scritture. Per le voci che devono essere mantenute, è consigliabile verificare che la scrittura sia diventata durevole. Per le scritture meno importanti in cui è preferibile una maggiore velocità effettiva del client, il passaggio di attesa potrebbe essere ignorato.

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')

In alternativa, il client potrebbe attendere il commit durante la scrittura di una voce libro mastro.

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"]}'
)

Recupero di voci mastro

L'acquisizione di voci libro mastro precedenti a quelle più recenti potrebbe richiedere del tempo perché il servizio sta caricando voci cronologiche, quindi viene fornito un poller.

Le voci libro mastro vengono recuperate dalla raccolta. Il valore restituito è il valore contenuto nella raccolta specificata nel momento identificato dall'ID transazione.

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"]}'
)

Creazione di una query con intervallo

Le voci del libro mastro possono essere recuperate su un intervallo di ID transazione. Le voci verranno restituite solo dalla raccolta predefinita o specificata.

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"]}')

Gestione degli utenti

Gli utenti con Administrator privilegi possono gestire gli utenti del libro mastro riservato direttamente con il libro mastro riservato stesso. I ruoli disponibili sono Reader (sola lettura), Contributor (lettura e scrittura) e Administrator (lettura, scrittura e aggiunta o rimozione utenti).

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)

Uso dell'autenticazione del certificato

I client possono eseguire l'autenticazione con un certificato client in TLS reciproco anziché tramite un token di Azure Active Directory. ConfidentialLedgerCertificateCredential viene fornito per tali client.

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
)

Verificare le ricevute delle transazioni di scrittura

I client possono sfruttare la libreria di verifica delle ricevute nell'SDK per verificare le ricevute delle transazioni di scrittura rilasciate dalle istanze di Azure Confidential Legder. L'utilità può essere usata per verificare completamente le ricevute offline perché l'algoritmo di verifica non deve essere connesso a un ledger riservato o a qualsiasi altro servizio di Azure.

Dopo aver aggiunto una nuova voce al ledger (fare riferimento a questo esempio), è possibile ottenere una ricevuta per la transazione di scrittura con commit.

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}")

Dopo aver recuperato una ricevuta per una transazione di scrittura, è possibile chiamare la verify_receipt funzione per verificare che la ricevuta sia valida. La funzione può accettare un elenco facoltativo di attestazioni dell'applicazione da verificare nel digest delle attestazioni di ricezione.

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")

Un programma Python di esempio completo che illustra come aggiungere una nuova voce a un'istanza del Ledger riservato in esecuzione, ottenere una ricevuta per la transazione di commit e verificare che il contenuto della ricevuta sia disponibile nella cartella esempi : get_and_verify_receipt.py.

API asincrona

Questa libreria include un'API asincrona completa supportata in Python 3.5+. Per usarlo, è prima necessario installare un trasporto asincrono, ad esempio aiohttp. Per altre informazioni, vedere la documentazione di azure-core .

Un client asincrono viene ottenuto da azure.confidentialledger.aio. I metodi hanno gli stessi nomi e firme del client sincrono. Gli esempi sono disponibili qui.

Risoluzione dei problemi

Generale

I client del ledger riservato generano eccezioni definite in azure-core. Ad esempio, se si tenta di ottenere una transazione che non esiste, ConfidentialLedgerClient genera 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)

Registrazione

Questa libreria usa la libreria di registrazione standard per la registrazione. Le informazioni di base sulle sessioni HTTP (URL, intestazioni e così via) vengono registrate a livello di INFO.

La registrazione dettagliata del livello DEBUG, inclusi i corpi di richiesta/risposta e le intestazioni non attendibili, può essere abilitata in un client con l'argomento logging_enable :

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,
)

Analogamente, logging_enable può abilitare la registrazione dettagliata per una singola operazione, anche quando non è abilitata per il client:

ledger_client.get_current_ledger_entry(logging_enable=True)

Passaggi successivi

Altro codice di esempio

Questi esempi di codice mostrano operazioni di scenario comuni con la libreria client di Azure Confidential Ledger.

Scenari comuni

Scenari avanzati

Documentazione aggiuntiva

Per una documentazione più completa su Azure Confidential Ledger, vedere la documentazione di riferimento sulle API. È anche possibile leggere altre informazioni su Microsoft Research open source Confidential Consortium Framework.

Contributo

In questo progetto sono benvenuti i contributi e i suggerimenti. Per la maggior parte dei contenuti è necessario sottoscrivere un contratto di licenza di collaborazione (CLA, Contributor License Agreement) che stabilisce che l'utente ha il diritto di concedere, e di fatto concede a Microsoft i diritti d'uso del suo contributo. Per informazioni dettagliate, vedere https://cla.microsoft.com.

Quando si invia una richiesta pull, un bot CLA determina automaticamente se è necessario specificare un contratto CLA e completare la richiesta pull in modo appropriato (ad esempio con un'etichetta e un commento). Seguire le istruzioni specificate dal bot. È sufficiente eseguire questa operazione una sola volta per tutti i repository che usano il contratto CLA Microsoft.

Questo progetto ha adottato il Codice di comportamento di Microsoft per l'open source. Per altre informazioni, vedere Code of Conduct FAQ (Domande frequenti sul Codice di comportamento) oppure contattare opencode@microsoft.com per eventuali altre domande o commenti.