Scope Inheritance at Scale

RBAC assignments flow Management Group → Subscription → Resource Group → Resource. An assignment at any level grants that permission to everything below — with no way to "revoke" it at a child scope (only deny assignments can block).

🔑 Inheritance Trade-offs

  • Broad scope (MG level): Low maintenance, but over-grants if you're not careful. One Reader at root = Reader on every resource in the tenant.
  • Narrow scope (RG/Resource): Precise least-privilege, but assignment sprawl creates management burden — hard to audit thousands of role assignments.
  • Sweet spot: Assign at Subscription level for environment-wide roles; use RG for team-specific isolation; reserve resource-level only for break-glass or service principals with single-resource access.
⚠️ Gotcha: Azure has a limit of 4,000 role assignments per subscription (and 500 per management group). At scale, prefer group-based assignments over per-user to stay under limits.

Custom Role Design Patterns

Built-in roles are coarse. When Contributor is too broad and a built-in doesn't fit, design a custom role.

🔑 When to Create a Custom Role

  • You need a subset of Contributor (e.g., can manage VMs but not delete VNets)
  • You need cross-service permissions not in any single built-in role
  • Compliance requires explicit action-level documentation of what a persona can do
Example: "App Team Deployer" Custom Role
{
  "Name": "App Team Deployer",
  "Description": "Deploy and manage App Services and Functions, read networking",
  "Actions": [
    "Microsoft.Web/*",
    "Microsoft.Network/virtualNetworks/read",
    "Microsoft.Network/virtualNetworks/subnets/join/action",
    "Microsoft.Resources/deployments/*"
  ],
  "NotActions": [
    "Microsoft.Web/sites/config/list/action"  // block reading connection strings
  ],
  "DataActions": [],
  "AssignableScopes": [
    "/subscriptions/{sub-id}/resourceGroups/rg-app-prod",
    "/subscriptions/{sub-id}/resourceGroups/rg-app-dev"
  ]
}

🔑 Scoping Custom Roles

  • AssignableScopes controls where the role can be assigned — not what resources the permissions act on (that's the assignment scope).
  • Set AssignableScopes to the Management Group if multiple subscriptions need it; narrow to subscription/RG if it's team-specific.
  • You can update AssignableScopes later without recreating the role.
⚠️ Limit: 5,000 custom roles per tenant. Plan role reuse across teams rather than one-off roles per project.

Deny Assignments

Deny assignments block specific actions even if another role assignment grants them. They override allow-based RBAC.

🔑 How Deny Assignments Work

  • Evaluated after role assignments — deny always wins.
  • Cannot be created directly by customers (today). They're applied by Azure Blueprints and Managed Applications to protect resources from modification.
  • Use case: Blueprint locks down a networking RG so even Subscription Owner can't delete the hub VNet.

📝 Exam Tip

If the exam asks "how to prevent an Owner from modifying a resource," the answer is deny assignment via Blueprint — not removing their role (you can't remove inherited Owner). Resource locks prevent deletion/modification but Owners can remove locks; deny assignments cannot be overridden.

RBAC vs Azure Policy

Both enforce governance, but they solve different problems. Getting this distinction wrong leads to architectures that fight themselves.

Dimension RBAC Azure Policy
Controls Who can do what (identity → action) What can exist / how it must be configured (resource state)
Enforcement point ARM authorization layer (before action executes) ARM resource provider (during/after deployment)
Default posture Deny-all (no access until role assigned) Allow-all (everything is allowed until policy restricts)
Scope MG / Sub / RG / Resource MG / Sub / RG (not individual resource)
Targets identity? Yes — specific user, group, SP, MI No — applies to all requests regardless of who
Can remediate? No Yes — DeployIfNotExists, Modify effects
Example "Devs can create VMs in rg-dev" "All VMs must use managed disks, everywhere"

🔑 Decision Rule

RBAC when the question is "should this person be allowed?" → identity-centric.
Policy when the question is "should this configuration be allowed?" → resource-centric.
Use both together: RBAC gates who can deploy; Policy gates what they can deploy.

PIM & Just-in-Time Access

Privileged Identity Management (PIM) converts standing access into eligible assignments that must be activated — with approval, MFA, time limits, and audit trails.

🔑 Architect Design Decisions for PIM

  • Eligible vs Active: Make high-privilege roles (Owner, User Access Admin, Key Vault Admin) eligible-only. Keep Reader/operational roles active.
  • Activation duration: Default 8 hours. For break-glass, allow up to 24h. For routine ops, 1-4h reduces blast radius.
  • Approval workflow: Require approval for production Owner; self-approve for dev Contributor.
  • Access reviews: Schedule quarterly reviews for all eligible assignments. PIM auto-removes stale access.
⚠️ License requirement: PIM requires Entra ID P2 (or Entra ID Governance). Factor this into cost discussions with stakeholders.

ABAC for Storage

Attribute-Based Access Control adds conditions to role assignments. Instead of creating dozens of custom roles, add conditions like "only blobs tagged project=alpha."

🔑 When to Use ABAC

  • Multi-tenant storage accounts where teams share a container but own different blobs
  • Restricting access based on blob index tags, container name, or encryption scope
  • Avoiding one-storage-account-per-team sprawl
Example Condition Expression
// Role: Storage Blob Data Contributor
// Condition: only act on blobs where tag "department" = assignee's department
(
  @Resource[Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags:department]
  StringEquals
  @Principal[Microsoft.Directory/CustomSecurityAttributes/department]
)

This means a user in department "Engineering" can only read/write blobs tagged department=Engineering — even though they have Data Contributor on the whole account.

🏢 Real-World: Designing Access for a 500-Person Org

Scenario: Contoso (500 people) has 4 personas — Developers (200), Ops/SRE (30), Contractors (50 rotating), Auditors (20) — across 3 environments (Dev, Staging, Prod) with 6 subscriptions and a hub-spoke network.

Access Design Solution

Structure

  • Management Group: mg-contoso → child MGs: mg-nonprod, mg-prod
  • Subscriptions: sub-dev, sub-staging under mg-nonprod; sub-prod-app, sub-prod-data under mg-prod; sub-connectivity, sub-management at mg-contoso level

Role Assignments

PersonaScopeRoleMethod
Developersmg-nonprodContributorActive (Entra group)
Developerssub-prod-appReaderActive
Developerssub-prod-appCustom "Deployer" (deploy only, no infra delete)Eligible via PIM, 2h, approval required
Ops/SREmg-contosoReaderActive
Ops/SREmg-prodContributorEligible via PIM, 4h, self-approve
Ops/SREsub-connectivityNetwork ContributorActive
Contractorsspecific RGs in sub-devCustom "Scoped Dev" (no secrets, no networking)Active, time-bound (contract end date)
Auditorsmg-contosoReaderActive
Auditorsmg-contosoSecurity ReaderActive

Guardrails (Policy, not RBAC)

  • Policy at mg-contoso: "Allowed locations = West Europe, North Europe"
  • Policy at mg-prod: "VMs must use managed disks," "Storage must have private endpoint"
  • Policy at mg-contoso: "Inherit tag: CostCenter from RG" (Modify effect)

Deny Assignment

  • Blueprint on sub-connectivity locks hub VNet, Firewall, and ExpressRoute circuit — even Ops Owner can't delete them without removing the Blueprint assignment (which requires elevated access + approval).

ABAC

  • Shared data lake in sub-prod-data: contractors get Storage Blob Data Reader with condition tags:project = their-assigned-project.

Key Takeaways

  • Assign at the right scope — broad enough for manageability, narrow enough for least-privilege.
  • Custom roles fill the gap between built-in roles; scope AssignableScopes to where they're needed.
  • Deny assignments (via Blueprints) are the only way to override inherited allow permissions.
  • RBAC = who can act. Policy = what's allowed to exist. Use both.
  • PIM eliminates standing privileged access — eligible + time-bound + auditable.
  • ABAC conditions on storage roles replace per-team storage account sprawl.

Knowledge Check