All posts

7 min readMicrosoft Entra · Managed Identity · Azure · Best Practices

Managed Identities statt Client Secrets: Wo es geht und wo nicht

Managed Identities ersetzen Client Secrets für Workloads in Azure. Welche Dienste sie unterstützen, wie du Graph-Berechtigungen per PowerShell vergibst, wo nur Workload Identity Federation hilft und welche Secrets trotzdem bleiben.

Read this post in English

Ein Client Secret ist ein Passwort für eine Anwendung. Es liegt in einer App-Konfiguration, einem Key Vault oder einer Pipeline-Variable, es läuft ab, und irgendwer muss es rechtzeitig tauschen. Managed Identities schaffen dieses Passwort ab, aber nur für Workloads, die in Azure laufen. Dieser Beitrag zeigt, wo der Wechsel funktioniert, wie er technisch aussieht und welche Credentials danach übrig bleiben.

Was eine Managed Identity ist

Eine Managed Identity ist ein Service Principal in Microsoft Entra ID, dessen Credential Azure selbst erstellt, speichert und erneuert. Es gibt kein Secret, das du kopieren, ablegen oder rotieren musst. Das Credential ist laut Microsoft zertifikatsbasiert, 90 Tage gültig und wird nach 45 Tagen automatisch erneuert. Du bekommst es nie zu sehen.

Anders als eine App-Registrierung hat eine Managed Identity kein Application-Objekt, nur den Service Principal. Das erklärt später, warum die Berechtigungsvergabe anders läuft als gewohnt.

System-assigned oder user-assigned

Beide Varianten liefern dieselbe Art Token. Der Unterschied liegt im Lebenszyklus:

  • System-assigned wird direkt auf einer Ressource aktiviert, etwa auf einer Function App. Die Identität heißt wie die Ressource, gehört nur ihr und wird mit ihr gelöscht. Passend, wenn ein Workload seine eigene Identität braucht und du im Audit-Log sehen willst, welche Ressource gehandelt hat.
  • User-assigned ist eine eigenständige Azure-Ressource, die du mehreren Ressourcen zuweist. Rollen und Graph-Berechtigungen kannst du vergeben, bevor der Workload existiert. Microsoft nennt diese Variante in den Best Practices die effizientere Wahl für die meisten Szenarien, weil weniger Identitäten und Rollenzuweisungen zu pflegen sind, etwa wenn fünf VMs denselben Storage Account lesen.

Eine Ressource kann beides gleichzeitig tragen: eine system-assigned und mehrere user-assigned Identitäten.

Welche Azure-Dienste Managed Identities unterstützen

Die vollständige Liste pflegt Microsoft unter Azure services that support managed identities. Für typische Integrations-Workloads relevant sind:

  • Azure App Service und Azure Functions (Konfiguration je Deployment-Slot)
  • Virtual Machines und Virtual Machine Scale Sets
  • Azure Kubernetes Service, für Pods über Microsoft Entra Workload ID
  • Azure Container Apps und Azure Container Instances
  • Azure Logic Apps
  • Azure Automation (Runbooks)
  • Azure Data Factory und Azure Synapse
  • API Management
  • Azure Arc-enabled Servers, also On-Prem-Server mit Connected Machine Agent (nur system-assigned)

Der letzte Punkt ist die einzige Ausnahme von der Regel „nur in Azure“. Ein Windows- oder Linux-Server im eigenen Rechenzentrum bekommt über Azure Arc eine system-assigned Identity, die der Agent selbst erneuert.

Wie der Code ein Token bekommt

In den Azure-Identity-Bibliotheken (Azure.Identity für .NET, azure-identity für Python und Java, @azure/identity für JavaScript) gibt es zwei relevante Klassen. ManagedIdentityCredential holt gezielt ein Token der Managed Identity. DefaultAzureCredential probiert eine Kette durch: Umgebungsvariablen, Workload Identity, Managed Identity und zuletzt die Anmeldung der Azure CLI auf dem Entwicklerrechner. Für produktiven Code in Azure empfiehlt Microsoft die explizite ManagedIdentityCredential, damit nicht versehentlich ein anderes Credential greift.

var credential = new ManagedIdentityCredential();
var token = await credential.GetTokenAsync(
    new TokenRequestContext(["https://graph.microsoft.com/.default"]));

Unter der Haube ruft die Bibliothek einen lokalen Endpunkt auf: auf einer VM den Instance Metadata Service unter 169.254.169.254, auf App Service, Functions und Container Apps die Adresse aus der Umgebungsvariable IDENTITY_ENDPOINT. Das Token wird direkt auf der Ressource ausgestellt, aus keinem Secret-Speicher wird etwas gelesen.

Graph-Berechtigungen für eine Managed Identity

Hier stolpern die meisten. Bei einer App-Registrierung klickst du im Entra Admin Center auf „API-Berechtigungen“, wählen Application.Read.All und erteilen Admin Consent. Diese Seite gibt es für eine Managed Identity nicht, weil ihr das Application-Objekt fehlt. Microsoft schreibt ausdrücklich, dass es derzeit keine Option gibt, Graph-Berechtigungen einer Managed Identity über das Admin Center zuzuweisen.

Stattdessen weist du die App-Rolle direkt dem Service Principal zu. Das Beispiel gibt einer Function App die Berechtigung Application.Read.All auf Microsoft Graph:

Connect-MgGraph -Scopes "Application.Read.All", "AppRoleAssignment.ReadWrite.All"

# Service Principal der Managed Identity (Name = Name der Azure-Ressource)
$mi = Get-MgServicePrincipal -Filter "displayName eq 'func-secret-report' and servicePrincipalType eq 'ManagedIdentity'"

# Service Principal von Microsoft Graph und die gewünschte App-Rolle
$graph = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
$role  = $graph.AppRoles | Where-Object { $_.Value -eq "Application.Read.All" }

New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $mi.Id `
  -PrincipalId $mi.Id -ResourceId $graph.Id -AppRoleId $role.Id

Die Zuweisung siehst du danach im Entra Admin Center unter „Unternehmensanwendungen“ mit dem Filter „Anwendungstyp: Verwaltete Identitäten“ im Reiter „Berechtigungen“. Ein Hinweis aus der Praxis: Token der Managed Identity werden gecacht. Eine neue Rolle kann deshalb eine Weile brauchen, bis sie im Token erscheint.

Wo Managed Identities nicht funktionieren

Managed Identities existieren nur für Ressourcen, die Azure kennt. Daraus folgen die Grenzen:

  • On-Prem-Server ohne Azure Arc, Server bei anderen Hostern, AWS oder Google Cloud: kein IMDS-Endpunkt, keine Managed Identity.
  • SaaS von Drittanbietern, die sich an deinen Tenant anbinden (Backup, Ticketing, Monitoring): Der Anbieter authentifiziert sich mit seiner eigenen App-Registrierung und deren Credential.
  • Entwickler-Laptops: Lokal greift DefaultAzureCredential auf die Anmeldung der Azure CLI oder von Visual Studio zurück. Das ist gut so, aber es ist eine Benutzeridentität, keine Managed Identity.
  • Multi-Tenant-Apps, denen Kunden per Admin Consent zustimmen: Managed Identities funktionieren nicht tenantübergreifend. Läuft die App selbst in Azure, kann die App-Registrierung inzwischen eine Managed Identity als Federated Credential akzeptieren und so ohne Secret auskommen. Der Consent beim Kunden bleibt davon unberührt.
  • SAML-SSO in Enterprise Apps: Das Signaturzertifikat hat mit Managed Identities nichts zu tun und läuft weiter ab.

Workload Identity Federation für CI/CD und Kubernetes außerhalb von Azure

Für GitHub Actions, Azure DevOps, Kubernetes im eigenen Rechenzentrum oder Workloads in anderen Clouds gibt es den zweiten Weg ohne Secret: Workload Identity Federation. Du hinterlegst an der App-Registrierung ein Federated Identity Credential, das einem externen OIDC-Aussteller vertraut. Im Admin Center findest du das unter „Zertifikate & Geheimnisse“ im Reiter „Federated credentials“.

Drei Werte definieren das Vertrauen: issuer (bei GitHub https://token.actions.githubusercontent.com), subject (etwa repo:meine-org/mein-repo:environment:Production) und audience (empfohlen api://AzureADTokenExchange). Der Workflow tauscht sein kurzlebiges GitHub-Token gegen ein Entra-Token, ohne dass irgendwo ein Secret liegt. Pro App-Registrierung oder user-assigned Managed Identity sind maximal 20 Federated Credentials möglich. Ein häufiger Fehler: Stimmt das subject nicht exakt, schlägt der Tausch ohne aussagekräftige Fehlermeldung fehl.

Entscheidungstabelle

Wo läuft der WorkloadEmpfehlungWas bleibt zu überwachen
App Service, Functions, Container Apps, VMManaged Identity, user-assigned wenn mehrere Ressourcen dieselben Rechte brauchennichts
AKS-PodsWorkload ID mit user-assigned Identity und Federated Credentialnichts
GitHub Actions, Azure DevOps, andere CIWorkload Identity Federation an der App-Registrierungnichts, aber die Subject-Regeln dokumentieren
Kubernetes außerhalb von AzureWorkload Identity Federation mit dem OIDC-Issuer des Clustersnichts
On-Prem-Server mit Azure Arcsystem-assigned Managed Identity des Arc-Serversnichts
On-Prem-Server ohne Arc, andere CloudsZertifikat, notfalls Client Secret an der App-RegistrierungAblaufdatum
Drittanbieter-SaaS mit eigener AppCredential des Anbieters, meist ein SecretAblaufdatum
Multi-Tenant-App für KundenZertifikat oder Secret, in Azure alternativ Managed Identity als Federated CredentialAblaufdatum
SAML-SSO in Enterprise AppsSignaturzertifikatAblaufdatum

Migration in vier Schritten

  1. Inventarisieren. Alle App-Registrierungen mit Secrets und Zertifikaten auflisten, per Skript oder Werkzeug. Wie das mit Get-MgApplication geht, steht im Beitrag Entra App Registration Secrets laufen ab.
  2. Nach Laufzeitort klassifizieren. Für jedes Credential festhalten, wer es benutzt und wo dieser Workload läuft: Azure-Ressource, CI-Pipeline, externer Dienst, Laptop, Kunde. Ohne Beschreibung und Owner am Secret ist dieser Schritt der teuerste.
  3. Azure-Workloads zuerst umstellen. Identität aktivieren, Graph-Rolle oder RBAC zuweisen, Code auf ManagedIdentityCredential umstellen, parallel zum alten Secret testen. Danach CI/CD und externe Kubernetes-Cluster auf Federated Credentials.
  4. Alte Secrets löschen. Erst wenn das Anmeldeprotokoll der App-Registrierung keine Anmeldungen mit dem Secret mehr zeigt. Ein ungenutztes Secret, das weiter existiert, ist Angriffsfläche ohne Nutzen.

Was nach der Migration bleibt

Nach unserer Erfahrung bleibt in einem mittelgroßen Tenant ein Drittel bis die Hälfte der Credentials übrig: Backup- und Archivierungsdienste mit eigener App, Monitoring-Tools, Connectoren zu ERP oder CRM, die Multi-Tenant-App des eigenen Produkts, SAML-Zertifikate für SSO. Jedes davon hat ein Ablaufdatum, und Microsoft warnt weiterhin nicht davor. Die Migration verkleinert das Problem, sie löst es nicht.

Wie SecretExpiry hilft

SecretExpiry überwacht die verbleibenden Client Secrets und Zertifikate von App-Registrierungen über viele Tenants hinweg, mit der Leseberechtigung Application.Read.All und ohne die Secret-Werte je zu sehen. Warnungen kommen per E-Mail je Ereignis oder als Wochenübersicht, in einen Teams- oder Slack-Kanal per Webhook und als Kalender-Abo (ICS). Jeder Tenant kann eine eigene Empfängeradresse haben, einzelne Credentials lassen sich stummschalten, das Dashboard zeigt eine Dringlichkeitsliste. Der Test ist 14 Tage kostenlos, danach ab 10 € pro Tenant und Monat. Details zur Einrichtung stehen in der Dokumentation.