Skip to main content

Azure Workload Identity

Microsoft Entra Workload ID (formerly Azure Workload Identity) lets Kubernetes pods authenticate to Azure resources without storing credentials. Pods use a Kubernetes service account token, which is exchanged for an Azure token via OIDC.

How It Works

  1. You annotate a Kubernetes ServiceAccount with the Azure Managed Identity client ID
  2. Pods using that ServiceAccount get a projected token volume
  3. The Azure Identity SDK or MSAL exchanges the token for an Azure access token
  4. Your app authenticates to Key Vault, Storage, etc., with no secrets in the cluster

Prerequisites

  • AKS 1.22+
  • Azure CLI 2.47+
  • User-assigned Managed Identity
  • OIDC issuer enabled on the cluster

Enable Workload Identity on AKS

az aks update \
--resource-group <your-resource-group> \
--name <your-aks-cluster> \
--enable-oidc-issuer \
--enable-workload-identity

Create Managed Identity

az identity create \
--resource-group <your-resource-group> \
--name <your-workload-identity>

# Get client ID
az identity show \
--resource-group <your-resource-group> \
--name <your-workload-identity> \
--query clientId -o tsv

Create Federated Credential

Link the Kubernetes ServiceAccount to the Azure Managed Identity:

az identity federated-credential create \
--name <credential-name> \
--identity-name <your-workload-identity> \
--resource-group <your-resource-group> \
--issuer <aks-oidc-issuer-url> \
--subject system:serviceaccount:<namespace>:<service-account-name> \
--audience api://AzureADTokenExchange

Get the OIDC issuer URL:

az aks show \
--resource-group <your-resource-group> \
--name <your-aks-cluster> \
--query "oidcIssuerProfile.issuerUrl" -o tsv

ServiceAccount Annotations

apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
namespace: my-namespace
annotations:
azure.workload.identity/client-id: "<managed-identity-client-id>"
azure.workload.identity/use: "true"

Pod Label

Pods must have this label for the mutating webhook to inject tokens:

labels:
azure.workload.identity/use: "true"

Grant Key Vault Access

az role assignment create \
--assignee <managed-identity-principal-id> \
--role "Key Vault Secrets User" \
--scope /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault-name>

References