Azure RBAC
Grant the minimum required access at management group, subscription, resource group, or resource scope.
Build scalable, auditable identity infrastructure using groups, managed identities, and Privileged Identity Management.
Use This Skill When
- The user needs role assignment design or access error diagnosis
- The user wants to secure team access or workload permissions
- The user needs compliance-ready access governance (audit trail, reviews)
- The user wants to migrate from per-user to group-based RBAC
Context: RBAC Maturity
Immature: Ad hoc assignments, direct user permissions, no audit trail
Developing: Some group-based access, manual reviews, audit logs exist
Managed: Group-based RBAC, scoped assignments, automated access reviews, PIM for elevation → Target
Optimized: Zero Trust with managed identities, ephemeral access, real-time risk-based access decisions
Required Inputs
- Principals: Users, groups, service principals, managed identities
- Required actions: Specific operations (create, delete, read, write)
- Resource scope: Subscription, resource group, or individual resource
- Compliance needs: Audit trail required? Access reviews? Time-bound access?
- Escalation model: Who approves elevated access? How long is it valid?
Decision Tree
Is this human access (person) or workload identity (application)?
├─ Human:
│ ├─ Is this just viewing resources? → Reader role
│ ├─ Is this deploying/configuring? → Contributor role (at resource group scope)
│ ├─ Is this infrastructure admin work? → PIM-eligible Owner (with approval)
│ └─ Is this on a single resource? → Role-scoped to that resource
└─ Workload:
├─ Is this a new app? → Create user-assigned managed identity, assign narrow role
├─ Needs secret access? → Key Vault Secrets User role
├─ Needs storage access? → Storage Blob Data Contributor (scoped)
└─ Needs database? → SQL DB Contributor (scoped)
Should this access be permanent or temporary?
├─ Permanent → Standard role assignment (group-based for humans)
└─ Temporary/Elevated → PIM-eligible role (approval workflow, 4-hour max)
How many users need this access?
├─ 1-2 people → Consider if per-user assignment is necessary
├─ 3+ people → MUST use security group assignment
└─ 10+ people → Automate group membership from identity provider
Workflow
Phase 1: Map Workload to Required Roles
Identify actions needed:
Workload: Web App
├─ Needs: Read secrets from Key Vault
├─ Needs: Write logs to Storage Account
├─ Needs: Query SQL Database
├─ Needs: Read configuration from App Configuration
└─ Needs: Call downstream API (no Azure role, only app auth)
Match to built-in roles (prefer over custom):
- Key Vault Secrets User (for secret read)
- Storage Blob Data Contributor (for write to blob)
- SQL DB Contributor (for database access)
- App Configuration Data Reader (for config)
Prefer built-in roles unless none match exactly:
✓ Use: "Key Vault Secrets User" (specific, audited)
✓ Use: "Storage Blob Data Contributor" (Microsoft-maintained)
✗ Avoid: Custom role with Microsoft.Storage/*
✗ Avoid: Contributor role (too broad)
Phase 2: Human Access (Groups & PIM)
Create security groups for role assignment:
# Azure AD group for developers
az ad group create --display-name "contoso-app-developers" --mail-nickname "app-devs"
# Add users to group
az ad group member add --group app-devs --member-id $USER_ID
Assign group to role at correct scope:
# Resource group scope (can deploy resources in group)
az role assignment create \
--role "Contributor" \
--assignee-object-id $GROUP_ID \
--scope "/subscriptions/$SUBID/resourceGroups/$RG"
# Single resource scope (can configure only this resource)
az role assignment create \
--role "Key Vault Secrets User" \
--assignee-object-id $GROUP_ID \
--scope "/subscriptions/$SUBID/resourceGroups/$RG/providers/Microsoft.KeyVault/vaults/$KV"
Use PIM for elevated access (Owner, Admin):
# Make group eligible for Owner role (requires approval to activate)
az rest --method post --uri "https://graph.microsoft.com/v1.0/privilegedIdentityManagement/roleAssignments" \
--body '{"roleDefinitionId":"'$OWNER_ROLE_ID'","principalId":"'$GROUP_ID'","resourceId":"'$SCOPE'","type":"eligible"}'
Set up access reviews (quarterly):
# Schedule review of all role assignments
# Portal: Azure AD > Identity Governance > Access Reviews
# Review: "Do these developers still need this access?"
Phase 3: Workload Identity (Managed Identities)
Create managed identity:
# System-assigned (tied to one resource)
az webapp identity assign --resource-group $RG --name $APP_NAME
# User-assigned (reusable across resources)
az identity create --resource-group $RG --name $IDENTITY_NAME
Assign minimal roles:
# Get managed identity object ID
PRINCIPAL_ID=$(az identity show --resource-group $RG --name $IDENTITY_NAME --query principalId)
# Grant only Key Vault Secrets User (not full contributor)
az role assignment create \
--role "Key Vault Secrets User" \
--assignee-object-id $PRINCIPAL_ID \
--scope /subscriptions/$SUBID/resourceGroups/$RG/providers/Microsoft.KeyVault/vaults/$KV
Use access from app (no credentials needed):
// .NET example: Managed identity token obtained automatically
var credential = new DefaultAzureCredential();
var kvClient = new SecretClient(new Uri("https://$KV.vault.azure.net"), credential);
var secret = await kvClient.GetSecretAsync("MySecret");
Phase 4: Custom Roles (Rare)
Create only if no built-in role fits:
{
"Name": "Application Configuration Reader",
"Description": "Read app config but cannot create/delete",
"Actions": [
"Microsoft.AppConfiguration/configurationStores/read",
"Microsoft.AppConfiguration/configurationStores/keyValues/read"
],
"NotActions": [],
"DataActions": [],
"AssignableScopes": [
"/subscriptions/SUBID"
]
}
Apply custom role:
az role definition create --role-definition @custom-role.json
Phase 5: Audit & Remediation
List all role assignments:
# All assignments in subscription
az role assignment list --all --output table
# Flag: Owner roles that should be PIM-eligible
az role assignment list --all --query "[?roleDefinitionName=='Owner']"
Find overpermissioned identities:
# Identities with Contributor (too broad)
az role assignment list --all --query "[?roleDefinitionName=='Contributor']"
# Action: Replace with scoped, specific roles
Set up recurring access review:
- Quarterly: Does each identity still need this access?
- Remove: Identities no longer used
- Reduce: Downgrade Contributor → specific roles
Output Contract
Access Model Design
- Human access via security groups (group IDs, members)
- Workload access via managed identities (system/user-assigned)
- Elevated access via PIM (approval workflow)
Role Mapping
- Principal → Role → Scope
- Justification for each assignment
- Built-in vs. custom rationale
Implementation Plan
- CLI/PowerShell commands (ready to copy/paste)
- Order of operations (dependencies)
- Validation steps (verify permissions work)
Governance & Audit
- Access review cadence (quarterly)
- Who approves elevated access? (PIM approvers)
- Audit log destination (Log Analytics workspace)
Migration Path (if consolidating old assignments)
- Current state (existing assignments)
- Target state (new group-based model)
- Per-user assignments to retire
- Timeline and testing plan
Practical Examples
Example 1: Web App + Managed Identity
Workload: ASP.NET app reads secrets from Key Vault, writes logs to Storage
1. Create system-assigned managed identity on App Service
2. Assign roles:
- Key Vault Secrets User (scope: Key Vault)
- Storage Blob Data Contributor (scope: logs container)
3. In code: new DefaultAzureCredential() fetches token automatically
4. No credentials in config
Example 2: Developer Team with PIM
Team: 5 developers need temporary admin access for troubleshooting
1. Create "contoso-admins" security group, add developers
2. Make group PIM-eligible for Owner role (approval required)
3. Developer clicks "Activate Role" in portal
4. Admin gets email to approve
5. 4-hour access granted, auto-revokes after
6. Audit trail in Activity Log
Example 3: Service-to-Service Access
Pattern: Microservice A calls Microservice B in AKS
1. Create user-assigned managed identity "service-a-identity"
2. AKS pod runs with this identity (via workload identity)
3. Service B checks incoming token for identity
4. No secrets, credentials, or connection strings needed
Guardrails
- Avoid Owner role: Only use for emergency escalation; make it PIM-eligible with approval.
- Avoid Contributor role: Replace with scoped, specific roles (e.g., Storage Blob Data Contributor).
- Never assign per-user: Use groups for 3+ users; automate group sync from identity provider.
- Use managed identities for workloads: No secrets in config, automatic credential rotation.
- Scope assignments narrowly: Assign at resource group, not subscription, when possible.
- Require MFA for elevated access: PIM + MFA for Owner, Admin, or sensitive resource roles.
- Audit quarterly: Access reviews, remove unused identities, downgrade overpermissioned accounts.
- Document why: Each elevated permission must have clear business justification.
1---2name: azure-rbac3description: Design and apply Azure role-based access control with least privilege at the right scope. Use this skill when users ask about permissions, role assignments, access errors, or governance. Covers built-in roles, custom roles, managed identities, PIM, and access reviews per Well-Architected principles.4---56# Azure RBAC78Grant the minimum required access at management group, subscription, resource group, or resource scope.9Build scalable, auditable identity infrastructure using groups, managed identities, and Privileged Identity Management.1011## Use This Skill When1213- The user needs role assignment design or access error diagnosis14- The user wants to secure team access or workload permissions15- The user needs compliance-ready access governance (audit trail, reviews)16- The user wants to migrate from per-user to group-based RBAC1718## Context: RBAC Maturity1920**Immature**: Ad hoc assignments, direct user permissions, no audit trail 21**Developing**: Some group-based access, manual reviews, audit logs exist 22**Managed**: Group-based RBAC, scoped assignments, automated access reviews, PIM for elevation → **Target** 23**Optimized**: Zero Trust with managed identities, ephemeral access, real-time risk-based access decisions2425## Required Inputs2627- **Principals**: Users, groups, service principals, managed identities28- **Required actions**: Specific operations (create, delete, read, write)29- **Resource scope**: Subscription, resource group, or individual resource30- **Compliance needs**: Audit trail required? Access reviews? Time-bound access?31- **Escalation model**: Who approves elevated access? How long is it valid?3233## Decision Tree3435```36Is this human access (person) or workload identity (application)?37├─ Human:38│ ├─ Is this just viewing resources? → Reader role39│ ├─ Is this deploying/configuring? → Contributor role (at resource group scope)40│ ├─ Is this infrastructure admin work? → PIM-eligible Owner (with approval)41│ └─ Is this on a single resource? → Role-scoped to that resource42└─ Workload:43 ├─ Is this a new app? → Create user-assigned managed identity, assign narrow role44 ├─ Needs secret access? → Key Vault Secrets User role45 ├─ Needs storage access? → Storage Blob Data Contributor (scoped)46 └─ Needs database? → SQL DB Contributor (scoped)4748Should this access be permanent or temporary?49├─ Permanent → Standard role assignment (group-based for humans)50└─ Temporary/Elevated → PIM-eligible role (approval workflow, 4-hour max)5152How many users need this access?53├─ 1-2 people → Consider if per-user assignment is necessary54├─ 3+ people → MUST use security group assignment55└─ 10+ people → Automate group membership from identity provider56```5758## Workflow5960### Phase 1: Map Workload to Required Roles61621. **Identify actions needed**:63 ```64 Workload: Web App65 ├─ Needs: Read secrets from Key Vault66 ├─ Needs: Write logs to Storage Account67 ├─ Needs: Query SQL Database68 ├─ Needs: Read configuration from App Configuration69 └─ Needs: Call downstream API (no Azure role, only app auth)70 ```71722. **Match to built-in roles** (prefer over custom):73 ```74 - Key Vault Secrets User (for secret read)75 - Storage Blob Data Contributor (for write to blob)76 - SQL DB Contributor (for database access)77 - App Configuration Data Reader (for config)78 ```79803. **Prefer built-in roles** unless none match exactly:81 ```82 ✓ Use: "Key Vault Secrets User" (specific, audited)83 ✓ Use: "Storage Blob Data Contributor" (Microsoft-maintained)84 ✗ Avoid: Custom role with Microsoft.Storage/*85 ✗ Avoid: Contributor role (too broad)86 ```8788### Phase 2: Human Access (Groups & PIM)89901. **Create security groups** for role assignment:91 ```bash92 # Azure AD group for developers93 az ad group create --display-name "contoso-app-developers" --mail-nickname "app-devs"94 95 # Add users to group96 az ad group member add --group app-devs --member-id $USER_ID97 ```98992. **Assign group to role at correct scope**:100 ```bash101 # Resource group scope (can deploy resources in group)102 az role assignment create \103 --role "Contributor" \104 --assignee-object-id $GROUP_ID \105 --scope "/subscriptions/$SUBID/resourceGroups/$RG"106 107 # Single resource scope (can configure only this resource)108 az role assignment create \109 --role "Key Vault Secrets User" \110 --assignee-object-id $GROUP_ID \111 --scope "/subscriptions/$SUBID/resourceGroups/$RG/providers/Microsoft.KeyVault/vaults/$KV"112 ```1131143. **Use PIM for elevated access** (Owner, Admin):115 ```bash116 # Make group eligible for Owner role (requires approval to activate)117 az rest --method post --uri "https://graph.microsoft.com/v1.0/privilegedIdentityManagement/roleAssignments" \118 --body '{"roleDefinitionId":"'$OWNER_ROLE_ID'","principalId":"'$GROUP_ID'","resourceId":"'$SCOPE'","type":"eligible"}'119 ```1201214. **Set up access reviews** (quarterly):122 ```bash123 # Schedule review of all role assignments124 # Portal: Azure AD > Identity Governance > Access Reviews125 # Review: "Do these developers still need this access?"126 ```127128### Phase 3: Workload Identity (Managed Identities)1291301. **Create managed identity**:131 ```bash132 # System-assigned (tied to one resource)133 az webapp identity assign --resource-group $RG --name $APP_NAME134 135 # User-assigned (reusable across resources)136 az identity create --resource-group $RG --name $IDENTITY_NAME137 ```1381392. **Assign minimal roles**:140 ```bash141 # Get managed identity object ID142 PRINCIPAL_ID=$(az identity show --resource-group $RG --name $IDENTITY_NAME --query principalId)143 144 # Grant only Key Vault Secrets User (not full contributor)145 az role assignment create \146 --role "Key Vault Secrets User" \147 --assignee-object-id $PRINCIPAL_ID \148 --scope /subscriptions/$SUBID/resourceGroups/$RG/providers/Microsoft.KeyVault/vaults/$KV149 ```1501513. **Use access from app** (no credentials needed):152 ```csharp153 // .NET example: Managed identity token obtained automatically154 var credential = new DefaultAzureCredential();155 var kvClient = new SecretClient(new Uri("https://$KV.vault.azure.net"), credential);156 var secret = await kvClient.GetSecretAsync("MySecret");157 ```158159### Phase 4: Custom Roles (Rare)1601611. **Create only if no built-in role fits**:162 ```json163 {164 "Name": "Application Configuration Reader",165 "Description": "Read app config but cannot create/delete",166 "Actions": [167 "Microsoft.AppConfiguration/configurationStores/read",168 "Microsoft.AppConfiguration/configurationStores/keyValues/read"169 ],170 "NotActions": [],171 "DataActions": [],172 "AssignableScopes": [173 "/subscriptions/SUBID"174 ]175 }176 ```1771782. **Apply custom role**:179 ```bash180 az role definition create --role-definition @custom-role.json181 ```182183### Phase 5: Audit & Remediation1841851. **List all role assignments**:186 ```bash187 # All assignments in subscription188 az role assignment list --all --output table189 190 # Flag: Owner roles that should be PIM-eligible191 az role assignment list --all --query "[?roleDefinitionName=='Owner']"192 ```1931942. **Find overpermissioned identities**:195 ```bash196 # Identities with Contributor (too broad)197 az role assignment list --all --query "[?roleDefinitionName=='Contributor']"198 199 # Action: Replace with scoped, specific roles200 ```2012023. **Set up recurring access review**:203 - Quarterly: Does each identity still need this access?204 - Remove: Identities no longer used205 - Reduce: Downgrade Contributor → specific roles206207## Output Contract2082091. **Access Model Design**210 - Human access via security groups (group IDs, members)211 - Workload access via managed identities (system/user-assigned)212 - Elevated access via PIM (approval workflow)2132142. **Role Mapping**215 - Principal → Role → Scope216 - Justification for each assignment217 - Built-in vs. custom rationale2182193. **Implementation Plan**220 - CLI/PowerShell commands (ready to copy/paste)221 - Order of operations (dependencies)222 - Validation steps (verify permissions work)2232244. **Governance & Audit**225 - Access review cadence (quarterly)226 - Who approves elevated access? (PIM approvers)227 - Audit log destination (Log Analytics workspace)2282295. **Migration Path** (if consolidating old assignments)230 - Current state (existing assignments)231 - Target state (new group-based model)232 - Per-user assignments to retire233 - Timeline and testing plan234235## Practical Examples236237### Example 1: Web App + Managed Identity238239**Workload**: ASP.NET app reads secrets from Key Vault, writes logs to Storage240241```2421. Create system-assigned managed identity on App Service2432. Assign roles:244 - Key Vault Secrets User (scope: Key Vault)245 - Storage Blob Data Contributor (scope: logs container)2463. In code: new DefaultAzureCredential() fetches token automatically2474. No credentials in config248```249250### Example 2: Developer Team with PIM251252**Team**: 5 developers need temporary admin access for troubleshooting253254```2551. Create "contoso-admins" security group, add developers2562. Make group PIM-eligible for Owner role (approval required)2573. Developer clicks "Activate Role" in portal2584. Admin gets email to approve2595. 4-hour access granted, auto-revokes after2606. Audit trail in Activity Log261```262263### Example 3: Service-to-Service Access264265**Pattern**: Microservice A calls Microservice B in AKS266267```2681. Create user-assigned managed identity "service-a-identity"2692. AKS pod runs with this identity (via workload identity)2703. Service B checks incoming token for identity2714. No secrets, credentials, or connection strings needed272```273274## Guardrails275276- **Avoid Owner role**: Only use for emergency escalation; make it PIM-eligible with approval.277- **Avoid Contributor role**: Replace with scoped, specific roles (e.g., Storage Blob Data Contributor).278- **Never assign per-user**: Use groups for 3+ users; automate group sync from identity provider.279- **Use managed identities for workloads**: No secrets in config, automatic credential rotation.280- **Scope assignments narrowly**: Assign at resource group, not subscription, when possible.281- **Require MFA for elevated access**: PIM + MFA for Owner, Admin, or sensitive resource roles.282- **Audit quarterly**: Access reviews, remove unused identities, downgrade overpermissioned accounts.283- **Document why**: Each elevated permission must have clear business justification.