Erstellen und Bereitstellen einer Django-Web-App in Azure mit einer benutzerseitig zugewiesenen verwalteten Identität
In diesem Tutorial stellen Sie eine Django Web-App für Azure App Services bereit. Die Web-App verwendet eine vom Benutzer zugewiesene verwaltete Identität (passwortlose Verbindungen) mit rollenbasierter Zugriffssteuerung von Azure für den Zugriff auf Azure Storage und Azure Datenbank for PostgreSQL - Flexible Server Ressourcen. Der Code verwendet die DefaultAzureCredential- Klasse der Azure Identity Client-Bibliothek für Python. Die DefaultAzureCredential
-Klasse erkennt automatisch, dass eine verwaltete Identität für den App Service existiert und verwendet diese für den Zugriff auf andere Azure Ressourcen.
In diesem Tutorial erstellen Sie eine vom Benutzer zugewiesene verwaltete Identität und weisen sie dem App Service zu, damit dieser auf die Ressourcen des Datenbank- und Storage-Kontos zugreifen kann. Ein Beispiel für die Verwendung einer vom System zugewiesenen verwalteten Identität finden Sie unter Erstellen und Bereitstellen einer Flask Python Web-App in Azure mit einer vom System zugewiesenen verwalteten Identität. Vom Benutzer zugewiesene verwaltete Identitäten sind empfehlenswert, da sie von mehreren Ressourcen verwendet werden können und ihre Lebenszyklen von den Lebenszyklen der Ressourcen, mit denen sie verknüpft sind, entkoppelt sind. Weitere Informationen über bewährte Verfahren für die Verwendung verwalteter Identitäten finden Sie unter Empfehlungen für bewährte Verfahren für verwaltete Identitäten.
Dieses Tutorial zeigt Ihnen, wie Sie die Python Web-App bereitstellen und Azure-Ressourcen mit Hilfe des Azure CLI erstellen. Die Befehle in diesem Tutorial sind so geschrieben, dass sie in einer Bash-Shell ausgeführt werden können. Sie können die Befehle des Tutorials in jeder Bash-Umgebung ausführen, in der das CLI installiert ist, wie z. B. in Ihrer lokalen Umgebung oder in der Azure Cloud Shell. Mit einigen Modifikationen - z. B. dem Festlegen und Verwenden von Umgebungsvariablen - können Sie diese Befehle auch in anderen Umgebungen wie der Windows Command Shell ausführen.
Abrufen der Beispiel-App
Verwenden Sie die Django-Beispielanwendung, um diesem Tutorial zu folgen. Laden Sie die Beispielanwendung herunter oder klonen Sie sie in Ihre Entwicklungsumgebung.
Klonen Sie das Beispiel.
git clone https://github.com/Azure-Samples/msdocs-django-web-app-managed-identity.git
Navigieren Sie zu dem Anwendungsordner.
cd msdocs-django-web-app-managed-identity
Untersuchen Sie den Code für die Authentifizierung
Die Beispiel-Web-App muss sich bei zwei verschiedenen Datenspeichern authentifizieren:
- Azure Blob Storage Server, auf dem sie die von den Prüfern gesendeten Fotos speichert und abruft.
- Eine Azure Datenbank for PostgreSQL - Flexible Server Datenbank, in der sie Restaurants und Bewertungen speichert.
Sie verwendet DefaultAzureCredential, um sich bei beiden Datenspeichern zu authentifizieren. Mit DefaultAzureCredential
kann die App so konfiguriert werden, dass sie je nach Umgebung, in der sie ausgeführt wird, unter der Identität verschiedener Dienstprinzipale ausgeführt wird, ohne dass Änderungen am Code vorgenommen werden müssen. In einer lokalen Entwicklungsumgebung kann die App beispielsweise unter der Identität des Entwicklers ausgeführt werden, der bei der Azure CLI angemeldet ist, während sie in Azure, wie in diesem Tutorial, unter einer vom Benutzer zugewiesenen verwalteten Identität ausgeführt werden kann.
In beiden Fällen muss das Sicherheitsprinzipal, unter dem die App ausgeführt wird, über eine Rolle für jede von der App verwendete Azure-Ressource verfügen, die es ihr erlaubt, die von der App benötigten Aktionen auf der Ressource durchzuführen. In diesem Tutorial erstellen Sie mithilfe von Azure CLI-Befehlen eine vom Benutzer zugewiesene verwaltete Identität und weisen sie Ihrer App in Azure zu. Anschließend weisen Sie dieser Identität manuell entsprechende Rollen auf Ihrem Azure Storage-Konto und Azure Datenbank for PostgreSQL Server zu. Schließlich legen Sie die Umgebungsvariable AZURE_CLIENT_ID
für Ihre App in Azure fest, um DefaultAzureCredential
für die Verwendung der verwalteten Identität zu konfigurieren.
Nachdem die vom Benutzer zugewiesene verwaltete Identität auf Ihrer App und ihrer Runtime-Umgebung konfiguriert ist und ihr die entsprechenden Rollen auf den Datenspeichern zugewiesen wurden, können Sie DefaultAzureCredential
verwenden, um sich bei den erforderlichen Ressourcen in Azure zu authentifizieren.
Mit dem folgenden Code erstellen Sie einen Blob-Storage Client zum Hochladen von Fotos in ./restaurant_review/views.py
. Dem Client wird eine Instanz von DefaultAzureCredential
zur Verfügung gestellt, über die er Zugriffstoken erhält, um Vorgänge gegen Azure Storage durchzuführen.
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)
Eine Instanz von DefaultAzureCredential
wird auch verwendet, um einen Zugriffstoken für die Azure Datenbank for PostgreSQL in ./azureproject/get_conn.py
zu erhalten. In diesem Fall wird das Token direkt erworben, indem Sie get_token auf der Anmeldeinformation-Instanz aufrufen und den entsprechenden scope
-Wert übergeben. Das Token wird dann zum Festlegen des Kennworts in der PostgreSQL-Verbindungs-URI verwendet.
azure_credential = DefaultAzureCredential()
token = azure_credential.get_token("https://ossrdbms-aad.database.windows.net")
conf.settings.DATABASES['default']['PASSWORD'] = token.token
Mehr über die Authentifizierung Ihrer Apps bei Azure Services erfahren Sie unter Authentifizierung von Python-Apps bei Azure Services mit dem Azure SDK für Python. Um mehr über DefaultAzureCredential
zu erfahren, einschließlich der Anpassung der Anmeldeinformationen, die für Ihre Umgebung ausgewertet werden, siehe DefaultAzureCredential Übersicht.
Flexiblen Azure-PostgreSQL-Server erstellen
Legen Sie die Umgebungsvariablen fest, die Sie für das Tutorial benötigen.
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"
Wichtig
Die
ADMIN_PW
muss 8 bis 128 Zeichen aus drei der folgenden Kategorien enthalten: Englische Großbuchstaben, englische Kleinbuchstaben, Zahlen und nicht alphanumerische Zeichen. Verwenden Sie beim Erstellen von Benutzernamen oder Kennwörtern nicht das Zeichen$
. Später erstellen Sie Umgebungsvariablen mit diesen Werten. Dabei hat das Zeichen$
innerhalb des Linux-Containers, der zum Ausführen von Python-Apps verwendet wird, eine besondere Bedeutung.Erstellen Sie mithilfe des Befehls az group create eine Ressourcengruppe.
az group create --location $LOCATION --name $RESOURCE_GROUP_NAME
Erstellen Sie einen PostgreSQL flexible server mit dem Befehl az postgres flexible-server create. (Dieser und die folgenden Befehle verwenden das Zeilenfortsetzungszeichen für die Bash Shell („\“). Ändern Sie das Zeilenfortsetzungszeichen für andere Shells.)
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
Der SKU-Name ist der Name der Preisstufe und der Rechenkonfiguration. Weitere Informationen finden Sie unter Azure Database for PostgreSQL – Preise. Um die verfügbaren SKUs aufzulisten, verwenden Sie
az postgres flexible-server list-skus --location $LOCATION
.Fügen Sie Ihr Azure-Konto als Microsoft Entra-Admin für den Server mit dem Befehl az postgres flexible-server ad-admin create hinzu.
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
Konfigurieren Sie eine Firewall-Regel auf Ihrem Server mit dem Befehl az postgres flexible-server firewall-rule create. Diese Regel bietet Ihrer lokalen Umgebung die Möglichkeit, auf den Server zuzugreifen. (Wenn Sie die Azure Cloud Shell verwenden, können Sie diesen Schritt überspringen).
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
Verwenden Sie ein beliebiges Tool oder eine Website, die Ihre IP-Adresse anzeigt, um
<your IP>
in dem Befehl zu ersetzen. Sie können zum Beispiel die Website Was ist meine IP-Adresse? verwenden.Erstellen Sie eine Datenbank namens
restaurant
mit dem Befehl 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;'
Azure App Service erstellen und den Code bereitstellen
Führen Sie diese Befehle im Root-Ordner der Beispiel-App aus, um einen App Service zu erstellen und den Code dafür bereitzustellen.
Erstellen Sie einen App Service mit dem Befehl az webapp up.
az webapp up \ --resource-group $RESOURCE_GROUP_NAME \ --location $LOCATION \ --name $APP_SERVICE_NAME \ --runtime PYTHON:3.9 \ --sku B1
Die sku definiert die Größe (CPU, Speicher) und die Kosten des App Service-Plans. Für den Plan B1 (Basic) fallen in Ihrem Azure-Abonnement geringe Kosten an. Eine vollständige Liste der App Service-Pläne finden Sie auf der Seite App Service – Preise.
Konfigurieren Sie den App Service so, dass er die start.sh im Beispiel-Repo mit dem Befehl az webapp config set verwendet.
az webapp config set \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --startup-file "start.sh"
Erstellen eines Speicherkontos und Containers
Die Beispiel-App sendet die Fotos der Reviewer als Blob-Storage in Azure Storage.
Wenn ein Benutzer ein Foto mit seiner Bewertung sendet, schreibt die Beispiel-App das Image in den Container und verwendet dabei die verwaltete Identität und
DefaultAzureCredential
für den Zugriff auf das Storage-Konto.Wenn ein Benutzer die Bewertungen für ein Restaurant anschaut, gibt die App für jede Bewertung, der ein Foto zugeordnet ist, einen Link zu dem Foto im Blob-Storage zurück. Damit der Browser das Foto anzeigen kann, muss er auf das Foto in Ihrem Storage-Konto zugreifen können. Die Blob-Daten müssen durch anonymen (nicht authentifizierten) Zugriff öffentlich zum Lesen verfügbar sein.
In diesem Abschnitt erstellen Sie ein Storage-Konto und einen Container, der den öffentlichen Lesezugriff auf Blobs im Container ermöglicht. In späteren Abschnitten erstellen Sie eine vom Benutzer zugewiesene verwaltete Identität und konfigurieren sie so, dass sie Blobs in das Storage-Konto schreibt.
Verwenden Sie den Befehl az storage create, um ein Storage-Konto zu erstellen.
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
Erstellen Sie im Storage-Konto mit dem Befehl az storage container create einen Container namens photos.
az storage container create \ --account-name $STORAGE_ACCOUNT_NAME \ --name photos \ --public-access blob \ --auth-mode login
Hinweis
Wenn der Befehl fehlschlägt, z. B. wenn Sie eine Fehlermeldung erhalten, dass die Anfrage möglicherweise durch die Netzwerkregeln des Storage-Kontos blockiert wird, geben Sie den folgenden Befehl ein, um sicherzustellen, dass Ihrem Azure-Benutzer-Konto eine Azure-Rolle mit der Berechtigung zum Erstellen eines Containers zugewiesen ist.
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"
Weitere Informationen finden Sie unter Schnellstart: Erstellen, Herunterladen und Auflisten von Blobs mit Azure CLI. Beachten Sie, dass mehrere Azure-Rollen es Ihnen erlauben, Container in einem Storage-Konto zu erstellen, darunter „Besitzer“, „Mitwirkender“, „Storage Blob Data Besitzer“ und „Storage Blob Data Mitwirkender“.
Erstellen einer benutzerseitig zugewiesenen verwalteten Identität
Erstellen Sie eine vom Benutzer zugewiesene verwaltete Identität und weisen Sie diese dem App Service zu. Die verwaltete Identität wird für den Zugriff auf die Datenbank und das Storage-Konto verwendet.
Verwenden Sie den Befehl az identity create, um eine vom Benutzer zugewiesene verwaltete Identität zu erstellen und die ID des Clients zur späteren Verwendung in eine Variable auszugeben.
UA_CLIENT_ID=$(az identity create --name $UA_NAME --resource-group $RESOURCE_GROUP_NAME --query clientId --output tsv) echo $UA_CLIENT_ID
Verwenden Sie den Befehl az account show, um die ID Ihres Abonnements abzurufen und in eine Variable auszugeben, aus der Sie die Ressourcen-ID der verwalteten Identität konstruieren können.
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
Weisen Sie die verwaltete Identität dem App Service mit dem Befehl az webapp identity assign zu.
export MSYS_NO_PATHCONV=1 az webapp identity assign \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --identities $RESOURCE_ID
Erstellen Sie App Service App-Einstellungen, die die Client ID der verwalteten Identität und andere Konfigurationsinformationen enthalten, mit dem Befehl 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
Die Beispiel-App verwendet Umgebungsvariablen (App-Einstellungen), um die Verbindungsinformationen für die Datenbank und das Storage-Konto festzulegen, aber diese Variablen enthalten keine Kennwörter. Stattdessen erfolgt die Authentifizierung passwortlos mit DefaultAzureCredential
.
Der Code der Beispiel-App verwendet den DefaultAzureCredential
-Klassenkonstruktor, ohne die vom Benutzer zugewiesene verwaltete Identität Client ID an den Konstruktor zu übergeben. In diesem Szenario wird nach der Umgebungsvariablen AZURE_CLIENT_ID
gesucht, die Sie als App-Einstellung festgelegt haben.
Wenn die AZURE_CLIENT_ID
-Umgebungsvariable nicht vorhanden ist, wird die vom System zugewiesene verwaltete Identität verwendet, sofern sie konfiguriert ist. Weitere Informationen finden Sie unter Einführung in DefaultAzureCredential.
Rollen für die verwaltete Identität erstellen
In diesem Abschnitt erstellen Sie Rollenzuweisungen für die verwaltete Identität, um den Zugriff auf das Storage-Konto und die Datenbank zu ermöglichen.
Erstellen Sie eine Rollenzuweisung für die verwaltete Identität, um den Zugriff auf das Storage-Konto mit dem Befehl az role assignment create zu ermöglichen.
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"
Der Befehl gibt den Bereich der Rollenzuweisung für die Ressourcengruppe an. Weitere Informationen finden Sie unter Rollenzuweisungen verstehen.
Verwenden Sie den Befehl az postgres flexible-server execute, um sich mit der Postgres-Datenbank zu verbinden und die gleichen Befehle auszuführen, um der verwalteten Identität Rollen zuzuweisen.
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);"
Wenn Sie Probleme haben, den Befehl auszuführen, vergewissern Sie sich, dass Sie Ihr Benutzerkonto als Microsoft Entra Admin für den PosgreSQL-Server hinzugefügt haben und dass Sie in den Firewall-Regeln den Zugriff auf Ihre IP-Adresse zugelassen haben. Weitere Informationen finden Sie unter Erstellen eines flexiblen Azure PostgreSQL-Servers.
Python-Web-App in Azure testen
Die Beispiel-Python App verwendet das azure.identity-Paket und seine DefaultAzureCredential
-Klasse. Wenn die App in Azure ausgeführt wird, erkennt DefaultAzureCredential
automatisch, ob eine verwaltete Identität für den App Service vorhanden ist und verwendet diese gegebenenfalls für den Zugriff auf andere Azure Ressourcen (in diesem Fall Storage und PostgreSQL). Sie müssen dem App Service keine Storage-Schlüssel, Zertifikate oder Anmeldeinformationen zur Verfügung stellen, um auf diese Ressourcen zuzugreifen.
Navigieren Sie zu der bereitgestellten Anwendung unter der URL
http://$APP_SERVICE_NAME.azurewebsites.net
.Es kann ein oder zwei Minuten dauern, bis die App gestartet ist. Wenn Sie eine Standardseite der App sehen, die nicht die Standardseite der Beispielanwendung ist, warten Sie eine Minute und aktualisieren Sie den Browser.
Testen Sie die Funktionalität der Beispiel-App, indem Sie ein Restaurant und einige Bewertungen mit Fotos für das Restaurant hinzufügen.
Die Restaurant- und Bewertungsinformationen werden in Azure Datenbank for PostgreSQL gespeichert und die Fotos werden in Azure Storage gespeichert. Hier ist ein Beispiel-Screenshot:
Bereinigung
In diesem Tutorial wurden alle Azure-Ressourcen in derselben Ressourcengruppe erstellt. Das Entfernen der Ressourcengruppe mit dem Befehl Az-Gruppe löschen entfernt alle Ressourcen in der Ressourcengruppe und ist der schnellste Weg, um alle für Ihre App verwendeten Azure-Ressourcen zu entfernen.
az group delete --name $RESOURCE_GROUP_NAME
Sie können optional das Argument --no-wait
hinzufügen, damit für den Befehl die Rückgabe erfolgen kann, bevor der Vorgang abgeschlossen ist.