Azure RBAC runs on Azure Resource Manager and answers who may do what where.
flowchart LR P["Security principal<br/>alice@example.com"] --> A["Role assignment"] R["Role definition<br/>Reader"] --> A S["Scope<br/>rg-devops-lab"] --> A
| Part | Example |
|---|---|
| Security principal | User, group, service principal, managed identity |
| Role definition | Set of permissions: Actions, NotActions, DataActions, NotDataActions, AssignableScopes |
| Scope | Management group → subscription → resource group → resource (inherited downwards) |
| Assignment | Binds the role to the principal at the scope |
Key built-in roles
| Role | Rights |
|---|---|
| Owner | Full access and can grant access to others |
| Contributor | Create/manage every resource but cannot grant access (NotActions block Microsoft.Authorization/*/Write, */Delete) |
| Reader | View only (*/read) |
| User Access Administrator | Manages access only, not resources |
You can create custom roles (for example a Virtual Machine Operator that only starts/stops VMs). Deny assignments are created by Azure (Managed Applications, Deployment Stacks); you do not create them directly.
Traps: Contributor cannot grant access to others; a role assigned at the subscription applies to every RG below; permission changes can take a few minutes to apply.
| Command | Meaning |
|---|---|
az role definition list --name Reader |
See the role JSON |
az role assignment create --assignee alice@example.com --role Reader --scope <rg-id> |
Assign a role |
az role assignment list -g rg-devops-lab -o table |
Assignments in the RG |
How permissions combine
RBAC is additive: a user's effective rights are the union of every role assigned to them and to their groups, at the scope and above. If one assignment grants Reader and another grants Contributor on the same resource group, the user can change resources there. Only deny assignments subtract rights, and they win over role assignments.
Control plane and data plane
Actions cover management operations through Azure Resource Manager, such as creating a storage account. DataActions cover the data inside, such as reading a blob. That is why Owner of a storage account does not automatically read blobs through Entra ID authorisation; you also need a data role such as Storage Blob Data Reader or Storage Blob Data Contributor. Key Vault and Cosmos DB follow the same split.
A custom role
{
"Name": "VM Operator",
"Actions": [
"Microsoft.Compute/virtualMachines/read",
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/deallocate/action"
],
"AssignableScopes": ["/subscriptions/00000000-0000-0000-0000-000000000000"]
}
Create it with az role definition create --role-definition @vm-operator.json.
Good practice
- Assign roles to groups, not individuals.
- Use the narrowest scope that works, usually a resource group.
- Give automation a managed identity or service principal with its own minimal role.
- Use Privileged Identity Management so powerful roles are eligible and activated for a few hours with approval, rather than permanently active.
- Review assignments regularly and remove ones left from finished projects with
az role assignment delete.