Live
Handling Faster Code, Token Spikes, and Agent Guardrails in LLM ProductionAdding Cloudflare Web Search to Agents SDK: Direct Web Queries for Your Durable ObjectsWorkers Observability Events via MCP: Real‑Time Issue Delivery to WebhooksMultilingual Agent Kit Adds Go, Java, Kotlin, and TypeScript SupportScaling AI Agent Swarms: Architecture and Ops Implications for EngineersAnonymous authentication for organization‑level Dependabot registries: practical impactCloudflare Queues add immutable jurisdiction controls for data residencyOpen AI Factory Architecture: NVIDIA’s MGX 1.2 Rack Design and New DSX Tooling Arrive at OCPHandling Faster Code, Token Spikes, and Agent Guardrails in LLM ProductionAdding Cloudflare Web Search to Agents SDK: Direct Web Queries for Your Durable ObjectsWorkers Observability Events via MCP: Real‑Time Issue Delivery to WebhooksMultilingual Agent Kit Adds Go, Java, Kotlin, and TypeScript SupportScaling AI Agent Swarms: Architecture and Ops Implications for EngineersAnonymous authentication for organization‑level Dependabot registries: practical impactCloudflare Queues add immutable jurisdiction controls for data residencyOpen AI Factory Architecture: NVIDIA’s MGX 1.2 Rack Design and New DSX Tooling Arrive at OCP
Azure

Azure RBAC Explained: Roles, Assignments and Best Practices

Overview

This tutorial covers Azure Role-Based Access Control (RBAC), the authorization system that controls who can do what with Azure resources. You will learn how to assign built-in roles, create custom roles, understand scope inheritance, and apply least-privilege principles in real environments.

Prerequisites:

  • An active Azure subscription (free tier works)
  • Azure CLI installed and authenticated (az login)
  • Basic understanding of Azure resource hierarchy (Management Groups → Subscriptions → Resource Groups → Resources)

Why this matters for AZ-104: RBAC is a core domain in the Azure Administrator certification. Expect 10–15% of exam questions to touch on role assignments, scope, custom roles, and deny assignments. Getting this wrong in production leads to privilege escalation or broken deployments — examiners know this and test it heavily.

Getting Started

Verify your Azure CLI version and set your working subscription before running any RBAC commands.

# Confirm CLI version (2.50+ recommended)
az --version

# Log in interactively
az login

# List available subscriptions
az account list --output table

# Set the target subscription
az account set --subscription "your-subscription-id"

# Confirm active subscription
az account show --query "{Name:name, ID:id, State:state}" --output table

You will also need your Object ID for any user, group, or service principal you want to assign roles to. Retrieve them like this:

# Get Object ID for a specific user by UPN
az ad user show --id user@yourdomain.com --query id --output tsv

# Get Object ID for a service principal
az ad sp show --id "http://my-service-principal" --query id --output tsv

# Get Object ID for a group
az ad group show --group "DevOps-Team" --query id --output tsv

Understanding RBAC Scope and Built-In Roles

Scope defines where a role assignment applies. Azure RBAC uses four scope levels, and assignments inherit downward — a role granted at the subscription level applies to all resource groups and resources within it.

  • Management Group: /providers/Microsoft.Management/managementGroups/mg-name
  • Subscription: /subscriptions/{subscription-id}
  • Resource Group: /subscriptions/{subscription-id}/resourceGroups/{rg-name}
  • Resource: /subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/...

Azure ships with over 300 built-in roles. The four you must memorise for AZ-104 are:

  • Owner — Full access including the ability to assign roles to others
  • Contributor — Full resource management but cannot assign roles or manage access
  • Reader — View-only access across all resources in scope
  • User Access Administrator — Can manage role assignments but not resources
# List all built-in roles
az role definition list --custom-role-only false --query "[].{Name:roleName, Description:description}" --output table

# Get details of a specific built-in role
az role definition list --name "Contributor" --output json

# List current role assignments at subscription scope
az role assignment list --all --output table

# Assign the Reader role to a user at resource group scope
az role assignment create \
  --assignee "user@yourdomain.com" \
  --role "Reader" \
  --resource-group "rg-production"

# Assign Contributor to a service principal at subscription scope
az role assignment create \
  --assignee "" \
  --role "Contributor" \
  --subscription "your-subscription-id"

# Verify the assignment was created
az role assignment list \
  --assignee "user@yourdomain.com" \
  --resource-group "rg-production" \
  --output table

Common pitfall: Assigning Owner at subscription scope to a service principal used by a pipeline. If that SP is compromised, an attacker can create new role assignments. Use Contributor and grant User Access Administrator only where explicitly needed, scoped as tightly as possible.

Custom Roles and Advanced Assignments

When built-in roles are too permissive or too restrictive, you define custom roles using a JSON definition. Custom roles are scoped to a management group or subscription and can be shared across child scopes.

# Export an existing built-in role as a starting template
az role definition list --name "Virtual Machine Contributor" > vm-contributor-template.json

Create a custom role JSON file named custom-vm-operator.json:

cat > custom-vm-operator.json << 'EOF'
{
  "Name": "VM Operator",
  "Description": "Can start, stop and restart VMs but cannot create or delete them.",
  "Actions": [
    "Microsoft.Compute/virtualMachines/read",
    "Microsoft.Compute/virtualMachines/start/action",
    "Microsoft.Compute/virtualMachines/powerOff/action",
    "Microsoft.Compute/virtualMachines/restart/action",
    "Microsoft.Compute/virtualMachines/deallocate/action",
    "Microsoft.Resources/subscriptions/resourceGroups/read"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/your-subscription-id"
  ]
}
EOF
# Create the custom role
az role definition create --role-definition custom-vm-operator.json

# Confirm it exists
az role definition list --custom-role-only true --query "[].{Name:roleName}" --output table

# Assign the custom role to a group at resource group scope
az role assignment create \
  --assignee-object-id "" \
  --assignee-principal-type Group \
  --role "VM Operator" \
  --resource-group "rg-compute"

# Update the custom role (edit JSON first, then use update)
az role definition update --role-definition custom-vm-operator.json

# Delete the custom role (remove all assignments first)
az role definition delete --name "VM Operator"

Best practices for custom roles:

  • Always use NotActions sparingly — they do not behave like deny rules. A user with two roles where one grants and one NotActions the same permission will still have access if another role grants it directly.
  • Prefer AssignableScopes at the management group level for roles used across multiple subscriptions.
  • Version-control your custom role JSON files in a Git repository alongside your infrastructure-as-code.
  • Audit role assignments monthly using az role assignment list --all and flag any direct user assignments that should be converted to group assignments.

Data plane vs. management plane: Actions starting with Microsoft.Storage/storageAccounts/blobServices/containers/blobs are DataActions and control data-level access (reading blob content). Standard Actions control the management plane (creating or deleting the storage account itself). Some roles like Storage Blob Data Contributor combine both — do not confuse them with Contributor, which only covers the management plane.

# Check effective permissions for the current user
az role assignment list --all \
  --query "[?principalName=='user@yourdomain.com'].{Role:roleDefinitionName, Scope:scope}" \
  --output table

# List deny assignments (preview feature)
az rest \
  --method GET \
  --url "https://management.azure.com/subscriptions/your-subscription-id/providers/Microsoft.Authorization/denyAssignments?api-version=2022-04-01" \
  --query "value[].{Name:properties.denyAssignmentName, Principal:properties.principals[0].id}"

Exam Tips for Azure Administrator (AZ-104)

Key concepts tested on the exam:

  • RBAC assignments are additive — a user with Reader at subscription and Contributor on a resource group gets the higher permission at that resource group.
  • Deny assignments override allow assignments and can only be created by Azure Blueprints or Managed Applications, not manually via the portal or CLI.
  • The Owner role includes all Contributor permissions plus the ability to assign roles. User Access Administrator can assign roles but cannot manage resources — know the difference.
  • Classic administrator roles (Co-Administrator, Service Administrator) are legacy and map roughly to Owner — the exam may reference them in context of older subscriptions.
  • Managed Identity assignments are preferred over service principals for Azure-native workloads; the process is identical — assign a role to the managed identity's Object ID.

Common exam scenarios:

  1. A developer can read a storage account but cannot list its access keys — identify which role grants Microsoft.Storage/storageAccounts/listKeys/action (Contributor or Storage Account Key Operator Service Role).
  2. A VM must write to a Log Analytics workspace without storing credentials — use a system-assigned managed identity and assign Log Analytics Contributor to it.
  3. You need to prevent a subscription Owner from deleting a resource group — use an Azure Resource Lock (CanNotDelete or ReadOnly), not RBAC.

Quick reference commands:

# List all role assignments across the entire subscription
az role assignment list --all --output table

# Find who has Owner on a subscription
az role assignment list \
  --role "Owner" \
  --scope "/subscriptions/your-subscription-id" \
  --output table

# Remove a specific role assignment
az role assignment delete \
  --assignee "user@yourdomain.com" \
  --role "Contributor" \
  --resource-group "rg-production"

# Check all permissions a role definition includes
az role definition list --name "Storage Blob Data Contributor" \
  --query "[0].permissions[0].{Actions:actions, DataActions:dataActions}" \
  --output json

Summary

Key takeaways from this tutorial:

  • RBAC uses a scope hierarchy (Management Group → Subscription → Resource Group → Resource) with downward inheritance.
  • Assign roles to groups, not individual users, to reduce management overhead and audit complexity.
  • Built-in roles cover most scenarios — create custom roles only when you need to split permissions that no built-in role addresses cleanly.
  • Understand the distinction between Actions (management plane) and DataActions (data plane) — this is a frequent exam trap.
  • Use managed identities for workload identities instead of service principals with stored secrets wherever possible.

Next steps:

  1. Practice creating and assigning custom roles in a sandbox subscription.
  2. Explore Azure Policy alongside RBAC — Policy enforces compliance while RBAC controls access.
  3. Review Privileged Identity Management (PIM) for just-in-time role elevation, which extends RBAC for sensitive roles.

Continue your AZ-104 preparation with our related guide: AZ-104 Certification Study Guide — CloudNinjas.ca.