Autenticazione di app ospitate in Azure in risorse di Azure con Azure SDK per Go
Quando si ospita un'app in Azure usando servizi come Azure App Service, Azure Virtual Machines o Azure Container Instances, l'approccio consigliato per autenticare un'app alle risorse di Azure è con identità gestita.
Un'identità gestita fornisce un'identità per l'app in modo che possa connettersi ad altre risorse di Azure senza la necessità di usare una chiave privata o un altro segreto dell'applicazione. Internamente, Azure conosce l'identità dell'app e le risorse a cui è consentito connettersi. Azure usa queste informazioni per ottenere automaticamente i token di Microsoft Entra per consentire all'app di connettersi ad altre risorse di Azure, senza dover gestire i segreti dell'applicazione.
Nota
Le app in esecuzione su Azure Kubernetes Service (AKS) possono utilizzare un'identità di carico di lavoro per autenticarsi con le risorse di Azure. Nel servizio AKS, un'identità di carico di lavoro rappresenta una relazione di fiducia tra un'identità gestita e un account di servizio Kubernetes. Se un'applicazione distribuita in AKS è configurata con un account di servizio Kubernetes in una relazione di questo tipo, DefaultAzureCredential
autentica l'app ad Azure utilizzando l'identità gestita. L'autenticazione tramite un'identità del carico di lavoro è descritta in Usare l'ID del carico di lavoro Microsoft Entra con il servizio Azure Kubernetes. Per informazioni su come configurare l'identità del carico di lavoro, vedere Distribuire e configurare l'identità del carico di lavoro in un cluster del servizio Azure Kubernetes.
Tipi di identità gestiti
Esistono due tipi di identità gestite:
- identità gestite assegnate dal sistema: questo tipo di identità gestita viene fornito e associato direttamente a una risorsa di Azure. Quando si abilita l'identità gestita in una risorsa di Azure, si ottiene un'identità gestita assegnata dal sistema per tale risorsa. Un'identità gestita assegnata dal sistema è associata al ciclo di vita della risorsa di Azure a cui è associata. Quando la risorsa viene eliminata, Azure elimina l'identità per te automaticamente. Poiché è necessario abilitare l'identità gestita per la risorsa di Azure che ospita il codice, questo approccio è il tipo più semplice di identità gestita da usare.
- identità gestite assegnate dall'utente: è anche possibile creare un'identità gestita come risorsa di Azure autonoma. Questo approccio viene usato più di frequente quando la soluzione ha più carichi di lavoro eseguiti su più risorse di Azure che devono tutti condividere la stessa identità e le stesse autorizzazioni. Ad esempio, se la soluzione include componenti eseguiti in più istanze del servizio app e delle macchine virtuali che devono accedere allo stesso set di risorse di Azure, un'identità gestita assegnata dall'utente usata tra queste risorse ha senso.
Questo articolo illustra i passaggi per abilitare e usare un'identità gestita assegnata dal sistema per un'app. Se è necessario usare un'identità gestita assegnata dall'utente, vedere l'articolo Gestire le identità gestite assegnate dall'utente per informazioni su come creare un'identità gestita assegnata dall'utente.
1 - Abilitare l'identità gestita nella risorsa di Azure che ospita l'app
Il primo passaggio consiste nell'abilitare l'identità gestita nella risorsa di Azure che ospita l'app. Ad esempio, se stai ospitando un'applicazione Gin usando Azure Container Apps, è necessario abilitare l'identità gestita per l'applicazione in contenitore. Se si usa una macchina virtuale per ospitare l'app, si abiliterà la macchina virtuale all'uso dell'identità gestita.
È possibile abilitare l'identità gestita da usare per una risorsa di Azure usando il portale di Azure o l'interfaccia della riga di comando di Azure.
- Azure CLI
- del portale di Azure
I comandi dell'interfaccia della riga di comando di Azure possono essere eseguiti nel di Azure Cloud Shell
I comandi dell'interfaccia della riga di comando di Azure usati per abilitare l'identità gestita per una risorsa di Azure sono nel formato az <command-group> identity --resource-group <resource-group-name> --name <resource-name>
. Di seguito sono riportati comandi specifici per i servizi di Azure più diffusi.
- App Container di Azure
- macchine virtuali di Azure
az containerapp identity assign \
--resource-group <resource-group-name> \
--name <container-app-name> \
--system-assigned
L'output sarà simile al seguente.
{
"principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
"tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
"type": "SystemAssigned",
"userAssignedIdentities": null
}
Il valore principalId
è l'ID univoco dell'identità gestita. Mantenere una copia di questo output perché questi valori saranno necessari nel passaggio successivo.
2 - Assegnare ruoli all'identità gestita
Successivamente, è necessario determinare i ruoli (autorizzazioni) necessari per l'app e assegnare l'identità gestita a tali ruoli in Azure. Un'identità gestita può essere assegnata a ruoli a livello di risorsa, gruppo di risorse o ambito di sottoscrizione. Questo esempio illustra come assegnare ruoli nell'ambito del gruppo di risorse perché la maggior parte delle applicazioni raggruppa tutte le risorse di Azure in un singolo gruppo di risorse.
- Azure CLI
- del portale di Azure
Ad un'identità gestita viene assegnato un ruolo in Azure utilizzando il comando az role assignment create. Per l'assegnatario, usare il codice principalId
copiato nel passaggio 1.
az role assignment create --assignee {managedIdentityprincipalId} \
--scope /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName} \
--role "{roleName}"
Per ottenere i nomi di ruolo a cui è possibile assegnare un principale del servizio, usare il comando az role definition list.
az role definition list \
--query "sort_by([].{roleName:roleName, description:description}, &roleName)" \
--output table
Ad esempio, per consentire all'identità gestita con l'ID aaaaaaaa-bbbb-cccc-1111-222222222222
l'accesso in lettura, scrittura ed eliminazione ai contenitori e ai dati BLOB di Archiviazione di Azure in tutti gli account di archiviazione nel gruppo di risorse your-resource-group-name della sottoscrizione con ID aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e
, si assegnerebbe l'entità servizio dell'applicazione al ruolo di Storage Blob Data Contributor usando il comando seguente.
az role assignment create --assignee aaaaaaaa-bbbb-cccc-1111-222222222222 \
--scope /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/your-resource-group-name \
--role "Storage Blob Data Contributor"
Per informazioni sull'assegnazione di autorizzazioni a livello di risorsa o sottoscrizione tramite l'interfaccia della riga di comando di Azure, vedere l'articolo Assegnare ruoli di Azure usando l'interfaccia della riga di comando di Azure.
3 - Implementare DefaultAzureCredential nell'applicazione
Quando il codice è in esecuzione in Azure e l'identità gestita è stata abilitata nella risorsa di Azure che ospita l'app, il DefaultAzureCredential
determina le credenziali da usare nell'ordine seguente:
- Controllare l'ambiente per un'entità servizio come definito dalle variabili di ambiente
AZURE_CLIENT_ID
,AZURE_TENANT_ID
eAZURE_CLIENT_SECRET
oAZURE_CLIENT_CERTIFICATE_PATH
e (facoltativamente)AZURE_CLIENT_CERTIFICATE_PASSWORD
. - Verificare la variabile di ambiente
AZURE_CLIENT_ID
per ottenere l'ID client di un'identità gestita assegnata a un utente. - Usare l'identità gestita assegnata dal sistema per la risorsa di Azure, se abilitata.
In questo articolo viene usata l'identità gestita assegnata dal sistema per un'app Azure Container, quindi non è necessario configurare un'identità gestita nell'ambiente o passarla come parametro. I passaggi seguenti illustrano come usare DefaultAzureCredential
.
Aggiungere prima di tutto il pacchetto azidentity
all'applicazione.
go get github.com/Azure/azure-sdk-for-go/sdk/azidentity
Successivamente, per qualsiasi codice Go che crea un'istanza di un client Azure SDK nell'app, è necessario:
- Importare il pacchetto
azidentity
. - Creare un'istanza del tipo
DefaultAzureCredential
. - Passare l'istanza di tipo
DefaultAzureCredential
al costruttore del client Azure SDK.
Un esempio di questi passaggi è mostrato nel segmento di codice seguente con un client Blob di Azure Storage.
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)
const (
account = "https://<replace_with_your_storage_account_name>.blob.core.windows.net/"
containerName = "sample-container"
blobName = "sample-blob"
sampleFile = "path/to/sample/file"
)
func main() {
// create a credential
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
// TODO: handle error
}
// create a client for the specified storage account
client, err := azblob.NewClient(account, cred, nil)
if err != nil {
// TODO: handle error
}
// TODO: perform some action with the azblob Client
// _, err = client.DownloadFile(context.TODO(), <containerName>, <blobName>, <target_file>, <DownloadFileOptions>)
}
Come descritto nell'articolo panoramica dell'autenticazione di Azure SDK for Go, DefaultAzureCredential
supporta più metodi di autenticazione e determina il metodo di autenticazione usato in fase di esecuzione. Il vantaggio di questo approccio è che l'app può usare metodi di autenticazione diversi in ambienti diversi senza implementare codice specifico dell'ambiente. Quando il codice precedente viene eseguito nella workstation durante lo sviluppo locale, DefaultAzureCredential
userà un'entità servizio dell'applicazione determinata dalle impostazioni dell'ambiente oppure utilizzando le credenziali dello strumento di sviluppo per l'autenticazione con altre risorse di Azure. Di conseguenza, lo stesso codice può essere usato per autenticare l'app nelle risorse di Azure durante lo sviluppo locale e quando viene distribuito in Azure.
Importante
DefaultAzureCredential
semplifica l'autenticazione durante lo sviluppo di applicazioni distribuite in Azure combinando le credenziali usate negli ambienti di hosting di Azure e le credenziali usate nello sviluppo locale. Nell'ambiente di produzione è preferibile usare un tipo di credenziale specifico, in modo che l'autenticazione sia più prevedibile e più semplice da eseguire.
4 - Implementare ManagedIdentityCredential nell'applicazione
I passaggi per l'implementazione di ManagedIdentityCredential
sono gli stessi di quelli per l'uso del tipo DefaultAzureCredential
.
Aggiungere prima di tutto il pacchetto azidentity
all'applicazione.
go get github.com/Azure/azure-sdk-for-go/sdk/azidentity
Successivamente, per ogni codice Go che crea un'istanza di un client Azure SDK nella tua app, è necessario:
- Importare il pacchetto
azidentity
. - Creare un'istanza di tipo
ManagedIdentityCredential
. - Passare l'istanza di tipo
ManagedIdentityCredential
al costruttore del client SDK di Azure.
Un esempio di questi passaggi è illustrato nel segmento di codice seguente con un client di archiviazione di Blob di Azure.
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)
const (
account = "https://<replace_with_your_storage_account_name>.blob.core.windows.net/"
containerName = "sample-container"
blobName = "sample-blob"
sampleFile = "path/to/sample/file"
)
func main() {
// create a credential
cred, err := azidentity.NewManagedIdentityCredential(nil)
// When using User Assigned Managed Identity use this instead and pass your client id in the options
// clientID := azidentity.ClientID("abcd1234-...")
// opts := azidentity.ManagedIdentityCredentialOptions{ID: clientID}
// cred, err := azidentity.NewManagedIdentityCredential(&opts)
if err != nil {
// TODO: handle error
}
// create a client for the specified storage account
client, err := azblob.NewClient(account, cred, nil)
if err != nil {
// TODO: handle error
}
// TODO: perform some action with the azblob Client
// _, err = client.DownloadFile(context.TODO(), <containerName>, <blobName>, <target_file>, <DownloadFileOptions>)
}