Stage 5 · Platform
Azure Foundations
Managed Identities
System-assigned vs user-assigned identities — the zero-secrets credential pattern.
What Are Managed Identities?
A managed identity is an Azure-managed service principal. Azure automatically handles credential management — you never see a password, never rotate a secret, and never store a certificate. The identity is tied to an Azure resource and is automatically available to that resource.
Managed identities eliminate the need to store credentials in code, environment variables, or configuration files. This is the recommended authentication pattern for all Azure-native workloads.
System-Assigned Identity
A system-assigned identity is created automatically when you enable it on an Azure resource (VM, App Service, AKS cluster, etc.). It is a 1:1 relationship — the identity exists only as long as the resource exists.
# Create a VM with a system-assigned identity
az vm create \
--resource-group rg-webapp \
--name vm-web-01 \
--image Ubuntu2204 \
--size Standard_D2s_v3 \
--assign-identity '[system]' \
--admin-username azureuser \
--generate-ssh-keys
# The output includes the principalId — this is the identity's object ID
# in Entra IDThe --assign-identity '[system]' flag enables a system-assigned managed identity. The identity's lifecycle is bound to the VM — delete the VM, delete the identity.
User-Assigned Identity
A user-assigned identity is a standalone Azure resource that you create independently. It can be assigned to multiple Azure resources simultaneously and persists independently of any resource lifecycle.
# Create a user-assigned managed identity
az identity create \
--resource-group rg-shared \
--name mi-aks-payments
# Get the principal ID
PRINCIPAL_ID=$(az identity show \
--resource-group rg-shared \
--name mi-aks-payments \
--query principalId --output tsv)
# Assign roles to the identity
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" \
--role "Key Vault Secrets User" \
--scope "/subscriptions/{sub-id}/resourceGroups/rg-payments"
# Assign the identity to a VM
az vm identity assign \
--resource-group rg-payments \
--name vm-payments-01 \
--identities "/subscriptions/{sub-id}/resourceGroups/rg-shared/providers/Microsoft.ManagedIdentity/userAssignedIdentities/mi-aks-payments"User-assigned identities are ideal for AKS workloads, where multiple pods or nodes share the same identity. They also simplify disaster recovery — the identity survives resource recreation.
System vs User Assigned
| Feature | System-Assigned | User-Assigned |
|---|---|---|
| Lifecycle | Bound to parent resource | Independent |
| One-to-many | 1:1 with resource | Shared across resources |
| Creation | Enable on existing resource | Create standalone resource |
| Use case | Single VM, App Service | AKS, multi-pod workloads |
| Cleanup | Delete parent resource | Must delete explicitly |
Using Managed Identities
Managed identities work by acquiring an OAuth2 token from the Azure Instance Metadata Service (IMDS). The IMDS is available at a well-known link-local address (169.254.169.254) from within the Azure resource.
# From inside an Azure VM with managed identity enabled:
TOKEN=$(curl -s -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" \
| jq -r '.access_token')
# Use the token to call Azure APIs
curl -s -H "Authorization: Bearer $TOKEN" \
"https://management.azure.com/subscriptions/{sub-id}/resourceGroups?api-version=2021-04-01"The IMDS endpoint is only accessible from within Azure resources. It returns tokens scoped to the resource's managed identity, with credentials that are automatically rotated.
In production code, use the Azure SDKs (e.g., DefaultAzureCredential in .NET/Python) which handle IMDS token acquisition automatically. Only use raw IMDS calls in scripts or custom runtimes.
AKS Workload Identity
Workload Identity on AKS connects Kubernetes service accounts to Azure managed identities. This lets pods authenticate to Azure services without any credentials in the pod or cluster.
# 1. Enable workload identity on AKS cluster
az aks update \
--resource-group rg-aks-prod \
--name aks-payments-prod \
--enable-oidc-issuer \
--enable-workload-identity
# 2. Get the OIDC issuer URL
ISSUER=$(az aks show \
--resource-group rg-aks-prod \
--name aks-payments-prod \
--query "oidcIssuerProfile.issuerUrl" --output tsv)
# 3. Create a user-assigned identity
az identity create --name mi-app-payments --resource-group rg-aks
# 4. Create a federated credential linking the identity to a K8s service account
az identity federated-credential create \
--name fic-app-payments \
--identity mi-app-payments \
--issuer "$ISSUER" \
--subject "system:serviceaccount:default:sa-payments"The federated credential tells Azure to trust tokens from the Kubernetes API server for the specified service account. No client secrets are involved at any point.
AAD Pod Identity was the previous approach but is now deprecated. Workload Identity is more reliable, does not require a mutating webhook, and works with standard Kubernetes RBAC.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.