Azure RBAC, scope & deny assignments
Inheritance, the roles that grant access, deny wins.
Azure RBAC looks simple — assign a role to a principal at a scope — but the security details are in the scope hierarchy, which roles can grant access, and the deny assignments that override grants.
Scope, inheritance, and the roles that grant access
A role assignment binds a principal to a role definition at a scope: management group, subscription, resource group, or a single resource. Assignments inherit downward, so Contributor at a subscription applies to every resource beneath it — which is why a broad assignment high up is dangerous. Two built-in roles can create role assignments themselves: Owner and User Access Administrator. Anyone holding them can grant themselves or others more access, so treat those two as privileged and audit who has them, everywhere.
# Prefer a specific built-in role at the narrowest scope over Contributor on a sub.az role assignment create \--assignee-object-id $APP_MI \--role "Key Vault Secrets User" \--scope /subscriptions/SUB/resourceGroups/rg/providers/Microsoft.KeyVault/vaults/app-kv# Audit who can grant access (the escalation-capable roles):az role assignment list --all --include-inherited \--query "[?roleDefinitionName=='Owner' || roleDefinitionName=='User Access Administrator']"
Deny assignments and custom roles
Deny assignments explicitly block actions for specified principals and take precedence over any granting role — they are how managed applications and Azure Blueprints protect resources even from Owners. When no built-in role fits, define a custom role with exactly the actions needed rather than reaching for Contributor. And avoid basic over-grants: Contributor can change almost any resource, so scope it or replace it with a purpose-built role.