Simon Vedder

Cloud Engineer · Zürich

AppLifecycleAnalyzer

Prerequisites

Three delegated scopes on Microsoft Graph, and nothing in Azure. Reading and acting are two different sets of rights, and the script only ever does the first.

Software

Who needs which role

To run the audit

Read scopes

Your own account, on Graph.

  • Application.Read.All — Graph, delegated
  • AuditLog.Read.All — Graph, delegated
  • Directory.Read.All — Graph, delegated

To act on a finding

Write, separately

Your own account, and only with -RequestWriteScopes.

  • Application.ReadWrite.All — Graph, delegated

Two ways to end up with a tenant that looks entirely dormant. Without AuditLog.Read.All every app comes back with no recorded sign-in — and without a premium tier the same happens, because servicePrincipalSignInActivities needs one. In that case the report still lists every app and its credentials, and the activity column says it does not know rather than guessing.

Before you delete anything

It reports registrations. It does not know what depends on them. An expired secret can sit next to a certificate that is doing all the work, and a dormant app can be the one that runs every December.

Do not use forWhyDo this instead
Managed identitiesDifferent lifecycle, no credentials to expireLook at their role assignments instead
Deciding on its own that an app is deadNo sign-in is evidence of nothing running, not of nothing needing itAsk the owner, then delete
Continuous monitoringOne run is one point in timeEntra ID Protection, Defender for Cloud Apps, Sentinel
Compliance baselinesIt has no baseline to compare againstMaester, ScubaGear
Unattended cleanupEvery command is meant to pass a person firstAccess reviews, or your own change process

← Overview·Commands