Back

Azure access control and compliance: a practical guide for intelligent access

If you run Azure at real scale, the platform is not your wild card. Access is. Breach impact, audit friction, and late-night incidents all come down to one thing: who can do what across your subscriptions, resource groups, and data planes. This guide shows how to turn Azure’s RBAC, ABAC, PIM, and access reviews into an operating model that shrinks blast radius without slowing the work.

Who this is for: mid-senior IT pros and operators in IAM, PAM, and IGA who need steps they can defend in a change review and evidence they can hand to auditors.

What you will get:

  • Three decisions that reduce risk fast: eliminate standing privilege, right-size role scope, and treat non-human identities like power users.
  • Four 10-minute checks with portal and CLI steps to find gaps and fix them.
  • Simple KPIs your CISO will accept, so progress is visible and provable.
  • Links to depth when needed, starting with Microsoft’s Azure security fundamentals.

Read this as a field guide. Make one change this week. Measure it next week, then keep going.

Three decisions you’ll make this quarter

Why start with these decisions?
Tools don’t change outcomes by themselves. Daily choices do. In Azure, the fastest way to cut risk is to change how admin power is issued, where role scope lives, and how you treat non-human identities. Start here, then let the tools follow your intent.

1) Kill standing privilege

Why it matters
Standing admin turns any stolen token into maximum blast radius. Time-bound elevation (approval + MFA + short window) forces attackers through a gate and gives you a clean trail.

What changes

  • Scope incidents to the last activation window, not the whole subscription.
  • Reviews argue less about intent; you have approver/reason/duration.
  • Audits get easier—admin is exceptional, short-lived, and logged.

How to do it

  • Make powerful roles eligible, not active; require a ticket ID and MFA; cap activations (≈2h).
  • Keep two break-glass accounts, documented and tested monthly.
  • Run quarterly access reviews that remove unused/high-risk access (see User Access Reviews).
  • Need a business case? Point to waste + risk from over-permissioning: The hidden cost of over-provisioned access.

Quick check
% of admins active in Owner / User Access Administrator / Contributor. Target ≈0; flip to eligible with approval + MFA and a 2-hour cap.

Evidence to retain
Eligible vs. active counts (quarterly), elevation logs (who/when/why/approver), and break-glass test results.

2) Right-size role scope

Why it matters
Most “how did that happen” moments are scope math. Inheritance across management groups, subscriptions, and resource groups, plus group nesting and DataActions, can turn a harmless grant into real power three layers down. Small scopes localize mistakes. Clean attributes let you use ABAC for precision without a sprawl of custom roles.

What changes

  • Fewer subscription or management group grants that include write or delete.
  • Fewer one-off customs. More use of built-ins and a small set of versioned customs.
  • Faster approvals because reviewers see the exact scope and conditions, not only a role name.

How to do it

  • Start from the Azure RBAC overview. Prefer built-ins. Keep customs rare, versioned, and documented with intent and JSON in source control.
  • Assign at the smallest scope that still works. Lift the scope only when you can state the business reason in one sentence.
  • Where tags and attributes are consistent, add ABAC conditions to avoid new custom roles.
  • Keep tenant-wide directory roles out of resource problems. Use Microsoft’s mapping to separate the planes: RBAC and directory admin roles.
  • For data-plane precision, use ACLs when the service supports them. A common case is ADLS Gen2: Azure Data Lake Storage access control.

Quick check
If a role includes */write or */delete, justify its scope in one sentence. If you cannot, shrink it.

Evidence to retain
A quarterly list of high-scope assignments with the owner and reason. A change log for custom roles with version, diff, and linked approvals.

3) Treat NHIs like power users

Why it matters
Machine identities (service principals, managed identities, automations) don’t change jobs, don’t rotate on their own, and often hold durable rights. A compromised SPN with wildcard actions is lateral movement on rails – no MFA prompt, no human behaviors to trip.

What changes

  • Fewer SPNs with wildcard or high-scope grants.
  • Secrets rotate on a calendar (or are replaced by managed identity).
  • When an SPN is implicated, impact is bound to the smallest scope that still works.

How to do it

  • Issue NHIs explicitly (owner, purpose, expiry). Assign at the smallest scope that still works; avoid subscription-level grants.
  • Prefer managed identity; where secrets are unavoidable, store in Key Vault and rotate on a schedule.
  • Review SPNs alongside humans in every access review; remove unused rights by default.
  • Use a simple registry: SPN name, app/team owner, scopes, key/secret rotation date, next review date.

Background for your team

Quick check
What % of SPNs have wildcard rights (*) or high-scope (subscription/management group) assignments? Drive it down every sprint.

Evidence to retain
SPN registry (owner/purpose/scope/expiry), rotation logs, and quarterly deltas showing removed rights.

Moving from decisions to action

Decisions set intent; checks create momentum. Next up: Four 10-minute checks – fast portal steps and one-liners you can run this week to surface standing privilege, high-scope roles, wildcard SPNs, and zombie guests, then prove they’re shrinking.

Four 10-minute checks (fast wins before the next sprint)

Why this section exists
Decisions set direction; these checks create momentum. Each one surfaces a high-impact issue and gives you a quick path to fix it – no committee, no new tooling.

1) Admins with always-on elevation

Goal: Find people actively sitting in high-impact roles (not PIM-eligible) and flip them to eligible with approval + MFA.

Portal (fastest): 

Entra admin center → Identity Governance → Privileged Identity Management → Azure resources → open each high-impact role (Owner, User Access Administrator, Contributor, Key Vault Administrator) → Assignments → filter Active (not Eligible) → Export CSV → remove standing assignments and re-add as Eligible with approval + MFA; set Max activation duration (for example, 1 hour).
PowerShell (visibility): Get-MgDirectoryRole; then Get-MgDirectoryRoleMember for each role to sanity-check tenant-wide directory roles.

CLI (subscription RBAC): 

az role assignment list --all --include-inherited --scope /subscriptions/<subId> --query "[?roleDefinitionName=='Owner' || roleDefinitionName=='Contributor' || roleDefinitionName=='User Access Administrator'].[principalName,principalType,roleDefinitionName,scope]" -o table

What “good” looks like: >90% of high-impact roles are Eligible; every activation shows MFA + approval in PIM history.

2) High-scope roles at subscription

Goal: Replace broad subscription/management-group grants with smaller roles at RG/resource scope; call out any /write or /delete.

Portal: 

Azure portal → Subscriptions → choose subscription → Access control (IAM) → Role assignments → filter Scope = This resource and Role = Owner / Contributor / User Access Administrator (plus risky customs) → Download → re-assign at resource group or resource with least privilege; document the reason.

CLI (list grants): 

az role assignment list --scope /subscriptions/<subId> --include-inherited false --query "[].[roleDefinitionName,principalType,principalName,scope]" -o table
CLI (find customs with write/delete): az role definition list --query "[?length(permissions[?contains(join(',', actions),'/write') || contains(join(',', actions),'/delete')])>0].[name,roleName]" -o table

What “good” looks like: Declining count of subscription-scope write/delete roles; customs are versioned and justified; reviewers can explain scope in one sentence.

3) Service principals with wildcard rights

Goal: Find SPNs with broad actions or scopes; narrow to what the automation actually needs; set expiry/rotation; prefer managed identity.

Portal: 

Subscriptions → Access control (IAM) → Role assignments → filter Principal type = Service principal → inspect Owner, Contributor, or customs with data-plane DataActions → for each SPN, confirm purpose, scope, expiration → move secrets/keys to Key Vault and enable rotation → prefer Managed Identity where possible.

CLI (SPN at subscription): 

az role assignment list --scope /subscriptions/<subId> --include-inherited --query "[?principalType=='ServicePrincipal'].[principalName,roleDefinitionName,scope]" -o table
CLI (SPN at management group): az role assignment list --scope /providers/Microsoft.Management/managementGroups/<mgId> --include-inherited --query "[?principalType=='ServicePrincipal']" -o table
CLI (custom roles with wildcards): az role definition list --query "[?length(permissions[?contains(join(',', actions),'*')])>0].[name,roleName]" -o table

What “good” looks like: Percentage of SPNs with wildcard rights trends down; secrets rotate on a calendar or are replaced with managed identities; every SPN assignment has an owner and expiry.

4) Guests past expiry

Goal: End “temporary forever” and make external access deliberate, time-bound, and easy to end.

Portal: 

Entra admin center → Users → External users → add columns: Created, Last sign-in, State → filter Last sign-in > 90 days or no expiration. If you use Entitlement Management: Identity Governance → Entitlement management → Access packages → verify expiration policies and auto-remove. For guests with standing RBAC: Subscriptions → Access control (IAM) → filter Principal type = Guest → Remove or re-issue via an access package with expiry.

PowerShell (quick guest list):

Get-MgUser -Filter "userType eq 'Guest'" | Select-Object DisplayName, UserPrincipalName, AccountEnabled 

(note: pulling last sign-in via Graph requires additional permissions; default to the Portal export.)

What “good” looks like: Guests have expiry; idle guests are auto-removed; Conditional Access applies to guests; RBAC grants tied to guests are scoped and time-bound.

Pro tips to make these stick (low overhead)

  • One owner per finding. Every export gets an assignee and a date. No owner, no action.
  • Version customs. Keep role intent + JSON in source control (e.g., “Prod-App-Deploy v3”) so reviewers see purpose and change history. If you need a refresher on role design boundaries, start with Microsoft’s Azure RBAC overview.
  • Evidence shelf. Save quarterly exports, elevation logs, and review outcomes in a shared folder by quarter. For the people/process side of reviews, this primer keeps you honest: User Access Reviews.
  • Two KPIs in exec readouts. Standing privilege ↓ and Time-to-scope ↓. Leadership will back whatever moves those lines.

You’ve got owners, versions, and evidence; now prove it’s working in numbers that leadership actually cares about.

What good looks like (simple KPIs your CISO will accept)

Standing privilege ↓ – Percentage of admins with always-on elevation. If this trends downward, your blast radius is shrinking.

High-scope roles ↓ – Count of subscription/management-group grants with write/delete. Fewer here means the inheritance risk is contained.

Time-to-scope ↓ – Minutes from “credential seen” to “what can it do.” Faster = incidents are bounded and response is repeatable.

Review removals ↑ – Percentage of reviews that actually revoke access. Upward movement shows reviews remove risk, not just attest.

Translation: These four numbers prove your design is changing outcomes, not just toggling settings.

The real challenges in Azure (and how teams get unstuck)

Complexity that compounds

Inheritance flows down management groups → subscriptions → resource groups → resources. Group nesting hides who is actually in scope. Custom roles drift. A harmless-looking grant turns into broad DataActions three layers down. Microsoft’s model is the ground truth: Azure role definitions.

Get unstuck: Assign at the smallest scope that still works. Prefer built-ins from the Azure RBAC overview, keep customs rare and versioned, and verify effective permissions (not just intended assignments). For path-level precision, use service data-plane ACLs where supported, e.g., ADLS access control.

Scale that outgrows human review

Most estates now have more machine identities than people. Manual group lookups miss where power sits: the effective permissions on service principals and automations.  

Get unstuck: Treat NHIs like power users: explicit issuance, smallest viable scope, rotation/expiry by default, and include them in every review cycle. Track % of SPNs with wildcard or high-scope rights and drive it down each sprint.

Collaboration that never ends

Guest access lingers. External identities inherit roles and expand your blast radius. Baseline the mechanics with Microsoft’s B2B external collaboration overview.

Get unstuck: Issue guest access via packages with approvals and expirations, apply Conditional Access, and review quarterly. Remove stale guests or re-issue with scoped, time-bound access.

Configuration drift by default

New subscriptions land without the right policies. Exemptions stack up. Alerts get noisy. Treat policy as code and apply at management groups so every subscription starts with guardrails. (Platform baseline: Azure security fundamentals.)

Get unstuck: Put initiatives at management-group scope, require owner/reason/expiry on exemptions, and store evidence (assignments, exemptions, review results) by quarter. 

Measure Standing privilege ↓ and Time-to-scope ↓ so leadership sees progress.

Standing privilege everywhere

It’s faster to grant a big role now and promise to fix it later. Later rarely arrives.

Get unstuck: Make powerful roles eligible, not active; cap elevation windows; require ticket + MFA; and test break-glass monthly. Run access reviews that actually remove what isn’t used.

If you only keep one idea

Keep effective permissions small and provable. Everything else – RBAC vs. ABAC, ACLs, reviews, policy-as-code – exists to serve that outcome.

Bottom line

Azure gives you the controls. Outcomes come from how precisely you issue power, how small you keep effective permissions, and how easily you can prove it. Kill standing privilege, right-size scope, treat NHIs like power users, and measure what matters. Do that, and incidents get smaller, audits get easier, and your team spends more time shipping than firefighting.

Next steps

Table of Contents