Condividi tramite


Catene di credenziali nella libreria client di Identità di Azure per Python

La libreria client di Identità di Azure fornisce le credenziali, ovvero classi pubbliche che implementano il protocollo TokenCredential della libreria Core di Azure. Una credenziale rappresenta un flusso di autenticazione distinto per l'acquisizione di un token di accesso da Microsoft Entra ID. Queste credenziali si possono concatenare per formare una sequenza ordinata di meccanismi di autenticazione da tentare.

Funzionamento di una credenziale concatenata

In fase di esecuzione, una catena di credenziali tenta di eseguire l'autenticazione usando la prima credenziale della sequenza. Se tale credenziale non riesce ad acquisire un token di accesso, viene tentata la credenziale successiva nella sequenza e così via finché non viene ottenuto un token di accesso correttamente. Il diagramma di sequenza seguente illustra questo comportamento:

Diagramma che mostra la sequenza della catena di credenziali.

Perché usare le catene di credenziali

Una credenziale concatenata può offrire i vantaggi seguenti:

  • Riconoscimento dell'ambiente: seleziona automaticamente la credenziale più adeguata in base all'ambiente di esecuzione dell'app. Senza di essa, si dovrebbe scrivere un codice simile al seguente:

    # Set up credential based on environment (Azure or local development)
    if os.getenv("WEBSITE_HOSTNAME"):
        credential = ManagedIdentityCredential(client_id=user_assigned_client_id)
    else:
        credential = AzureCliCredential()
    
  • Transizioni lineari: l'app può passare dall'ambiente di sviluppo locale a quello di gestione temporanea o di produzione senza modificare il codice l'autenticazione.

  • Resilienza migliorata: include un meccanismo di fallback che passa alla credenziale successiva se quella precedente non riesce ad acquisire un token di accesso.

Come scegliere una credenziale concatenata

Esistono due filosofie diverse per il concatenamento delle credenziali:

Panoramica di DefaultAzureCredential

DefaultAzureCredential è una catena di credenziali preconfigurata e vincolante. È progettata per supportare molti ambienti, insieme ai flussi di autenticazione e agli strumenti di sviluppo più comuni. Graficamente, la catena sottostante è simile alla seguente:

Diagramma che mostra il flusso di autenticazione DefaultAzureCredential.

L'ordine in cui DefaultAzureCredential tenta le credenziali.

Ordinamento Credenziale Descrizione Abilitata per impostazione predefinita?
1 Ambiente Legge una raccolta di variabili di ambiente per determinare se un'entità servizio dell'applicazione (utente dell'applicazione) è configurata per l'app. In questo caso, DefaultAzureCredential usa questi valori per autenticare l'app in Azure. Questo metodo viene usato più spesso negli ambienti server, ma può essere usato anche durante lo sviluppo in locale.
2 Identità del carico di lavoro Se l'app viene distribuita in un host di Azure con identità del carico di lavoro abilitata, autenticare l'account.
3 Identità gestita Se l'app viene distribuita in un host di Azure con identità gestita abilitata, autentica l'app in Azure usando l'identità gestita.
4 Cache dei token condivisi Se lo sviluppatore ha eseguito l'autenticazione in Azure accedendo a Visual Studio, autenticare l'app in Azure usando lo stesso account. (solo Windows).
5 Interfaccia della riga di comando di Azure Se lo sviluppatore ha eseguito l'autenticazione in Azure usando il comando az login dell'interfaccia della riga di comando, autenticare l'app in Azure usando lo stesso account.
6 Azure PowerShell Se lo sviluppatore ha eseguito l'autenticazione in Azure usando il cmdlet Connect-AzAccount di PowerShell, autenticare l'app in Azure usando lo stesso account.
7 Azure Developer CLI Se lo sviluppatore ha eseguito l'autenticazione in Azure usando il comando azd auth login dell'interfaccia a riga di comando di Azure Developer, eseguire l'autenticazione con tale account.
8 Browser interattivo Se abilitato, autenticare in modo interattivo lo sviluppatore tramite il browser predefinito del sistema corrente. No

Nella sua forma più semplice, è possibile usare la versione senza parametri di DefaultAzureCredential, come indicato di seguito:

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

# Acquire a credential object
credential = DefaultAzureCredential()

blob_service_client = BlobServiceClient(
    account_url="https://<my_account_name>.blob.core.windows.net",
    credential=credential
)

Come personalizzare DefaultAzureCredential

Per rimuovere una credenziale da DefaultAzureCredential, usare il parametro della parola chiave -prefixed corrispondenteexclude. Ad esempio:

credential = DefaultAzureCredential(
    exclude_environment_credential=True, 
    exclude_workload_identity_credential=True,
    managed_identity_client_id=user_assigned_client_id
)

Nell'esempio di codice precedente, EnvironmentCredential e WorkloadIdentityCredential vengono rimossi dalla catena di credenziali. Di conseguenza, la prima credenziale da tentare è ManagedIdentityCredential. La catena modificata ha un aspetto simile alla seguente:

Diagramma che mostra il flusso di autenticazione per un'istanza DefaultAzureCredential dopo l'uso di parametri di parole chiave con prefisso exclude nel costruttore per rimuovere le credenziali dell'identità dell'ambiente e del carico di lavoro.

Nota

InteractiveBrowserCredential viene esclusa per impostazione predefinita, pertanto non compare nel diagramma precedente. Per includere InteractiveBrowserCredential, impostare il parametro della exclude_interactive_browser_credential parola chiave su False quando si chiama il DefaultAzureCredential costruttore.

Man mano che sono impostati True più excludeparametri con parole chiave con prefisso (sono configurate esclusioni di credenziali), i vantaggi dell'uso DefaultAzureCredential diminuiscono. In questi casi, ChainedTokenCredential è una scelta migliore e richiede meno codice. Per un esempio, questi due codici si comportano allo stesso modo:

credential = DefaultAzureCredential(
    exclude_environment_credential=True,
    exclude_workload_identity_credential=True,
    exclude_shared_token_cache_credential=True,
    exclude_azure_powershell_credential=True,
    exclude_azure_developer_cli_credential=True,
    managed_identity_client_id=user_assigned_client_id
)

Panoramica di ChainedTokenCredential

ChainedTokenCredential è una catena vuota a cui aggiungere le credenziali in base alle esigenze dell'app. Ad esempio:

credential = ChainedTokenCredential(
    ManagedIdentityCredential(client_id=user_assigned_client_id),
    AzureCliCredential()
)

L'esempio di codice precedente crea una catena di credenziali personalizzata che ne comprende due. La variante con identità gestita assegnata dall'utente di ManagedIdentityCredential viene tentata per prima, seguita da AzureCliCredential, se necessario. Graficamente, la catena è simile alla seguente:

Diagramma che mostra il flusso di autenticazione per un'istanza chainedTokenCredential composta da credenziali di identità gestite e credenziali dell'interfaccia della riga di comando di Azure.

Suggerimento

Per migliorare le prestazioni, ottimizzare l'ordinamento delle credenziali in ChainedTokenCredential per l'ambiente di produzione. Le credenziali destinate all'uso nell'ambiente di sviluppo locale devono essere aggiunte per ultime.

Linee guida sull'utilizzo di DefaultAzureCredential

DefaultAzureCredential è senza dubbio il modo più semplice per iniziare a usare la libreria client di Identità di Azure, ma con tale praticità risulta compromesso. Una volta distribuita l'app in Azure, è necessario comprendere i requisiti di autenticazione dell'app. Per questo motivo è consigliabile passare da DefaultAzureCredential a una delle soluzioni seguenti:

  • Implementazione specifica delle credenziali, ad esempio ManagedIdentityCredential.
  • Un'implementazione essenziale di ChainedTokenCredential ottimizzata per l'ambiente Azure in cui viene eseguita l'app.

Ecco perché:

  • Problematiche di debug: quando l'autenticazione non va a buon fine, può essere difficile eseguire il debug e l'identificazione della credenziale all'origine dell'errore. È necessario abilitare la registrazione per visualizzare il passaggio da una credenziale alla successiva e lo stato di esito positivo/negativo di ognuna di esse. Per altre informazioni, vedere la sezione Eseguire il debug di una credenziale concatenata.
  • Overhead delle prestazioni: il processo di prova sequenziale di più credenziali può introdurre l'overhead delle prestazioni. Ad esempio, se si esegue l'app in un computer di sviluppo locale, l'identità gestita non è disponibile. Di conseguenza, ManagedIdentityCredential ha sempre esito negativo nell'ambiente di sviluppo locale, a meno che non sia disabilitato in modo esplicito tramite la proprietà con prefisso exclude corrispondente.
  • Comportamento imprevedibile: DefaultAzureCredential verifica la presenza di alcune variabili di ambiente. È possibile che un utente possa aggiungere o modificare queste variabili di ambiente a livello di sistema nel computer host. Tali modifiche si applicano a livello globale e quindi modificano il comportamento di DefaultAzureCredential in fase di runtime in qualsiasi app in esecuzione in tale computer.

Eseguire il debug di credenziali concatenate

Per diagnosticare un problema imprevisto o per comprendere le operazioni di una credenziale concatenata, abilitare la registrazione nell'app. Facoltativamente, filtrare i log in modo che solo gli eventi generati dalla libreria client di Identità di Azure. Ad esempio:

import logging
from azure.identity import DefaultAzureCredential

# Set the logging level for the Azure Identity library
logger = logging.getLogger("azure.identity")
logger.setLevel(logging.DEBUG)

# Direct logging output to stdout. Without adding a handler,
# no logging output is visible.
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)

# Optional: Output logging levels to the console.
print(
    f"Logger enabled for ERROR={logger.isEnabledFor(logging.ERROR)}, "
    f"WARNING={logger.isEnabledFor(logging.WARNING)}, "
    f"INFO={logger.isEnabledFor(logging.INFO)}, "
    f"DEBUG={logger.isEnabledFor(logging.DEBUG)}"
)

A scopo illustrativo, si supponga che venga usata la forma senza parametri di DefaultAzureCredential per autenticare una richiesta a un account di archiviazione BLOB. L'app viene eseguita nell'ambiente di sviluppo locale e lo sviluppatore ha eseguito l'autenticazione in Azure usando l'interfaccia della riga di comando di Azure. Si supponga anche che il livello di registrazione sia impostato su logging.DEBUG. Quando l'app viene eseguita, nell'output vengono visualizzate le voci pertinenti seguenti:

Logger enabled for ERROR=True, WARNING=True, INFO=True, DEBUG=True
No environment configuration found.
ManagedIdentityCredential will use IMDS
EnvironmentCredential.get_token failed: EnvironmentCredential authentication unavailable. Environment variables are not fully configured.
Visit https://aka.ms/azsdk/python/identity/environmentcredential/troubleshoot to troubleshoot this issue.
ManagedIdentityCredential.get_token failed: ManagedIdentityCredential authentication unavailable, no response from the IMDS endpoint.     
SharedTokenCacheCredential.get_token failed: SharedTokenCacheCredential authentication unavailable. No accounts were found in the cache.
AzureCliCredential.get_token succeeded
[Authenticated account] Client ID: 00001111-aaaa-2222-bbbb-3333cccc4444. Tenant ID: aaaabbbb-0000-cccc-1111-dddd2222eeee. User Principal Name: unavailableUpn. Object ID (user): aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb
DefaultAzureCredential acquired a token from AzureCliCredential

Nell'output precedente è possibile notare quanto segue:

  • EnvironmentCredential, ManagedIdentityCredential e SharedTokenCacheCredential hanno tutte fallito nel tentativo di acquisire un token di accesso Microsoft Entra, nell'ordine.
  • La AzureCliCredential.get_token chiamata ha esito positivo e l'output indica anche che DefaultAzureCredential ha acquisito un token da AzureCliCredential. Poiché AzureCliCredential l'operazione è riuscita, non sono state tentate credenziali oltre.

Nota

Nell'esempio precedente il livello di registrazione è impostato su logging.DEBUG. Prestare attenzione quando si usa questo livello di registrazione, in quanto può restituire informazioni riservate. In questo caso, ad esempio, l'ID client, l'ID tenant e l'ID oggetto dell'entità utente dello sviluppatore in Azure. Tutte le informazioni di traceback sono state rimosse dall'output per maggiore chiarezza.