Creare e distribuire un'app Web Django in Azure con un'identità gestita assegnata dall'utente

In questa esercitazione si distribuisce un'app Web Django nel servizio app Azure. L'app Web usa un'identità gestita assegnata dall'utente (connessioni senza password) con il controllo degli accessi in base al ruolo di Azure per accedere Archiviazione di Azure e Database di Azure per PostgreSQL - Risorse server flessibili. Il codice usa la classe DefaultAzureCredential della libreria client di Azure Identity per Python. La DefaultAzureCredential classe rileva automaticamente che esiste un'identità gestita per il servizio app e la usa per accedere ad altre risorse di Azure.

In questa esercitazione viene creata un'identità gestita assegnata dall'utente e assegnata all'servizio app in modo che possa accedere alle risorse del database e dell'account di archiviazione. Per un esempio di uso di un'identità gestita assegnata dal sistema, vedere Creare e distribuire un'app Web Python Flask in Azure con identità gestita assegnata dal sistema. Le identità gestite assegnate dall'utente sono consigliate perché possono essere usate da più risorse e i relativi cicli di vita vengono separati dai cicli di vita delle risorse a cui sono associati. Per altre informazioni sulle procedure consigliatejper l'uso delle identità gestite, vedere Raccomandazioni sulle procedure consigliate per le identità gestite.

Questa esercitazione illustra come distribuire l'app Web Python e creare risorse di Azure usando l'interfaccia della riga di comando di Azure. I comandi in questa esercitazione vengono scritti per l'esecuzione in una shell Bash. È possibile eseguire i comandi dell'esercitazione in qualsiasi ambiente Bash con l'interfaccia della riga di comando installata, ad esempio l'ambiente locale o Azure Cloud Shell. Con alcune modifiche, ad esempio l'impostazione e l'uso delle variabili di ambiente, è possibile eseguire questi comandi in altri ambienti, ad esempio la shell dei comandi di Windows.

Ottenere l'app di esempio

Usare l'applicazione di esempio Django di esempio per seguire questa esercitazione. Scaricare o clonare l'applicazione di esempio nell'ambiente di sviluppo.

  1. Clonare l'esempio.

    git clone https://github.com/Azure-Samples/msdocs-django-web-app-managed-identity.git
    
  2. Passare alla cartella dell'applicazione.

    cd msdocs-django-web-app-managed-identity
    

Esaminare il codice di autenticazione

L'app Web di esempio deve eseguire l'autenticazione in due archivi dati diversi:

  • Server di archiviazione BLOB di Azure in cui archivia e recupera le foto inviate dai revisori.
  • Un database server flessibile Database di Azure per PostgreSQL in cui vengono archiviati ristoranti e recensioni.

Usa DefaultAzureCredential per eseguire l'autenticazione in entrambi gli archivi dati. Con DefaultAzureCredential, l'app può essere configurata per l'esecuzione con l'identità di entità servizio diverse, a seconda dell'ambiente in cui è in esecuzione, senza apportare modifiche al codice. Ad esempio, in un ambiente di sviluppo locale, l'app può essere eseguita con l'identità dello sviluppatore che ha eseguito l'accesso all'interfaccia della riga di comando di Azure, mentre in Azure, come in questa esercitazione, può essere eseguita con un'identità gestita assegnata dall'utente.

In entrambi i casi, l'entità di sicurezza in cui viene eseguita l'app deve avere un ruolo in ogni risorsa di Azure usata dall'app che consente di eseguire le azioni sulla risorsa richiesta dall'app. In questa esercitazione si usano i comandi dell'interfaccia della riga di comando di Azure per creare un'identità gestita assegnata dall'utente e assegnarla all'app in Azure. Assegnare quindi manualmente i ruoli appropriati per l'identità nell'account di archiviazione di Azure e nel server Database di Azure per PostgreSQL. Infine, si imposta la variabile di ambiente per l'app AZURE_CLIENT_ID in Azure per configurare DefaultAzureCredential l'uso dell'identità gestita.

Dopo aver configurato l'identità gestita assegnata dall'utente nell'app e nel relativo ambiente di runtime e aver assegnato i ruoli appropriati negli archivi dati, è possibile usare DefaultAzureCredential per eseguire l'autenticazione con le risorse di Azure necessarie.

Il codice seguente viene usato per creare un client di archiviazione BLOB per caricare le foto in ./restaurant_review/views.py. Un'istanza di viene fornita al client, che usa per acquisire i token di DefaultAzureCredential accesso per eseguire operazioni sull'archiviazione di Azure.

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

azure_credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
    account_url=account_url,
    credential=azure_credential)

Un'istanza di viene usata anche per ottenere un token di DefaultAzureCredential accesso per Database di Azure per PostgreSQL in ./azureproject/get_conn.py. In questo caso, il token viene acquisito direttamente chiamando get_token nell'istanza delle credenziali e passando il valore appropriato scope . Il token viene quindi usato per impostare la password nell'URI di connessione PostgreSQL.

azure_credential = DefaultAzureCredential()
token = azure_credential.get_token("https://ossrdbms-aad.database.windows.net")
conf.settings.DATABASES['default']['PASSWORD'] = token.token

Per altre informazioni sull'autenticazione delle app con i servizi di Azure, vedere Autenticare le app Python nei servizi di Azure usando Azure SDK per Python. Per altre informazioni su DefaultAzureCredential, tra cui come personalizzare la catena di credenziali valutata per l'ambiente, vedere Panoramica di DefaultAzureCredential.

Creare un server flessibile di Azure PostgreSQL

  1. Configurare le variabili di ambiente necessarie per l'esercitazione.

    LOCATION="eastus"
    RAND_ID=$RANDOM
    RESOURCE_GROUP_NAME="msdocs-mi-web-app"
    APP_SERVICE_NAME="msdocs-mi-web-$RAND_ID"
    DB_SERVER_NAME="msdocs-mi-postgres-$RAND_ID"
    ADMIN_USER="demoadmin"
    ADMIN_PW="ChAnG33#ThsPssWD$RAND_ID"
    UA_NAME="UAManagedIdentityPythonTest$RAND_ID"
    

    Importante

    ADMIN_PW Deve contenere da 8 a 128 caratteri da tre delle categorie seguenti: lettere maiuscole, lettere minuscole, numeri e caratteri non alfanumerici. Quando si creano nomi utente o password non si usa il $ carattere . Successivamente, si creano variabili di ambiente con questi valori, in cui il carattere $ ha un significato speciale all'interno del contenitore Linux usato per eseguire le app Python.

  2. Creare un gruppo di risorse con il comando az group create.

    az group create --location $LOCATION --name $RESOURCE_GROUP_NAME
    
  3. Creare un server flessibile PostgreSQL con il comando az postgres flexible-server create . (Questo e i comandi successivi usano il carattere di continuazione della riga per la shell Bash ('\'). Modificare il carattere di continuazione della riga per altre shell.

    az postgres flexible-server create \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $DB_SERVER_NAME \
      --location $LOCATION \
      --admin-user $ADMIN_USER \
      --admin-password $ADMIN_PW \
      --sku-name Standard_D2ds_v4 \
      --active-directory-auth Enabled \
      --public-access 0.0.0.0
    

    Sku-name è il nome del piano tariffario e della configurazione di calcolo. Per altre informazioni, vedere Piano tariffario di Database di Azure per PostgreSQL. Per elencare gli SKU disponibili, usare az postgres flexible-server list-skus --location $LOCATION.

  4. Aggiungere l'account Azure come amministratore di Microsoft Entra per il server con il comando az postgres flexible-server ad-admin create .

    ACCOUNT_EMAIL=$(az ad signed-in-user show --query userPrincipalName --output tsv)
    ACCOUNT_ID=$(az ad signed-in-user show --query id --output tsv)
    echo $ACCOUNT_EMAIL, $ACCOUNT_ID
    az postgres flexible-server ad-admin create \
      --resource-group $RESOURCE_GROUP_NAME \
      --server-name $DB_SERVER_NAME \
      --display-name $ACCOUNT_EMAIL \
      --object-id $ACCOUNT_ID \
      --type User
    
  5. Configurare una regola del firewall nel server con il comando az postgres flexible-server firewall-rule create . Questa regola consente all'ambiente locale di connettersi al server. Se si usa Azure Cloud Shell, è possibile ignorare questo passaggio.

    IP_ADDRESS=<your IP>
    az postgres flexible-server firewall-rule create \
       --resource-group $RESOURCE_GROUP_NAME \
       --name $DB_SERVER_NAME \
       --rule-name AllowMyIP \
       --start-ip-address $IP_ADDRESS \
       --end-ip-address $IP_ADDRESS
    

    Usare qualsiasi strumento o sito Web che mostri l'indirizzo IP da sostituire <your IP> nel comando. Ad esempio, è possibile usare il sito Web What's My IP Address? (Indirizzo IP personale).

  6. Creare un database denominato restaurant usando il comando az postgres flexible-server execute .

    az postgres flexible-server execute \
      --name $DB_SERVER_NAME \
      --admin-user $ADMIN_USER \
      --admin-password $ADMIN_PW \
      --database-name postgres \
      --querytext 'create database restaurant;'
    

Creare un servizio app Azure e distribuire il codice

Eseguire questi comandi nella cartella radice dell'app di esempio per creare un servizio app e distribuirvi il codice.

  1. Creare un servizio app usando il comando az webapp up .

    az webapp up \
      --resource-group $RESOURCE_GROUP_NAME \
      --location $LOCATION \
      --name $APP_SERVICE_NAME \
      --runtime PYTHON:3.9 \
      --sku B1
    

    Lo SKU definisce le dimensioni (CPU, memoria) e il costo del piano di servizio app. Il piano di servizio B1 (Basic) comporta un costo ridotto nella sottoscrizione di Azure. Per un elenco completo dei piani del Servizio app, visualizzare la pagina Prezzi del Servizio app.

  2. Configurare servizio app per usare il start.sh nel repository di esempio con il comando az webapp config set.

    az webapp config set \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $APP_SERVICE_NAME \
      --startup-file "start.sh"
    

Creare un account di archiviazione e un contenitore

L'app di esempio archivia le foto inviate dai revisori come BLOB in Archiviazione di Azure.

  • Quando un utente invia una foto con la revisione, l'app di esempio scrive l'immagine nel contenitore usando l'identità gestita e DefaultAzureCredential per accedere all'account di archiviazione.

  • Quando un utente visualizza le recensioni per un ristorante, l'app restituisce un collegamento alla foto nell'archivio BLOB per ogni recensione associata. Affinché il browser visualizzi la foto, deve essere in grado di accedervi nell'account di archiviazione. I dati BLOB devono essere disponibili per la lettura pubblica tramite l'accesso anonimo (non autenticato).

In questa sezione viene creato un account di archiviazione e un contenitore che consente l'accesso in lettura pubblico ai BLOB nel contenitore. Nelle sezioni successive viene creata un'identità gestita assegnata dall'utente e configurata per scrivere BLOB nell'account di archiviazione.

  1. Usare il comando az storage create per creare un account di archiviazione.

    STORAGE_ACCOUNT_NAME="msdocsstorage$RAND_ID"
    az storage account create \
      --name $STORAGE_ACCOUNT_NAME \
      --resource-group $RESOURCE_GROUP_NAME \
      --location $LOCATION \
      --sku Standard_LRS \
      --allow-blob-public-access true
    
  2. Creare un contenitore denominato photos nell'account di archiviazione con il comando az storage container create .

    az storage container create \
      --account-name $STORAGE_ACCOUNT_NAME \
      --name photos \
      --public-access blob \
      --auth-mode login
    

    Nota

    Se il comando non riesce, ad esempio, se viene visualizzato un errore che indica che la richiesta potrebbe essere bloccata dalle regole di rete dell'account di archiviazione, immettere il comando seguente per assicurarsi che all'account utente di Azure sia assegnato un ruolo di Azure con l'autorizzazione per creare un contenitore.

    az role assignment create --role "Storage Blob Data Contributor" --assignee $ACCOUNT_EMAIL --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"
    

    Per altre informazioni, vedere Avvio rapido: Creare, scaricare ed elencare BLOB con l'interfaccia della riga di comando di Azure. Si noti che diversi ruoli di Azure consentono di creare contenitori in un account di archiviazione, tra cui "Proprietario", "Collaboratore", "Proprietario dei dati BLOB di archiviazione" e "Collaboratore ai dati dei BLOB di archiviazione".

Creare un'identità gestita assegnata dall'utente

Creare un'identità gestita assegnata dall'utente e assegnarla al servizio app. L'identità gestita viene usata per accedere al database e all'account di archiviazione.

  1. Usare il comando az identity create per creare un'identità gestita assegnata dall'utente e restituire l'ID client a una variabile per un uso successivo.

    UA_CLIENT_ID=$(az identity create --name $UA_NAME --resource-group $RESOURCE_GROUP_NAME --query clientId --output tsv)
    echo $UA_CLIENT_ID
    
  2. Usare il comando az account show per ottenere l'ID sottoscrizione e restituirlo in una variabile che può essere usata per costruire l'ID risorsa dell'identità gestita.

    SUBSCRIPTION_ID=$(az account show --query id --output tsv)
    RESOURCE_ID="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$UA_NAME"
    echo $RESOURCE_ID
    
  3. Assegnare l'identità gestita al servizio app con il comando az webapp identity assign.

    export MSYS_NO_PATHCONV=1
    az webapp identity assign \
        --resource-group $RESOURCE_GROUP_NAME \
        --name $APP_SERVICE_NAME \
        --identities $RESOURCE_ID
    
  4. Creare servizio app impostazioni dell'app che contengono l'ID client dell'identità gestita e altre informazioni di configurazione con il comando az webapp config appsettings set.

    az webapp config appsettings set \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $APP_SERVICE_NAME \
      --settings AZURE_CLIENT_ID=$UA_CLIENT_ID \
        STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT_NAME \
        STORAGE_CONTAINER_NAME=photos \
        DBHOST=$DB_SERVER_NAME \
        DBNAME=restaurant \
        DBUSER=$UA_NAME
    

L'app di esempio usa variabili di ambiente (impostazioni dell'app) per definire le informazioni di connessione per il database e l'account di archiviazione, ma queste variabili non includono password. L'autenticazione viene invece eseguita senza password con DefaultAzureCredential.

Il codice dell'app di esempio usa il costruttore della DefaultAzureCredential classe senza passare l'ID client dell'identità gestita assegnata dall'utente al costruttore. In questo scenario, il fallback consiste nel verificare la presenza della AZURE_CLIENT_ID variabile di ambiente impostata come impostazione dell'app.

Se la AZURE_CLIENT_ID variabile di ambiente non esiste, se configurata viene usata l'identità gestita assegnata dal sistema. Per altre informazioni, vedere Introduzione a DefaultAzureCredential.

Creare ruoli per l'identità gestita

In questa sezione vengono create assegnazioni di ruolo per l'identità gestita per abilitare l'accesso all'account di archiviazione e al database.

  1. Creare un'assegnazione di ruolo per l'identità gestita per abilitare l'accesso all'account di archiviazione con il comando az role assignment create .

    export MSYS_NO_PATHCONV=1
    az role assignment create \
    --assignee $UA_CLIENT_ID \
    --role "Storage Blob Data Contributor" \
    --scope "/subscriptions/$SUBSCRIPTION_ID/resourcegroups/$RESOURCE_GROUP_NAME"
    

    Il comando specifica l'ambito dell'assegnazione di ruolo al gruppo di risorse. Per altre informazioni, vedere Informazioni sulle assegnazioni di ruolo.

  2. Usare il comando az postgres flexible-server execute per connettersi al database Postgres ed eseguire gli stessi comandi per assegnare ruoli all'identità gestita.

    ACCOUNT_EMAIL_TOKEN=$(az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken)
    az postgres flexible-server execute \
      --name $DB_SERVER_NAME \
      --admin-user $ACCOUNT_EMAIL \
      --admin-password $ACCOUNT_EMAIL_TOKEN \
      --database-name postgres \
      --querytext "select * from pgaadauth_create_principal('"$UA_NAME"', false, false);select * from pgaadauth_list_principals(false);"
    

    In caso di problemi durante l'esecuzione del comando, assicurarsi di aver aggiunto l'account utente come amministratore di Microsoft Entra per il server PosgreSQL e di aver consentito l'accesso all'indirizzo IP nelle regole del firewall. Per altre informazioni, vedere la sezione Creare un server flessibile di Azure PostgreSQL.

Testare l'app Web Python in Azure

L'app Python di esempio usa il pacchetto azure.identity e la relativa DefaultAzureCredential classe. Quando l'app è in esecuzione in Azure, DefaultAzureCredential rileva automaticamente se esiste un'identità gestita per il servizio app e, in tal caso, la usa per accedere ad altre risorse di Azure (archiviazione e PostgreSQL in questo caso). Non è necessario fornire chiavi di archiviazione, certificati o credenziali al servizio app per accedere a queste risorse.

  1. Passare all'applicazione distribuita nell'URL http://$APP_SERVICE_NAME.azurewebsites.net.

    L'avvio dell'app può richiedere un minuto o due. Se viene visualizzata una pagina dell'app predefinita che non è la pagina predefinita dell'app di esempio, attendere un minuto e aggiornare il browser.

  2. Testare la funzionalità dell'app di esempio aggiungendo un ristorante e alcune recensioni con foto per il ristorante.

    Le informazioni sul ristorante e sulla revisione vengono archiviate in Database di Azure per PostgreSQL e le foto vengono archiviate in Archiviazione di Azure. Ecco uno screenshot di esempio:

    Screenshot dell'app di esempio che mostra la funzionalità di revisione del ristorante usando app Azure Servizio, Azure Postgre database SQL e Archiviazione di Azure.

Eseguire la pulizia

In questa esercitazione tutte le risorse di Azure sono state create nello stesso gruppo di risorse. La rimozione del gruppo di risorse rimuove con il comando az group delete rimuove tutte le risorse nel gruppo di risorse ed è il modo più rapido per rimuovere tutte le risorse di Azure usate per l'app.

az group delete  --name $RESOURCE_GROUP_NAME 

Facoltativamente, è possibile aggiungere l'argomento --no-wait per consentire al comando di tornare prima del completamento dell'operazione.

Passaggi successivi