Join our Newsletter — 33% off our NHI Course
Home› Guides› AKS Workload Identity Guide: Configuring Pod Federation Step…
Guide Non-Human Identity (NHI)

AKS Workload Identity Guide: Configuring Pod Federation Step by Step

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 13 November 2026 16 min read
On this page

Pods on Azure Kubernetes Service still reach Azure with client secrets in Kubernetes Secrets or through node-level identities that every pod on the node can borrow, when the platform can federate each workload to its own identity instead. Microsoft Entra Workload ID lets a pod present a Kubernetes service account token, signed by the cluster's OIDC issuer, and exchange it for a Microsoft Entra access token without any stored secret. This guide is the step-by-step setup: enabling the issuer and webhook, creating the managed identity and federated credential, wiring the service account and pod, testing, migrating off pod-managed identity, and rolling back. It is written for platform engineers and Kubernetes administrators who run AKS Standard clusters. Cluster-wide identity hardening, Entra integration for human access and local account control are covered in the AKS Identity Hardening Guide.

This is an independent guide from NHI Mgmt Group, based on Microsoft's public AKS and Microsoft Entra Workload ID documentation as of November 2026. It is not sponsored or reviewed by Microsoft. Product features change, so confirm settings against Microsoft's current documentation.

Key takeaways

  • Three objects make the trust: the cluster OIDC issuer URL, a federated identity credential on a user-assigned managed identity (or app registration), and a Kubernetes service account whose namespace and name form the subject system:serviceaccount:<namespace>:<name>.
  • The pod must opt in: the mutating webhook only acts on pods labelled azure.workload.identity/use: "true", and only then injects AZURE_FEDERATED_TOKEN_FILE and the projected token volume.
  • The subject is the security boundary: anyone who can run a pod under that service account in that namespace gets the identity, so namespace RBAC and service account creation rights matter as much as Azure roles.
  • Expect propagation delays: federated credentials take seconds to minutes to replicate and Azure role assignments up to 10 minutes, so build retries into tests and pipelines rather than treating the first failure as a misconfiguration.
  • Pod-managed identity is finished: the open source project was deprecated on 24 October 2022 and the AKS add-on was supported through September 2025, so migrate with the parallel deployment path and treat the proxy sidecar as a short bridge only.

How the token exchange works

Workload ID uses Kubernetes service account token volume projection. The cluster acts as an OIDC issuer and publishes two endpoints: {IssuerURL}/.well-known/openid-configuration (discovery document) and {IssuerURL}/openid/v1/jwks (the RS256 public signing keys). When the application asks for a token, the Azure Identity library reads the projected service account token from the file named in AZURE_FEDERATED_TOKEN_FILE and sends it to Microsoft Entra ID as a client assertion. Entra ID fetches the cluster's keys, validates the signature, then checks the token's iss, sub and aud claims against a federated identity credential on the target identity. If all three match, it returns an access token for the requested resource.

ComponentWhere it livesWhat it contributesValue to record
OIDC issuerAKS cluster property oidcIssuerProfile.issuerUrlSigns projected service account tokens and publishes the keysIssuer URL, format https://{region}.oic.prod-aks.azure.com/{tenant_id}/{uuid}
Mutating admission webhookCluster add-on, enabled with --enable-workload-identityInjects environment variables and the token volume into labelled podsWebhook configuration ConfigMap azure-wi-webhook-config
User-assigned managed identityAzure resource groupThe Entra identity the pod becomes; holds Azure role assignmentsClient ID and principal (object) ID
Federated identity credentialChild resource of the managed identityDeclares which issuer, subject and audience may sign in as the identityName, issuer, subject, audience api://AzureADTokenExchange
Kubernetes service accountNamespace in the clusterCarries the azure.workload.identity/client-id annotation and defines the token subjectNamespace and name
PodDeployment, StatefulSet or JobUses the service account and the opt-in labelserviceAccountName and label

Two lifetimes are in play. The projected service account token defaults to 3,600 seconds (configurable from 3,600 to 86,400 with an annotation) and Kubernetes refreshes the file in place, so code must re-read the file each time rather than cache it. The Entra access token is separate, and Microsoft's overview states it expires 24 hours after issue. Scopes must use the v2 form <resource>/.default, for example https://management.azure.com/.default; a bare resource URI can fail. The general model, including other platforms that use the same pattern, is explained in the Workload Identity Federation Guide.

Prerequisites and design decisions before you start

  • Versions: Kubernetes 1.22 or later and Azure CLI 2.47.0 or later for Workload ID. On AKS Automatic clusters the OIDC issuer and Workload ID are preconfigured. For new AKS Standard clusters on Kubernetes 1.34 and later the OIDC issuer is enabled by default; existing clusters need it enabled manually.
  • Client libraries: minimum Azure Identity versions are Azure.Identity 1.9.0 (.NET), azidentity 1.3.0 (Go), azure-identity 1.9.0 (Java), @azure/identity 3.2.0 (Node.js), azure-identity 1.13.0 (Python) and azure-identity-cpp 1.6.0 (C++). Older code is the main reason migrations stall.
  • Permissions: you need rights to create the managed identity and federated credential, and a role that can create role assignments at the target scope, such as Role Based Access Control Administrator. Microsoft notes that Contributor and Key Vault Contributor cannot create role assignments.
  • Unsupported cases: the virtual nodes add-on is not supported, and creating federated credentials on user-assigned managed identities is not supported in the Malaysia South region (create the identity in a supported region instead).

Choosing the identity mapping

MappingHow it is builtUse whenTrade-off
One-to-oneOne service account, one managed identity, one federated credentialDefault for every production workloadMore identities to manage, but each role assignment reflects one workload
Many-to-oneSeveral service accounts each have a federated credential on the same identityReplicas of the same app across namespaces or clustersCounts against the limit of 20 federated credentials per identity; a breach in any namespace reaches the shared permissions
One-to-manyOne service account, several identities, selected by changing the client ID annotationA tool that genuinely needs different identities at different timesHarder to reason about in reviews; changing the annotation needs a pod restart

Prefer a user-assigned managed identity over an app registration for workloads in your own tenant: there is no secret or certificate to manage alongside the federated credential, and the identity lives in a resource group with normal Azure RBAC over who can change it. Keep the kubelet identity and cluster identity out of application access entirely; their roles and IMDS exposure are dealt with in the Azure Managed Identities Security Guide.

Step-by-step configuration

The commands below follow Microsoft's deployment tutorial. Replace the variables with your own naming standard; examples here use a dedicated namespace rather than default.

  1. Enable the OIDC issuer and Workload ID. For a new cluster:
    az aks create --resource-group "$RG" --name "$CLUSTER" \
      --enable-oidc-issuer --enable-workload-identity --generate-ssh-keys
    For an existing cluster run az aks update --resource-group "$RG" --name "$CLUSTER" --enable-oidc-issuer --enable-workload-identity. Enabling the issuer on an existing cluster restarts the API server, causing brief downtime, and the issuer cannot be disabled once enabled. Schedule it in a change window.
  2. Record the issuer URL.
    export AKS_OIDC_ISSUER="$(az aks show --name "$CLUSTER" --resource-group "$RG" \
      --query "oidcIssuerProfile.issuerUrl" --output tsv)"
    The trailing slash is part of the value. Copy it exactly: leading or trailing whitespace in the federated credential issuer blocks the exchange.
  3. Create the user-assigned managed identity and capture its client ID and principal ID:
    az identity create --name "$UAMI" --resource-group "$RG" --location "$LOCATION"
    export CLIENT_ID="$(az identity show -g "$RG" -n "$UAMI" --query clientId -o tsv)"
    export PRINCIPAL_ID="$(az identity show -g "$RG" -n "$UAMI" --query principalId -o tsv)"
  4. Create the service account with the client ID annotation:
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: orders-api
      namespace: orders
      annotations:
        azure.workload.identity/client-id: "<CLIENT_ID>"
    The azure.workload.identity/tenant-id annotation is optional and defaults to the tenant in the webhook ConfigMap.
  5. Create the federated identity credential.
    az identity federated-credential create --name orders-api-aks-prod \
      --identity-name "$UAMI" --resource-group "$RG" \
      --issuer "$AKS_OIDC_ISSUER" \
      --subject system:serviceaccount:orders:orders-api \
      --audience api://AzureADTokenExchange
    Microsoft describes api://AzureADTokenExchange as the default and recommended audience and advises against changing it. The credential name is 3 to 120 characters and cannot be changed later, so encode cluster and workload in it. Mismatched values are accepted at creation and only fail at sign-in.
  6. Grant least-privilege Azure roles to the identity's principal ID at the narrowest scope, for example a single key vault rather than its resource group:
    az role assignment create --assignee-object-id "$PRINCIPAL_ID" \
      --assignee-principal-type ServicePrincipal \
      --role "Key Vault Secrets User" --scope "$KEYVAULT_ID"
    Microsoft's tutorial uses a vault with Azure RBAC authorisation and purge protection enabled.
  7. Label the pod and reference the service account. In the Deployment's pod template set serviceAccountName: orders-api and the label azure.workload.identity/use: "true". In application code use DefaultAzureCredential or WorkloadIdentityCredential from a supported library; never hard-code the token path, which the docs show only as an illustration.
  8. Verify. Run kubectl describe pod and confirm the injected AZURE_CLIENT_ID, AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE variables and the projected volume. Then check application logs for a successful call. Microsoft's sample image ghcr.io/azure/azure-workload-identity/msal-go reads a Key Vault secret and logs "successfully got secret" when the chain works.

Optional annotations worth knowing

AnnotationSet onDefaultUse
azure.workload.identity/client-idService accountNoneSelects the identity; required in practice
azure.workload.identity/tenant-idService accountAZURE_TENANT_ID from the webhook ConfigMapIdentity registered in another tenant
azure.workload.identity/service-account-token-expirationService account or pod (pod wins)3600 secondsKeep the default unless a workload cannot refresh; maximum 86,400
azure.workload.identity/skip-containersPodToken added to all containersKeep the token out of sidecars that do not need Azure, for example istio-proxy
azure.workload.identity/inject-proxy-sidecarPodfalseTemporary migration proxy for code that still calls IMDS
azure.workload.identity/proxy-sidecar-portPod8000Change only if the port clashes

Use skip-containers deliberately. Every container that receives the token file can become the identity, so a logging or service mesh sidecar that never calls Azure should not hold it.

Infrastructure as code and automation

  • Create credentials sequentially: concurrent creation of several federated credentials under the same managed identity can return HTTP 409 Conflict. The AzureRM Terraform provider from version 3.40.0 creates them sequentially; in ARM or Bicep loops use serial mode or dependsOn chains.
  • Respect throttling: Microsoft documents create and update limits of 10 per second per tenant, 2 per second per subscription and 0.25 per second per resource, with HTTP 429 when exceeded.
  • Keep the subject in code review: treat the namespace and service account name in the federated credential as a security-relevant value, owned by the same repository that defines the Kubernetes service account, so a rename in one place is caught in the other.
  • Add retries: early token requests can fail with AADSTS70021: No matching federated identity record found for presented assertion while the credential replicates. Pipelines that deploy and immediately smoke-test should wait and retry.
  • Restrict who can add credentials: Microsoft publishes an Azure Policy rule that denies the resource type Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials. Assign it with exemptions for the subscriptions or resource groups where platform pipelines are allowed to create them. See the Azure Policy and Management Groups Guide.

Migrating from pod-managed identity

Microsoft Entra pod-managed identity worked by running Node Managed Identity (NMI) on every node to intercept calls to the Instance Metadata Service and decide which pod could have which identity, selected by the aadpodidbinding label. Microsoft states that the open source project was deprecated on 24 October 2022 and archived in September 2023, and that the AKS add-on was patched and supported through September 2025. Clusters still running it are past that support window.

SituationMigration pathStepsLimits
Application already on a supported Azure Identity versionParallel deploymentCreate identity, federated credential and service account; restart the deployment; verify; remove pod identity annotations; remove the add-onLowest risk; recommended default
Older SDK, Linux containers, need timeMigration sidecarAdd inject-proxy-sidecar: "true"; webhook adds proxy-init and proxy containers that translate IMDS calls; verify; schedule SDK upgrade; remove sidecarLinux only; Microsoft states it is not intended for long-term production use
Older SDK, long-term fixRewriteUpgrade the library; test with pod identity; restart; verify Workload ID; remove pod identityMost effort; no proxy overhead and works for Windows containers

The most common code change is the scope format. ManagedIdentityCredential used the IMDS resource parameter, while WorkloadIdentityCredential calls the Entra v2 endpoint with scope, so https://vault.azure.net becomes https://vault.azure.net/.default. Once every workload is verified, remove the pod identity with az aks pod-identity delete for each binding and then disable the add-on, so NMI stops intercepting IMDS traffic.

Testing, rollback and day-two operations

  1. Pilot one non-critical workload in a non-production cluster, with the old credential still in place, and confirm the new identity in Entra sign-in logs before removing anything.
  2. Cut over by restart: annotation changes on the service account only take effect after a pod restart, which also makes rollback straightforward: revert the manifest and restart.
  3. Rollback per workload: remove the label and restore the previous credential source. Keep any secret you are replacing disabled rather than deleted until the workload has run cleanly through at least one token refresh cycle, then delete and revoke it. For secrets held in Kubernetes see How to migrate Kubernetes secrets to an external Secrets Manager.
  4. Cluster-level rollback: az aks update --disable-workload-identity removes the webhook. The OIDC issuer stays, because it cannot be disabled.
  5. Rotate the issuer signing keys with az aks oidc-issuer rotate-signing-keys. Old and new keys stay valid for 24 hours; to invalidate the old key at once, Microsoft says to rotate twice and restart pods that use projected tokens. Do this after any suspected key exposure and on a planned schedule.
  6. Identity bindings: if you adopt AKS identity bindings, the webhook sets the token audience to api://AKSIdentityBinding. A workload that also needs direct federation must project a second token with audience api://AzureADTokenExchange; reusing the binding token fails with AADSTS700212.

Detection and measurement

  • Azure Activity Log: alert on writes and deletes to federatedIdentityCredentials resources and on role assignment writes for workload identities. A new federated credential with an unfamiliar issuer is a persistence path, because whoever controls that issuer can sign in as the identity. Route the logs as described in the Azure Monitor, Activity Log and Diagnostic Settings Guide.
  • Entra sign-in logs: managed identity sign-ins show which identities are used and from which resources; a workload identity that stops appearing after a cutover is a candidate for removal.
  • Kubernetes audit logs: watch creation of service accounts, changes to azure.workload.identity/client-id annotations and pods created with an unexpected serviceAccountName in namespaces that hold federated subjects.
  • Periodic audit: list every federated credential, its issuer and subject, and confirm the issuer is a cluster you still run. The process is set out in How to audit Entra workload identity federated credentials.
MetricTargetWhy it matters
Share of AKS workloads calling Azure that use Workload ID100% for new workloads; rising quarter on quarterMeasures removal of stored secrets
Client secrets or certificates still mounted for Azure accessFalling to zeroEach one is a long-lived credential that can leak
Federated credentials whose issuer is not a live clusterZeroOrphaned trust left after cluster deletion
Identities shared by more than one namespaceDocumented exceptions onlyShared identities widen blast radius
Workload identities with roles above resource-level scopeZero without approvalSubscription-wide roles defeat per-pod identity

Common failure patterns

  • Missing pod label: the service account is annotated but pods lack azure.workload.identity/use: "true", so nothing is injected and the library falls back to another credential, sometimes the node's.
  • Subject drift: a namespace or service account is renamed and the federated credential is not, producing silent sign-in failures; or a broad shared service account is reused across apps, so one subject grants every app's permissions.
  • Namespace rights ignored: developers who can create pods in a namespace can run any pod under any service account there. Restrict pod creation in namespaces whose service accounts map to privileged identities; see the Kubernetes RBAC Guide.
  • Testing too fast: pipelines fail immediately after creating the credential or role assignment, engineers widen roles to "fix" it, and the wider role is never reverted.
  • Sidecar left in place: the migration proxy becomes permanent, keeping IMDS-style calls alive and delaying the library upgrade it was meant to buy time for.
  • Orphaned trust: clusters are deleted but their federated credentials remain on identities that still hold roles.

Framework mapping

FrameworkReferenceHow Workload ID supports it
NIST CSF 2.0PR.AA-01, PR.AA-05Workload credentials are managed by the organisation; permissions scoped per workload
NIST SP 800-53 Rev 5IA-9 Service Identification and Authentication; IA-5 Authenticator Management; AC-6 Least Privilege; AU-6 Audit Record ReviewEach service authenticates with its own short-lived token; no stored authenticator; narrow role scope; review of federated credential changes
MITRE ATT&CKT1552.005 Cloud Instance Metadata API; T1528 Steal Application Access Token; T1078.004 Cloud AccountsRemoves reliance on node metadata credentials; short token lifetimes limit stolen token value; monitoring of identity use and new trusts

Practitioner checklist

  • Enable the OIDC issuer and Workload ID on each AKS Standard cluster in a change window, and record the issuer URL in your identity inventory.
  • Create one user-assigned managed identity per workload by default, with a federated credential whose name encodes cluster and workload.
  • Use the subject system:serviceaccount:<namespace>:<name> and the audience api://AzureADTokenExchange exactly.
  • Assign Azure roles to the identity at resource scope, never subscription scope without approval.
  • Label pods with azure.workload.identity/use: "true", use skip-containers for sidecars, and upgrade to the minimum Azure Identity versions.
  • Restrict pod creation and service account changes in namespaces that hold federated subjects.
  • Migrate every pod-managed identity binding, remove the add-on, and set a removal date for any migration sidecar.
  • Assign an Azure Policy deny on federated credential creation outside platform-owned scopes.
  • Alert on federated credential writes and audit issuers quarterly for clusters that no longer exist.
  • Rotate OIDC issuer signing keys on a schedule and twice after any suspected compromise.

Standards and references

Related NHI Mgmt Group resources: AKS Identity Hardening Guide · Workload Identity Federation Guide · Kubernetes Service Account Token Guide · Azure Managed Identities Security Guide · Kubernetes Workload Identity Checklist

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 13 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.