Identity & Access Management Cheatsheet
Access governance for Microsoft Entra: how to design who gets what, how it is granted, reviewed, and revoked. Group and role architecture, conditional access, consent and service-principal governance, privileged access, and the reviews that keep it clean. No account needed.
IAM is the discipline of granting exactly the access each identity needs, and no more, then proving it stays that way. Where attack-detection asks "is someone abusing this access," governance asks "should this access exist at all," and the second question prevents far more incidents than the first catches. This is the design and review reference: the configuration and patterns that keep an Entra tenant least-privilege over time, across human users, guests, applications, and the non-human identities that quietly outnumber all of them. Every control here exists because access, left alone, only grows.
The IAM problem
Access only ever accumulates unless something removes it. People change roles and keep the old access (permission creep), accounts outlive their owners (stale identities), apps and service principals are granted broad scopes and never reviewed, and privilege becomes permanent. Every item below is a governance control that counters one of these drifts.
| Drift | Governance control |
|---|---|
| Permission creep | Role-based access via groups; access reviews; separation of duties. |
| Stale identities | Lifecycle automation (joiner-mover-leaver); stale-account detection. |
| Ungoverned apps | Consent policy; permission review; app governance. |
| Non-human sprawl | Service-principal inventory; credential governance. |
| Standing privilege | PIM (just-in-time); privileged access reviews; break-glass design. |
Group and role architecture
Groups are how access scales without becoming unmanageable. The core decision is assigned vs dynamic membership: assigned groups are explicit and auditable but manual; dynamic groups are rule-driven and self-maintaining but only as correct as their rule. Access is granted to groups, not users, so that a role change is a group change, not an audit of every resource. The failure mode is the nested group nobody fully maps: access granted three groups deep, inherited by members who were never meant to have it. Keep nesting shallow and deliberate, and treat a dynamic-group rule as a privileged object, because in effect it is one, it grants access at the scale of whatever it matches.
| Choice | Use when |
|---|---|
| Assigned group | Membership is small, sensitive, or does not map to a directory attribute. Explicit and reviewable. |
| Dynamic group | Membership maps to an attribute (department, jobTitle). Self-maintaining; the rule is the control. |
| Built-in role | The role matches a standard Entra function. Prefer over custom; less to govern. |
| Custom role | Only when no built-in role fits and least-privilege demands it. Each custom role is governance debt. |
Conditional access design
Conditional access is the policy engine that decides whether a sign-in proceeds. Good design is layered and explicit: a baseline that requires MFA and a compliant or managed device, risk-based policies that step up on signal, and as few exclusions as possible. The common design errors are a single monolithic policy that is impossible to reason about, and a sprawl of overlapping policies whose combined effect nobody can predict. Build named policies with one clear intent each, test them in report-only mode before enforcement, and keep a documented map of which policy covers which population, an undocumented CA estate becomes a set of rules people are afraid to touch, which is how stale exclusions survive for years.
| Policy pattern | Intent |
|---|---|
| Require MFA, all users | The baseline. Phishing-resistant methods for privileged roles. |
| Require compliant / managed device | Ties access to a known device, not just a credential. |
| Block legacy authentication | Closes the protocols that skip MFA. Highest-value single policy. |
| Risk-based step-up | Identity Protection risk raises the requirement (re-auth, block). |
| Session controls | Sign-in frequency, persistent-browser limits for sensitive apps. |
Applications and consent governance
OAuth consent is how apps get access to your data, and unrestricted user consent is how attackers do too. In a consent-phishing attack the user is tricked into granting a malicious app real Graph permissions (read mail, read files), and because the user consented, no credential was stolen and MFA never mattered. The governance move is to restrict who can consent, define the low-risk permission tier an app may be granted without admin review, route everything above it to an admin-consent workflow, and periodically re-examine what apps already hold, because the dangerous grant is usually the one made months ago that no one has looked at since.
| Control | What it governs |
|---|---|
| Consent policy | Whether users can consent at all, and to which permission tiers without admin approval. |
| Admin consent workflow | Routes high-privilege requests to a reviewer instead of silent grant. |
| Granted-permission review | Periodic audit of what apps already hold, the creep nobody sees. |
| App governance (Defender) | Behavioral monitoring of OAuth apps for anomalous data access. |
Service principal and workload governance
Service principals and workload identities authenticate as themselves and outlive any human. They are the least-governed identities in most tenants and the most dangerous when neglected: a forgotten app registration with a long-lived secret and broad permissions is a standing backdoor that no password reset or offboarding ever touches. The reason they sprawl is that anyone can register an app, the credential never expires unless someone sets it to, and ownership evaporates when the person who created it leaves. Inventory every service principal against an accountable owner, classify by privilege, prefer certificates over secrets, and alert on credential additions, a new secret on an existing app is one of the cleanest persistence moves an attacker has.
| Governance step | Why |
|---|---|
| Inventory & classify | You cannot govern what you have not enumerated. Map every SP to an owner and purpose. |
| Credential governance | Prefer certificates over secrets; expire and rotate; alert on new credentials. |
| Permission analysis | Right-size Graph permissions; remove unused high-privilege grants. |
| Ownership & review | Every SP has an accountable owner and a review cadence, or it is decommissioned. |
Privileged access
Standing privilege is the highest-value target in the tenant, so the governance goal is that almost no privilege is permanent. PIM makes privileged roles eligible rather than active: a user activates the role when needed, time-bound and justified, and it drops automatically after. That single change turns a permanent Global Admin (a credential worth stealing every hour of every day) into a role that is dormant most of the time and audited every time it wakes. Role assignment itself is governed (who may grant privilege, and how that is reviewed), and a small number of break-glass accounts exist for the day everything else fails, designed deliberately, not discovered missing during the incident.
| Element | Design |
|---|---|
| PIM eligibility | Privileged roles are eligible, not active; activation is time-bound, justified, approved. |
| Role assignment governance | Who can assign privileged roles, and how that assignment is reviewed. |
| Break-glass accounts | Two cloud-only Global Admins, excluded from CA, FIDO2, monitored for any use, validated quarterly. |
| Privileged access reviews | Recurring certification that each privileged assignment is still needed. |
Entitlement management and access reviews
Entitlement management packages access into requestable, approvable, expiring bundles, so granting is governed at the point of request, not retrofitted later, and the access carries its own expiry instead of living forever. Access reviews are the counterweight that removes what is no longer needed. Together they make access a loop (request, approve, use, review, expire) rather than the one-way accumulation that is the default state of every directory. The hardest part is the leaver and the mover: offboarding usually removes the obvious account but leaves the group memberships, app roles, and standing access behind, which is exactly the residue that becomes an orphaned attack surface. Lifecycle automation that triggers on the HR signal, not on someone remembering, is what closes that gap.
| Mechanism | Governs |
|---|---|
| Access packages | Bundled access (groups, apps, roles) requestable with approval and expiry. |
| Approval workflows | Who signs off on a request, and on what basis. |
| Separation of duties | Incompatible access packages that no one identity may hold together. |
| Access reviews | Scoped, scheduled recertification; reviewers who actually know; auto-remove on no-response. |
| Lifecycle (JML) | Joiner-mover-leaver automation so access tracks role, including removal. |
IAM monitoring queries
Governance needs evidence, not assumption. These KQL queries surface the three drifts that governance exists to counter, the stale account that should be gone, the identity quietly accumulating access, the application credential nobody is tracking. Run them on a cadence and feed the output straight into the access-review process, so the monitoring and the remediation are one loop rather than a report that gets filed. They run in Microsoft Sentinel; several depend on the IdentityInfo table, which requires UEBA enabled with Entra ID as the entity provider.
Stale member accounts
// Hunt: Stale member accounts: no successful sign-in in 90 days
// Data source: SigninLogs, IdentityInfo
// Requires: Entra ID connector with SigninLogs enabled
let threshold = 90d;
let recentSignIns = SigninLogs
| where TimeGenerated > ago(threshold)
| where ResultType == "0"
| where UserType == "Member"
| summarize LastSuccessfulSignIn = max(TimeGenerated) by UserPrincipalName;
IdentityInfo
| where TimeGenerated > ago(1d)
| where UserType == "Member"
| where IsAccountEnabled == true
| summarize arg_max(TimeGenerated, *) by AccountUPN
| join kind=leftanti recentSignIns on $left.AccountUPN == $right.UserPrincipalName
| project AccountUPN, AccountDisplayName, Department, JobTitle,
AccountCreationTime
| where AccountCreationTime < ago(threshold)
Members with no successful sign-in inside the threshold are candidates for disable-then-delete, route them to manager review with their directory context attached.
Permission creep
// Hunt: Users with group additions but no removals in 180 days
// Signal: mover event that added groups without removing old ones
let lookback = 180d;
let additions = AuditLogs
| where TimeGenerated > ago(lookback)
| where OperationName == "Add member to group"
| where Category == "GroupManagement"
| extend TargetUser = tostring(TargetResources[0].userPrincipalName)
| extend GroupName = tostring(TargetResources[1].displayName)
| where isnotempty(TargetUser)
| summarize GroupsAdded = dcount(GroupName),
AddedGroups = make_set(GroupName) by TargetUser;
let removals = AuditLogs
| where TimeGenerated > ago(lookback)
| where OperationName == "Remove member from group"
| where Category == "GroupManagement"
| extend TargetUser = tostring(TargetResources[0].userPrincipalName)
| summarize Gro
Accounts gaining group memberships without losing any are accumulating access, the signature of a mover whose old access was never removed.
Credential health
// Monitor: Credential lifecycle events for app registrations
// Detects: secret/certificate additions, removals, and modifications
let lookback = 30d;
AuditLogs
| where TimeGenerated > ago(lookback)
| where OperationName has_any (
"Update application – Certificates and secrets management",
"Add service principal credentials",
"Remove service principal credentials")
| extend AppName = tostring(TargetResources[0].displayName)
| extend Actor = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
| extend ActorApp = tostring(parse_json(tostring(InitiatedBy.app)).displayName)
| project TimeGenerated, OperationName, AppName,
Actor = coalesce(Actor, ActorApp),
Result, CorrelationId
| sort by TimeGenerated desc
Credential lifecycle events on app registrations surface new, expiring, and long-lived secrets, the service-principal hygiene that governance has to enforce.
Governance checklist
| Domain | The baseline |
|---|---|
| Access model | Grant to groups not users; built-in roles over custom; least privilege by default. |
| Conditional access | MFA baseline, block legacy auth, compliant device, minimal reviewed exclusions. |
| Consent | Restrict user consent; admin workflow for high-privilege; review granted permissions. |
| Service principals | Inventoried, owned, certificate-based, permission-right-sized, credential-alerted. |
| Privilege | PIM-eligible not active; break-glass designed; privileged reviews recurring. |
| Lifecycle | JML automation; entitlement packages with expiry; access reviews that default to removal. |
From governance patterns to the designed identity system
This cheatsheet is the governance reference. Identity and Access Management teaches the full design: group and CA architecture, consent and service-principal governance, privileged access, entitlement management, and the access-review program that holds it together.
Explore the course