Freigeben über


Authentifizieren von Python-Apps bei Azure-Diensten während der lokalen Entwicklung mithilfe von Dienstprinzipalen

Beim Erstellen von Cloudanwendungen müssen Entwickler ihre Apps häufig lokal ausführen und testen. Auch während der lokalen Entwicklung muss sich die Anwendung bei allen Azure-Diensten authentifizieren, mit denen sie interagiert. In diesem Artikel wird erläutert, wie dedizierte Dienstprinzipalidentitäten speziell für die Verwendung während der lokalen Entwicklung konfiguriert werden.

Ein Diagramm, das zeigt, wie eine App, die in einer lokalen Entwicklungsumgebung ausgeführt wird, den Anwendungsdienstprinzipal aus einer .env-Datei abruft und diese Identität dann verwendet, um eine Verbindung mit Azure-Ressourcen herzustellen.

Dedizierte Anwendungsdienstprinzipale für die lokale Entwicklung unterstützen das Prinzip der geringsten Berechtigungen, indem der Zugriff nur auf die Azure-Ressourcen beschränkt wird, die während der Entwicklung von der App benötigt werden. Durch die Verwendung eines dedizierten Anwendungsdienstprinzipals wird das Risiko des unbeabsichtigten Zugriffs auf andere Ressourcen reduziert und die Entstehung von Berechtigungsfehlern beim Übergang in die Produktion verhindert, wo umfassendere Berechtigungen zu Problemen führen könnten.

Bei der Registrierung von Anwendungen für die lokale Entwicklung in Azure wird folgendes empfohlen:

  • Erstellen Sie separate App-Registrierungen für jeden Entwickler: Dadurch erhält jeder Entwickler einen eigenen Dienstprinzipal, wodurch vermieden wird, dass Anmeldeinformationen geteilt werden müssen, und wodurch eine präzisere Zugriffssteuerung ermöglicht wird.
  • Erstellen Sie separate App-Registrierungen für jede Anwendung: Dadurch wird sichergestellt, dass jede App nur über die benötigten Berechtigungen verfügt, wodurch die potenzielle Angriffsfläche reduziert wird.

Um die Authentifizierung während der lokalen Entwicklung zu aktivieren, legen Sie Umgebungsvariablen mit den Anmeldeinformationen des Anwendungsdienstprinzipals fest. Das Azure SDK für Python erkennt diese Variablen und verwendet sie zum Authentifizieren von Anforderungen an Azure-Dienste.

1 - Registrieren der Anwendung in Azure AD

Anwendungsdienstprinzipalobjekte werden erstellt, wenn Sie eine App in Azure registrieren. Diese Registrierung kann entweder über das Azure-Portal oder die Azure CLI durchgeführt werden. Der Registrierungsprozess erstellt eine App-Registrierung in microsoft Entra ID (vormals Azure Active Directory) und generiert ein Dienstprinzipalobjekt für die App. Das Dienstprinzipalobjekt wird verwendet, um die App bei Azure-Diensten zu authentifizieren. Der App-Registrierungsprozess generiert auch einen geheimen Clientschlüssel (Kennwort) für die App. Dieser Geheimschlüssel wird verwendet, um die App bei Azure-Diensten zu authentifizieren. Der geheime Clientschlüssel wird nie in der Quellcodeverwaltung gespeichert, sondern in einer .env Datei im Anwendungsverzeichnis. Die .env Datei wird von der Anwendung zur Laufzeit gelesen, um Umgebungsvariablen festzulegen, die das Azure SDK für Python zum Authentifizieren der App verwendet. Die folgenden Schritte zeigen, wie Sie eine App in Azure registrieren und einen Dienstprinzipal für die App erstellen. Die Schritte werden sowohl für die Azure CLI als auch für das Azure-Portal angezeigt.

Azure CLI-Befehle können in der Azure Cloud Shell oder auf einer Workstation mit installierter Azure CLI ausgeführt werden.

Verwenden Sie zunächst den Befehl az ad sp create-for-rbac , um einen neuen Dienstprinzipal für die App zu erstellen. Der Befehl erstellt auch gleichzeitig die App-Registrierung für die App.

SERVICE_PRINCIPAL_NAME=<service-principal-name>
az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME

Die Ausgabe dieses Befehls ähnelt der folgenden. Notieren Sie sich diese Werte, oder lassen Sie dieses Fenster geöffnet, da Sie diese Werte für die nächsten Schritte benötigen und der Wert des Kennworts (Client-Secret) nicht erneut angezeigt wird. Sie können aber bei Bedarf später ein neues Kennwort hinzufügen, ohne den Dienstprinzipal oder vorhandene Kennwörter ungültig zu machen.

{
  "appId": "00001111-aaaa-2222-bbbb-3333cccc4444",
  "displayName": "<service-principal-name>",
  "password": "Ee5Ff~6Gg7.-Hh8Ii9Jj0Kk1Ll2Mm3_Nn4Oo5Pp6",
  "tenant": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
}

Als Nächstes müssen Sie den appID Wert abrufen und in einer Variablen speichern. Dieser Wert wird verwendet, um Umgebungsvariablen in Ihrer lokalen Entwicklungsumgebung festzulegen, damit sich das Azure SDK für Python mithilfe des Dienstprinzipals bei Azure authentifizieren kann.

APP_ID=$(az ad sp list \
  --all \
  --query "[?displayName=='$SERVICE_PRINCIPAL_NAME'].appId | [0]" \
  --output tsv)

2 – Erstellen einer Microsoft Entra-Sicherheitsgruppe für die lokale Entwicklung

Da in der Regel mehrere Entwickler an einer Anwendung arbeiten, wird empfohlen, eine Microsoft Entra-Sicherheitsgruppe zu erstellen, um die Rollen (Berechtigungen) einzuschließen, die die App bei der lokalen Entwicklung benötigt, anstatt die Rollen einzelnen Dienstprinzipalobjekten zuzuweisen. Dies bietet die folgenden Vorteile:

  • Jedem Entwickler wird sichergestellt, dass dieselben Rollen zugewiesen werden, da Rollen auf Gruppenebene zugewiesen werden.
  • Wenn eine neue Rolle für die App benötigt wird, muss sie nur der Microsoft Entra-Gruppe für die App hinzugefügt werden.
  • Wenn ein neuer Entwickler dem Team beitritt, wird ein neuer Anwendungsdienstprinzipal für den Entwickler erstellt und der Gruppe hinzugefügt, um zu sorgen, dass der Entwickler über die richtigen Berechtigungen für die Arbeit an der App verfügt.

Der Befehl az ad group create wird verwendet, um Sicherheitsgruppen in Microsoft Entra ID zu erstellen. Die --display-name- und --main-nickname-Parameter sind erforderlich. Der der Gruppe angegebene Name sollte auf dem Namen der Anwendung basieren. Es ist auch hilfreich, eine Zeichenfolge wie local-dev in den Namen der Gruppe aufzunehmen, um den Zweck der Gruppe anzugeben.

GROUP_DISPLAY_NAME="<group-name>"
GROUP_MAIL_NICKNAME="<group-mail-nickname>"
GROUP_DESCRIPTION="<group-description>"
az ad group create \
  --display-name $GROUP_DISPLAY_NAME \
  --mail-nickname $GROUP_MAIL_NICKNAME \
  --description $GROUP_DESCRIPTION

Zum Hinzufügen von Mitgliedern zur Gruppe benötigen Sie die Objekt-ID des Anwendungsdienstprinzipals, die sich von der Anwendungs-ID unterscheidet. Verwenden Sie die az ad sp list , um die verfügbaren Dienstprinzipale aufzulisten. Der --filter Parameterbefehl akzeptiert OData-Formatfilter und kann verwendet werden, um die Liste wie gezeigt zu filtern. Der --query Parameter beschränkt sich auf Spalten auf die von Interesse.

SP_OBJECT_ID=$(az ad sp list \
  --filter "startswith(displayName,'$GROUP_DISPLAY_NAME')" \
  --query "[0].id" \
  --output tsv)

Der Befehl az ad group member add kann dann verwendet werden, um Gruppen Mitglieder hinzuzufügen.

az ad group member add \
    --group $GROUP_DISPLAY_NAME \
    --member-id $SP_OBJECT_ID

Hinweis

Standardmäßig ist die Erstellung von Microsoft Entra-Sicherheitsgruppen auf bestimmte privilegierte Rollen in einem Verzeichnis beschränkt. Wenn Sie keine Gruppe erstellen können, wenden Sie sich an einen Administrator für Ihr Verzeichnis. Wenn Sie einer vorhandenen Gruppe keine Mitglieder hinzufügen können, wenden Sie sich an den Gruppenbesitzer oder einen Verzeichnisadministrator. Weitere Informationen finden Sie unter Verwalten von Microsoft Entra-Gruppen und -Gruppenmitgliedschaften.

3 : Zuweisen von Rollen zur Anwendung

Als Nächstes müssen Sie bestimmen, welche Rollen (Berechtigungen) Ihre App für welche Ressourcen benötigt, und diese Rollen Ihrer App zuweisen. In diesem Beispiel werden die Rollen der Microsoft Entra-Gruppe zugewiesen, die in Schritt 2 erstellt wurde. Rollen können in einem Ressourcen-, Ressourcengruppen- oder Abonnementbereich zugewiesen werden. In diesem Beispiel wird gezeigt, wie Sie Rollen auf der Ebene der Ressourcengruppe zuweisen, da die meisten Anwendungen alle ihre Azure-Ressourcen in einer einzigen Ressourcengruppe zusammenfassen.

Einem Benutzer, einer Gruppe oder einem Anwendungsdienstprinzipal wird in Azure mit dem Befehl az role assignment create eine Rolle zugewiesen. Sie können eine Gruppe mit ihrer Objekt-ID angeben. Sie können einen Anwendungsdienstprinzipal mit seiner appId angeben.

RESOURCE_GROUP_NAME=<resource-group-name>
SUBSCRIPTION_ID=$(az account show --query id --output tsv)
ROLE_NAME=<role-name>
az role assignment create \
  --assignee "$APP_ID" \
  --scope "./subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME" \
  --role "$ROLE_NAME"

![!HINWEIS] Um zu verhindern, dass Git Bash /subscriptions/... als Dateipfad behandelt, fügen Sie der Zeichenfolge für den scope-Parameter ./ voran und setzen Sie die gesamte Zeichenfolge in doppelte Anführungszeichen.

Verwenden Sie den Befehl az role definition list, um die Rollennamen abzurufen, die zugewiesen werden können.

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

Um beispielsweise dem Anwendungsdienstprinzipal mit der appId 00001111-aaaa-2222-bbbb-3333cccc4444 Lese-, Schreib- und Lösch-Zugang zu Azure Storage-Blob-Containern und Daten in allen Speicherkonten in der Ressourcengruppe msdocs-python-sdk-auth-example im Rahmen des Abonnements mit der ID aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e zu gewähren, weisen Sie den Anwendungsdienstprinzipal mithilfe des folgenden Befehls der Rolle Storage Blob Data Contributor zu.

az role assignment create --assignee 00001111-aaaa-2222-bbbb-3333cccc4444 \
    --scope "./subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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.

4 – Einrichten von Umgebungsvariablen für die lokale Entwicklung

Das DefaultAzureCredential -Objekt sucht zur Laufzeit nach den Dienstprinzipalinformationen in einer Reihe von Umgebungsvariablen. Da die meisten Entwickler an mehreren Anwendungen arbeiten, wird empfohlen, ein Paket wie python-dotenv für den Zugriff auf die Umgebung aus einer .env-Datei heraus zu verwenden, die während der Entwicklung im Verzeichnis der Anwendung gespeichert ist. Dadurch werden die Umgebungsvariablen für die Authentifizierung der Anwendung bei Azure so verwendet, dass sie nur von dieser Anwendung verwendet werden können.

Die Datei .env wird nie in die Quellcodeverwaltung eingecheckt, da sie das Anwendungsgeheimnis für Azure enthält. Die standardmäßige .gitignore-Datei für Python schließt die .env-Datei automatisch vom Einchecken aus.

Um das python-dotenv-Paket zu verwenden, installieren Sie zuerst das Paket in Ihrer Anwendung.

pip install python-dotenv

Erstellen Sie dann eine .env-Datei im Stammverzeichnis Ihrer Anwendung. Legen Sie die Umgebungsvariablen mit Werten fest, die wie folgt aus dem App-Registrierungsprozess abgerufen werden:

  • AZURE_CLIENT_ID → Der App-ID-Wert.
  • AZURE_TENANT_ID → Der Wert der Mandanten-ID.
  • AZURE_CLIENT_SECRET → Das für die App generierte Kennwort/Anmeldeinformationen.
AZURE_CLIENT_ID=00001111-aaaa-2222-bbbb-3333cccc4444
AZURE_TENANT_ID=aaaabbbb-0000-cccc-1111-dddd2222eeee
AZURE_CLIENT_SECRET=Ee5Ff~6Gg7.-Hh8Ii9Jj0Kk1Ll2Mm3_Nn4Oo5Pp6

Verwenden Sie schließlich im Startcode für Ihre Anwendung die python-dotenv-Bibliothek, um die Umgebungsvariablen aus der .env-Datei beim Start zu lesen.

from dotenv import load_dotenv

if ( os.environ['ENVIRONMENT'] == 'development'):
    print("Loading environment variables from .env file")
    load_dotenv(".env")

5 - 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. In diesem Szenario erkennt DefaultAzureCredential die Umgebungsvariablen AZURE_CLIENT_ID, AZURE_TENANT_ID und AZURE_CLIENT_SECRET, richtet sie ein und liest sie, um die Informationen zu dem Anwendungsdienstprinzipal zu erhalten, der mit Azure verbunden werden soll.

Fügen Sie Ihrer Anwendung zunächst das Paket azure.identity hinzu.

pip install azure-identity

Danach 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)