Python-apps verifiëren bij Azure-services tijdens lokale ontwikkeling met behulp van service-principals

Bij het maken van cloudtoepassingen moeten ontwikkelaars fouten opsporen en toepassingen testen op hun lokale werkstation. Wanneer een toepassing wordt uitgevoerd op het werkstation van een ontwikkelaar tijdens de lokale ontwikkeling, moet deze nog steeds worden geverifieerd bij alle Azure-services die door de app worden gebruikt. In dit artikel wordt beschreven hoe u service-principalobjecten voor toegewezen toepassingen instelt die moeten worden gebruikt tijdens lokale ontwikkeling.

Een diagram waarin wordt getoond hoe een app die wordt uitgevoerd in de lokale ontwikkelaar de toepassingsservice-principal verkrijgt van een .env-bestand en die identiteit vervolgens gebruikt om verbinding te maken met Azure-resources.

Met speciale toepassingsservice-principals voor lokale ontwikkeling kunt u het principe van minimale bevoegdheden tijdens het ontwikkelen van apps volgen. Omdat machtigingen zijn afgestemd op precies wat er nodig is voor de app tijdens de ontwikkeling, wordt voorkomen dat app-code per ongeluk toegang krijgt tot een Azure-resource die is bedoeld voor gebruik door een andere app. Dit voorkomt ook dat er fouten optreden wanneer de app naar productie wordt verplaatst, omdat de app te veel is gemachtigd in de ontwikkelomgeving.

Een toepassingsservice-principal wordt ingesteld voor de app wanneer de app is geregistreerd in Azure. Bij het registreren van apps voor lokale ontwikkeling is het raadzaam het volgende te doen:

  • Maak afzonderlijke app-registraties voor elke ontwikkelaar die aan de app werkt. Hiermee maakt u afzonderlijke toepassingsservice-principals voor elke ontwikkelaar die moet worden gebruikt tijdens de lokale ontwikkeling en voorkomt u dat ontwikkelaars referenties voor één toepassingsservice-principal moeten delen.
  • Afzonderlijke app-registraties per app maken. Hiermee worden de machtigingen van de app alleen bereikt voor wat de app nodig heeft.

Tijdens lokale ontwikkeling worden omgevingsvariabelen ingesteld met de identiteit van de toepassingsservice-principal. De Azure SDK voor Python leest deze omgevingsvariabelen en gebruikt deze informatie om de app te verifiëren bij de Azure-resources die nodig zijn.

1 - De toepassing registreren in Azure

Toepassingsservice-principalobjecten worden gemaakt met een app-registratie in Azure. U kunt dit doen met behulp van Azure Portal of Azure CLI.

Azure CLI-opdrachten kunnen worden uitgevoerd in Azure Cloud Shell of op een werkstation waarop de Azure CLI is geïnstalleerd.

Gebruik eerst de opdracht az ad sp create-for-rbac om een nieuwe service-principal voor de app te maken. Met de opdracht wordt ook tegelijkertijd de app-registratie voor de app gemaakt.

az ad sp create-for-rbac --name {service-principal-name}

De uitvoer van deze opdracht ziet er als volgt uit. Noteer deze waarden of houd dit venster open, omdat u deze waarden nodig hebt in de volgende stappen en de waarde voor het wachtwoord (clientgeheim) niet meer kunt weergeven. U kunt echter later een nieuw wachtwoord toevoegen zonder de service-principal of bestaande wachtwoorden indien nodig ongeldig te maken.

{
  "appId": "00000000-0000-0000-0000-000000000000",
  "displayName": "{service-principal-name}",
  "password": "abcdefghijklmnopqrstuvwxyz",
  "tenant": "33333333-3333-3333-3333-333333333333"
}

2 - Een Microsoft Entra-beveiligingsgroep maken voor lokale ontwikkeling

Aangezien er doorgaans meerdere ontwikkelaars zijn die aan een toepassing werken, is het raadzaam om een Microsoft Entra-beveiligingsgroep te maken om de rollen (machtigingen) die de app nodig heeft in lokale ontwikkeling in te kapselen in plaats van de rollen toe te wijzen aan afzonderlijke service-principal-objecten. Dit biedt de volgende voordelen:

  • Elke ontwikkelaar weet zeker dat dezelfde rollen zijn toegewezen omdat rollen op groepsniveau worden toegewezen.
  • Als er een nieuwe rol nodig is voor de app, hoeft deze alleen te worden toegevoegd aan de Microsoft Entra-groep voor de app.
  • Als een nieuwe ontwikkelaar lid wordt van het team, wordt er een nieuwe toepassingsservice-principal gemaakt voor de ontwikkelaar en toegevoegd aan de groep, zodat de ontwikkelaar over de juiste machtigingen beschikt om aan de app te werken.

De opdracht az ad group create wordt gebruikt voor het maken van beveiligingsgroepen in Microsoft Entra ID. De parameters --display-name en --main-nickname zijn vereist. De naam die aan de groep wordt gegeven, moet zijn gebaseerd op de naam van de toepassing. Het is ook handig om een woordgroep zoals 'local-dev' op te nemen in de naam van de groep om het doel van de groep aan te geven.

az ad group create \
    --display-name MyDisplay \
    --mail-nickname MyDisplay  \
    --description "<group-description>"

Kopieer de waarde van de id eigenschap in de uitvoer van de opdracht. Dit is de object-id voor de groep. U hebt deze in latere stappen nodig. U kunt ook de opdracht az ad group show gebruiken om deze eigenschap op te halen.

Als u leden aan de groep wilt toevoegen, hebt u de object-id van de service-principal van de toepassing nodig. Dit verschilt van de toepassings-id. Gebruik de lijst az ad sp om de beschikbare service-principals weer te geven. De --filter parameteropdracht accepteert OData-stijlfilters en kan worden gebruikt om de lijst te filteren zoals wordt weergegeven. De --query parameter beperkt zich tot alleen kolommen die van belang zijn.

az ad sp list \
    --filter "startswith(displayName, 'msdocs')" \
    --query "[].{objectId:id, displayName:displayName}" \
    --output table

De opdracht az ad group member add kan vervolgens worden gebruikt om leden toe te voegen aan groepen.

az ad group member add \
    --group <group-name> \
    --member-id <object-id>

Notitie

Standaard is het maken van Microsoft Entra-beveiligingsgroepen beperkt tot bepaalde bevoorrechte rollen in een directory. Als u geen groep kunt maken, neemt u contact op met een beheerder voor uw adreslijst. Als u geen leden kunt toevoegen aan een bestaande groep, neemt u contact op met de groepseigenaar of een adreslijstbeheerder. Zie Microsoft Entra-groepen en groepslidmaatschap beheren voor meer informatie.

3 - Rollen toewijzen aan de toepassing

Vervolgens moet u bepalen welke rollen (machtigingen) uw app nodig heeft voor welke resources en welke rollen aan uw app worden toegewezen. In dit voorbeeld worden de rollen toegewezen aan de Microsoft Entra-groep die in stap 2 is gemaakt. Rollen kunnen worden toegewezen aan een resource, resourcegroep of abonnementsbereik. In dit voorbeeld ziet u hoe u rollen toewijst aan het bereik van de resourcegroep, omdat de meeste toepassingen al hun Azure-resources groeperen in één resourcegroep.

Aan een gebruiker, groep of toepassingsservice-principal wordt een rol toegewezen in Azure met behulp van de opdracht az role assignment create . U kunt een groep opgeven met de bijbehorende object-id. U kunt een toepassingsservice-principal opgeven met de bijbehorende appId.

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

Gebruik de opdracht az role definition list om de rolnamen op te halen die kunnen worden toegewezen.

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

Als u bijvoorbeeld de service-principal van de toepassing wilt toestaan met de appId van 00000000-0000-0000-0000-000000000000 lezen, schrijven en verwijderen van toegang tot Azure Storage-blobcontainers en -gegevens in alle opslagaccounts in de resourcegroep msdocs-python-sdk-auth-auth-example in het abonnement met id 11111111-1111-1111-1111-111111111111, wijst u de service-principal van de toepassing toe aan de rol Inzender voor opslagblobgegevens met behulp van de volgende opdracht.

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"

Zie het artikel Azure-rollen toewijzen met behulp van de Azure CLI voor informatie over het toewijzen van machtigingen op resource- of abonnementsniveau met behulp van de Azure CLI.

4 - Omgevingsvariabelen voor lokale ontwikkeling instellen

Het DefaultAzureCredential object zoekt tijdens runtime naar de informatie van de service-principal in een set omgevingsvariabelen. Omdat de meeste ontwikkelaars aan meerdere toepassingen werken, is het raadzaam om een pakket zoals python-dotenv te gebruiken voor toegang tot de omgeving vanuit een .env bestand dat tijdens de ontwikkeling in de map van de toepassing is opgeslagen. Dit is het bereik van de omgevingsvariabelen die worden gebruikt voor het verifiëren van de toepassing bij Azure, zodat ze alleen door deze toepassing kunnen worden gebruikt.

Het .env bestand wordt nooit ingecheckt bij broncodebeheer omdat het de geheime sleutel van de toepassing voor Azure bevat. Het standaard .gitignore-bestand voor Python sluit het .env bestand automatisch uit van het inchecken.

Als u het python-dotenv-pakket wilt gebruiken, installeert u eerst het pakket in uw toepassing.

pip install python-dotenv

Maak vervolgens een .env bestand in de hoofdmap van uw toepassing. Stel de omgevingsvariabelewaarden als volgt in met waarden die zijn verkregen uit het app-registratieproces:

  • AZURE_CLIENT_ID → de waarde van de app-id.
  • AZURE_TENANT_ID → de waarde van de tenant-id.
  • AZURE_CLIENT_SECRET → het wachtwoord/de referentie die voor de app is gegenereerd.
AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
AZURE_TENANT_ID=11111111-1111-1111-1111-111111111111
AZURE_CLIENT_SECRET=abcdefghijklmnopqrstuvwxyz

Gebruik ten slotte in de opstartcode voor uw toepassing de python-dotenv bibliotheek om de omgevingsvariabelen uit het bestand bij het .env opstarten te lezen.

from dotenv import load_dotenv

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

5 - DefaultAzureCredential implementeren in uw toepassing

Als u Azure SDK-clientobjecten wilt verifiëren bij Azure, moet uw toepassing de DefaultAzureCredential klasse van het azure.identity pakket gebruiken. In dit scenario DefaultAzureCredential worden de omgevingsvariabelen AZURE_CLIENT_IDAZURE_TENANT_IDgedetecteerd en AZURE_CLIENT_SECRET worden deze variabelen ingesteld en gelezen om de service-principalgegevens van de toepassing op te halen om verbinding te maken met Azure.

Begin met het toevoegen van het pakket azure.identity aan uw toepassing.

pip install azure-identity

Vervolgens wilt u voor elke Python-code die een Azure SDK-clientobject maakt in uw app het volgende doen:

  1. Importeer de DefaultAzureCredential klasse uit de azure.identity module.
  2. Maak een DefaultAzureCredential object.
  3. Geef het DefaultAzureCredential object door aan de objectconstructor van de Azure SDK-client.

Een voorbeeld hiervan wordt weergegeven in het volgende codesegment.

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)