CloudOpsGuide
azure

Azure Identity and Access Management: Complete Guide

Intermediate
16 minutes
October 2026
CloudOpsGuide Team

Azure Identity and Access Management: Complete Guide

Master Azure IAM — RBAC roles, managed identities, service principals, and access control patterns for secure cloud operations.

Table of Contents

Identity Types

TypePurposeWhere
UserHuman accountsMicrosoft Entra ID
Service PrincipalApp/service identityMicrosoft Entra ID
Managed IdentityAzure-managed SPAzure resource-linked
GroupCollection of usersMicrosoft Entra ID

Azure RBAC

Role-Based Access Control controls what identities can do on Azure resources.

Built-in Roles

RoleScopePermissions
OwnerFull access + manage accessEverything
ContributorFull resource accessCan't grant access
ReaderView-onlyRead only
User Access AdministratorManage accessRBAC only

Common Workload Roles

Azure Kubernetes Service Cluster Admin Role   — manage AKS
Storage Blob Data Contributor                   — read/write blobs
Key Vault Secrets Officer                       — manage secrets
Virtual Machine Contributor                     — manage VMs
Network Contributor                             — manage networking

Scopes

/subscriptions/{sub-id}                          — subscription level
/subscriptions/{sub-id}/resourceGroups/{rg}      — resource group level
/subscriptions/.../resourceGroups/{rg}/providers/... — resource level

Always assign at the lowest scope possible.

Managed Identities

The preferred way for Azure services to authenticate — no credentials to manage.

Types

System-AssignedUser-Assigned
LifecycleTied to resourceIndependent
Multi-resourceNoYes
Use caseSimple, single serviceShared identity across services

Enable System-Assigned

# Enable on a VM
az vm identity assign -g my-rg -n my-vm

# Enable on an AKS cluster
az aks update -g my-rg -n my-cluster --enable-managed-identity

Use in Code

// C# — Azure SDK picks up managed identity automatically
var credential = new DefaultAzureCredential();
var client = new SecretClient(new Uri("https://myvault.vault.azure.net/"), credential);
# Python
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient

credential = DefaultAzureCredential()
client = SecretClient(vault_url="https://myvault.vault.azure.net/", credential=credential)

Service Principals

When managed identities can't be used (CI/CD pipelines, Terraform, external tools).

Create

az ad sp create-for-rbac \
  --name terraform-sp \
  --role Contributor \
  --scopes /subscriptions/{sub-id}/resourceGroups/my-rg

Terraform Authentication

export ARM_CLIENT_ID="..."
export ARM_CLIENT_SECRET="..."
export ARM_SUBSCRIPTION_ID="..."
export ARM_TENANT_ID="..."

Or use Azure CLI authentication (for local dev):

az login

Better: Workload Identity Federation

No secrets at all — uses OIDC tokens from GitHub Actions/Azure DevOps:

az ad app federated-credential create \
  --id <app-object-id> \
  --parameters '{
    "name": "github-federated",
    "issuer": "https://token.actions.githubusercontent.com",
    "subject": "repo:myorg/myrepo:ref:refs/heads/main",
    "audiences": ["api://AzureADTokenExchange"]
  }'

Role Assignments

Assign a Role

az role assignment create \
  --assignee <principal-id> \
  --role "Storage Blob Data Contributor" \
  --scope /subscriptions/{sub-id}/resourceGroups/my-rg

List Assignments

# Who has access to a resource group
az role assignment list --resource-group my-rg --output table

# What roles does a user have
az role assignment list --assignee user@example.com --output table

Remove an Assignment

az role assignment delete \
  --assignee <principal-id> \
  --role "Contributor" \
  --scope /subscriptions/{sub-id}/resourceGroups/my-rg

Best Practices

1. Prefer Managed Identities

# Don't do this — secrets to manage
az ad sp create-for-rbac --name my-app --role Contributor

# Do this instead — no secrets
az vm identity assign -g my-rg -n my-vm
az role assignment create \
  --assignee $(az vm show -g my-rg -n my-vm --query identity.principalId -o tsv) \
  --role Reader \
  --scope /subscriptions/{sub-id}

2. Minimum Privilege

# Bad — Contributor on entire subscription
--role Contributor --scope /subscriptions/{sub-id}

# Good — specific role on specific RG
--role "Storage Blob Data Contributor" \
--scope /subscriptions/{sub-id}/resourceGroups/my-rg

3. Use Groups, Not Individuals

# Create a group for team access
az ad group create --display-name "AKS-Admins" --mail-nickname aksadmins

# Assign role to the group
az role assignment create \
  --assignee $(az ad group show -g "AKS-Admins" --query id -o tsv) \
  --role "Azure Kubernetes Service Cluster Admin" \
  --scope /subscriptions/{sub-id}

4. Review Regularly

# Find all assignments on a subscription
az role assignment list --all --output table > access-review.csv

Common Patterns

AKS Accessing ACR

# Give AKS's kubelet identity pull access to ACR
az aks update -g my-rg -n my-cluster --attach-acr my-acr

Terraform Service Principal

SP=$(az ad sp create-for-rbac --name tf-sp --role Contributor --scopes /subscriptions/{sub-id})
export ARM_CLIENT_ID=$(echo $SP | jq -r .appId)
export ARM_CLIENT_SECRET=$(echo $SP | jq -r .password)
export ARM_TENANT_ID=$(echo $SP | jq -r .tenant)
export ARM_SUBSCRIPTION_ID="{sub-id}"

App Service Reading Key Vault

# Enable managed identity
az webapp identity assign -g my-rg -n my-app

# Grant Key Vault access
az keyvault set-policy \
  --name my-vault \
  --object-id $(az webapp show -g my-rg -n my-app --query identity.principalId -o tsv) \
  --secret-permissions get list

GitHub Actions with OIDC

# .github/workflows/deploy.yml
permissions:
  id-token: write
  contents: read

steps:
  - uses: azure/login@v2
    with:
      client-id: ${{ secrets.AZURE_CLIENT_ID }}
      tenant-id: ${{ secrets.AZURE_TENANT_ID }}
      subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
  # No client_secret needed — OIDC handles auth

Troubleshooting

"Insufficient privileges" errors

# Check what role the caller has
az role assignment list --assignee <id> --all --output table

Managed identity not working

# Verify the identity exists
az vm show -g my-rg -n my-vm --query identity
# Check the role assignment was created
az role assignment list --assignee $(az vm show -g my-rg -n my-vm --query identity.principalId -o tsv)

Service principal expired

az ad app credential reset --id <app-id>

Related Articles


Last Updated: October 2026
Author: CloudOpsGuide Team
Difficulty: Intermediate
Estimated Reading Time: 16 minutes