Azure App Registration Monitor: Client-Secrets im Blick, bevor Prod bricht
Es passiert lautlos. Ein Client Secret auf einer App Registration läuft ab – kein Alarm, keine Mail, kein Banner im Portal. Auffallen tut es erst, wenn in Produktion die Authentifizierung bricht: der nächtliche Job, die Integration, der Service, der seit Monaten unauffällig lief. Und dann suchst du unter Zeitdruck in einem Tenant mit dutzenden App Registrations nach dem einen Secret, das gestern gültig war und heute nicht mehr.
Das Problem ist nicht, dass Secrets ablaufen – das sollen sie. Das Problem ist, dass Entra dir keine tenantweite Übersicht gibt, welche wann fällig sind. Genau die liefert der Azure App Registration Monitor (AARM).
Was man zuerst sieht
Der typische Ablauf: Jemand hat vor einem Jahr im Portal eine App Registration angelegt, ein Client Secret erzeugt, „24 Monate” gewählt und weitergearbeitet. Kein Ticket, kein Kalendereintrag. Zwölf oder vierundzwanzig Monate später steht der Ausfall im Raum – und niemand weiß auf Anhieb, wie viele Secrets im Tenant überhaupt existieren, wem sie gehören und wann das nächste fällt. Das Entra-Portal zeigt Secrets nur pro App, nie als Gesamtbild.
Was AARM wirklich tut
AARM liest über Microsoft Graph alle App Registrations deines Tenants samt ihrer Client Secrets und Zertifikate aus, bewertet das Risiko nach Restlaufzeit (Info → Critical) und macht daraus eine durchsuchbare, sortierbare Übersicht. Es gibt das Werkzeug in drei Ausprägungen, die dasselbe Fundament teilen:
- die
aarmCLI – liest Graph, prüft Berechtigungen (Preflight) und gibt stabiles JSON aus (perfekt fürs CI-Gate), - die Desktop-App (WinUI/Blazor) – mit Local Mode (ruft die gebündelte CLI) oder Cloud Mode (spricht eine Azure Function an),
- die Azure Function – als Cloud-Scan-Engine mit geplanten Scans, Blob-Storage für Ergebnisse und Teams-Benachrichtigungen.
Dieser Beitrag zeigt die Desktop-App; den reinen CLI-Weg – inklusive Installation ohne jede Azure-Infrastruktur – findest du im aarm-CLI-Beitrag.
Die naheliegende, aber unzureichende Lösung
Der Reflex ist eine Kalendererinnerung „Secret X erneuern” oder eine Excel-Liste. Beides bricht in der Praxis: Erinnerungen überleben keinen Rollenwechsel, und die Liste ist am Tag nach dem Anlegen schon veraltet. Was du brauchst, ist kein manuell gepflegtes Artefakt, sondern eine Ansicht, die den Ist-Zustand aus Graph zieht – jederzeit, für den ganzen Tenant.
Die belastbare Lösung: AARM im Überblick
Das Dashboard fasst pro Tenant das Wesentliche zusammen: Anzahl App Registrations, Gesamtzahl der Secrets, wie viele bereits abgelaufen sind und wie viele in den nächsten 30 bzw. 90 Tagen fällig werden. Ein Blick genügt, um zu wissen, ob dieser Tenant ruhig ist oder brennt.
Das Dashboard verdichtet den Secret-Status eines Tenants auf wenige Kennzahlen.
Secrets & Ablaufdaten
Die Secrets-Liste ist das Herzstück: jede Zeile ein Secret mit Risiko (Info/Low/…), zugehöriger App, Ablaufdatum, Restlaufzeit in Tagen und Status. Sortier- und filterbar nach Risiko, damit die kritischen zuerst oben stehen. Wichtig: AARM zeigt Metadaten – wann läuft was ab –, niemals den geheimen Secret-Wert selbst.
Die Secrets-Liste sortiert nach Restlaufzeit – die App- und Secret-Namen sind für diesen Beitrag geschwärzt.
Preflight: erst prüfen, ob Graph überhaupt darf
Bevor ein Scan verlässliche Zahlen liefert, muss klar sein, was der verwendete Service Principal in Graph darf. Der Preflight-Check testet die Capabilities einzeln – canReadApplications, canReadApplicationSecrets, canReadServicePrincipals und weitere – und zeigt transparent, welche verfügbar sind und welche noch eine Berechtigung samt Admin-Consent brauchen. So weißt du, ob eine leere Liste „wirklich keine Secrets” oder „fehlende Berechtigung” bedeutet.
Preflight macht sichtbar, welche Graph-Berechtigungen fehlen – statt an einer leeren Liste zu rätseln.
Benachrichtigungen per Template
Damit aus der Übersicht Handeln wird, kennt AARM Benachrichtigungs-Templates – etwa für Teams-Nachrichten, wenn ein Secret in ein definiertes Fenster rutscht. So landet die Warnung dort, wo das Team ohnehin hinschaut, statt in einem Dashboard, das niemand öffnet.
Templates verwandeln die Ablauf-Übersicht in rechtzeitige Benachrichtigungen.
Hands-on: derselbe Scan per CLI
Was die Desktop-App visuell zeigt, geht headless genauso – ideal fürs CI-Gate:
# einmalig global installieren
npm install -g @brunsforge/aarm
# Tenant hinterlegen (Client-ID/Secret oder Service Principal)
aarm tenants add
# erst prüfen, was Graph erlaubt
aarm preflight run --tenant "Contoso PROD"
# ablaufende Secrets der nächsten 3 Monate auflisten
aarm secrets expiring --months 3 --output json
Der --output json-Envelope ist stabil – ein Pipeline-Schritt, der rot wird, sobald ein Secret abgelaufen (oder bald fällig) ist, ist damit ein Dreizeiler. Details zu allen Auth-Modi im aarm-CLI-Beitrag.
Local Mode ohne Azure, Cloud Mode mit Infrastruktur
Ein Punkt, der über den Aufwand entscheidet: Local Mode braucht keine Azure-Infrastruktur. Die Desktop-App ruft dann die gebündelte CLI lokal – du brauchst nur ein Konto oder einen Service Principal mit den passenden Graph-Berechtigungen (die Preflight prüft). Für Ad-hoc-Checks am eigenen Rechner reicht das vollständig.
Der Cloud Mode dagegen – geplante Scans, Teams-Benachrichtigungen, ein geteiltes Browser-Dashboard, mehrere Tenants zentral – läuft auf Azure-Infrastruktur, die du einmal ausrollst. Genau das zeigt auch die Demo oben (Badge „Cloud Mode”). Das mitgelieferte Bicep-Template (infra/main.bicep) legt alles Nötige an: eine Function App (Flex Consumption) als Scan-Engine, ein Storage Account (Job-Konfigurationen + Scan-Ergebnisse), einen Key Vault (Scan-Credentials der Ziel-Tenants), Log Analytics + Application Insights für Telemetrie und eine User-Assigned Managed Identity mit den passenden Rollenzuweisungen.
# 1) Ressourcengruppe + komplette Infrastruktur ausrollen (Bicep)
az group create --name aarm-dev-rg --location westeurope
az deployment group create -g aarm-dev-rg \
--template-file infra/main.bicep \
--parameters infra/main.bicepparam \
--name aarm-deploy
# 2) Function-Code veröffentlichen
cd apps/azure-function && npm install && npm run build
func azure functionapp publish <functionAppName> --node
Aus den Deployment-Outputs brauchst du vor allem den functionAppHostname – den trägst du in den Cloud-Mode-Einstellungen der Desktop-App ein. Die Scan-Credentials pro Tenant liegen im Key Vault und werden als Function-App-Setting AARM_SECRET_<JOB> referenziert; beim Tenant-Setup hilft das Skript infra/setup-tenant.ps1. Alle Schritte – inklusive Rollenzuweisungen, jobs.json-Upload und Teardown – stehen ausführlich in der Repo-README unter infra/.
Kurz: Wer nur schnell den eigenen Tenant prüfen will, bleibt im Local Mode (kein Azure nötig). Wer geplante Scans und Team-Benachrichtigungen über mehrere Tenants braucht, rollt einmal die Cloud-Infrastruktur aus – und hat danach genau das Dashboard aus dem Video, serverseitig und geteilt.
Grenzen und Ehrliches
- Ohne Berechtigung keine Daten. AARM ist nur so gut wie die Graph-Permissions des Service Principals. Genau dafür ist Preflight da – aber die Rechte samt Admin-Consent musst du im Vorfeld erteilen.
- Nur Lesen ist der sichere Default. Schreib-Capabilities (Secrets erstellen/löschen) werden nicht automatisch getestet, um keine ungewollten Mutationen auszulösen.
- Optionale Analysen brauchen mehr. Nutzungsanalyse über Log Analytics setzt einen konfigurierten Workspace voraus; ist keiner da, bleibt dieser Teil schlicht leer statt zu raten.
Kurz: Der lautlose Secret-Ablauf ist kein Schicksal, sondern eine Frage der Sichtbarkeit. Wer den Tenant-Gesamtstand regelmäßig aus Graph zieht – per Desktop-App oder als CI-Gate per CLI –, wird von „Prod bricht, weil ein Secret abgelaufen ist” nie wieder überrascht.