Authentifizieren bei Azure-Ressourcen mit lokal gehosteten Python-Apps

Apps, die außerhalb von Azure (z. B. lokal oder in einem Rechenzentrum eines Drittanbieters) gehostet werden, sollten einen Anwendungsdienstprinzipal verwenden, um sich beim Zugriff auf Azure-Ressourcen bei Azure zu authentifizieren. Anwendungsdienstprinzipalobjekte werden mithilfe des App-Registrierungsprozesses in Azure erstellt. Wenn ein Anwendungsdienstprinzipal erstellt wird, werden eine Client-ID und ein geheimer Clientschlüssel für Ihre App generiert. Die Client-ID, der geheime Clientschlüssel und Ihre Mandanten-ID werden dann in Umgebungsvariablen gespeichert, damit sie vom Azure SDK für Python verwendet werden können, um Ihre App zur Laufzeit bei Azure zu authentifizieren.

Für jede Umgebung, in der die App gehostet wird, sollte eine andere App-Registrierung erstellt werden. Dadurch können umgebungsspezifische Ressourcenberechtigungen für jeden Dienstprinzipal konfiguriert werden und sichergestellt werden, dass eine in einer Umgebung bereitgestellte App nicht mit Azure-Ressourcen spricht, die Teil einer anderen Umgebung sind.

1 - Registrieren der Anwendung in Azure AD

Eine App kann entweder mit dem Azure-Portal oder der Azure CLI bei Azure registriert werden.

az ad sp create-for-rbac --name <app-name>

Der Befehl gibt eine Ausgabe ähnlich der folgenden zurück: Notieren Sie sich diese Werte, oder lassen Sie dieses Fenster geöffnet, da Sie diese Werte in den nächsten Schritten benötigen und den Wert des Kennworts (geheimer Clientschlüssel) nicht erneut anzeigen können.

{
  "appId": "00000000-0000-0000-0000-000000000000",
  "displayName": "msdocs-python-sdk-auth-prod",
  "password": "abcdefghijklmnopqrstuvwxyz",
  "tenant": "33333333-3333-3333-3333-333333333333"
}

2: Zuweisen von Rollen zum Anwendungsdienstprinzipal

Als Nächstes müssen Sie bestimmen, welche Rollen (Berechtigungen) Ihre App für welche Ressourcen benötigt, und diese Rollen Ihrer App zuweisen. Rollen können in einem Ressourcen-, Ressourcengruppen- oder Abonnementbereich eine Rolle zugewiesen werden. In diesem Beispiel wird gezeigt, wie Rollen für den Dienstprinzipal im Ressourcengruppenbereich zugewiesen werden, da die meisten Anwendungen alle ihre Azure-Ressourcen in einer einzelnen Ressourcengruppe gruppieren.

Einem Anwendungsdienstprinzipal wird mithilfe des Befehls az role assignment create eine Rolle in Azure zugewiesen.

az role assignment create --assignee {appId} \
    --scope /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName} \
    --role "{roleName}" 

Verwenden Sie den Befehl az role definition list , um die Rollennamen abzurufen, denen ein Dienstprinzipal zugewiesen werden kann.

az role definition list \
    --query "sort_by([].{roleName:roleName, description:description}, &roleName)" \
    --output table

Um beispielsweise den Dienstprinzipal mit der appId von 00000000-0000-0000-0000-000000000000 Lese-, Schreib- und Löschzugriff auf Azure Storage-Blobcontainer und -Daten in allen Speicherkonten in der Msdocs-python-sdk-auth-beispiel-Ressourcengruppe im Abonnement mit ID 11111111-1111-1111-1111-111111111111zuzulassen, würden Sie den Anwendungsdienstprinzipal der Rolle "Storage Blob Data Contributor " mit dem folgenden Befehl zuweisen.

az role assignment create --assignee 00000000-0000-0000-0000-000000000000 \
    --scope /subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/msdocs-python-sdk-auth-example \
    --role "Storage Blob Data Contributor"

Informationen zum Zuweisen von Berechtigungen auf Ressourcen- oder Abonnementebene mithilfe der Azure CLI finden Sie im Artikel Zuweisen von Azure-Rollen mithilfe der Azure CLI.

3. Konfigurieren von Umgebungsvariablen für die Anwendung

Sie müssen die AZURE_CLIENT_IDVariablen und AZURE_TENANT_IDAZURE_CLIENT_SECRET Umgebungsvariablen für den Prozess festlegen, der Ihre Python-App ausführt, um die Anmeldeinformationen des Anwendungsdienstprinzipals zur Laufzeit für Ihre App verfügbar zu machen. Das DefaultAzureCredential Objekt sucht nach den Dienstprinzipalinformationen in diesen Umgebungsvariablen.

Wenn Sie Gunicorn zum Ausführen von Python-Web-Apps in einer UNIX-Serverumgebung verwenden, können Umgebungsvariablen für eine App mithilfe der EnvironmentFile Direktive in der gunicorn.server Datei wie unten dargestellt angegeben angegeben werden.

[Unit]
Description=gunicorn daemon
After=network.target  
  
[Service]  
User=www-user
Group=www-data
WorkingDirectory=/path/to/python-app
EnvironmentFile=/path/to/python-app/py-env/app-environment-variables
ExecStart=/path/to/python-app/py-env/gunicorn --config config.py wsgi:app
            
[Install]  
WantedBy=multi-user.target

Die in der EnvironmentFile Direktive angegebene Datei sollte eine Liste von Umgebungsvariablen mit ihren Werten enthalten, wie unten dargestellt.

AZURE_CLIENT_ID=<value>
AZURE_TENANT_ID=<value>
AZURE_CLIENT_SECRET=<value>

4 - Implementieren von DefaultAzureCredential in Ihrer Anwendung

Um Azure SDK-Clientobjekte für Azure zu authentifizieren, sollte Ihre Anwendung die DefaultAzureCredential Klasse aus dem azure.identity Paket verwenden.

Fügen Sie zunächst das Azure.Identity-Paket zu Ihrer Anwendung hinzu.

pip install azure-identity

Als Nächstes sollten Sie für jeden Python-Code, der ein Azure SDK-Clientobjekt in Ihrer App erstellt, Folgendes ausführen:

  1. Importieren Sie die DefaultAzureCredential Klasse aus dem azure.identity Modul.
  2. Erstellen eines DefaultAzureCredential-Objekts
  3. Übergeben Sie das DefaultAzureCredential Objekt an den Azure SDK-Clientobjektkonstruktor.

Ein Beispiel dafür wird im folgenden Codeausschnitt gezeigt.

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

# Acquire a credential object
token_credential = DefaultAzureCredential()

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

Wenn der obige Code das DefaultAzureCredential Objekt instanziiert, DefaultAzureCredential liest die Umgebungsvariablen AZURE_TENANT_ID, AZURE_CLIENT_IDund AZURE_CLIENT_SECRET für die Anwendungsdienstprinzipalinformationen, mit der eine Verbindung mit Azure hergestellt werden soll.