Home Azure Workload Identity on Kubernetes
Post
Cancel

Azure Workload Identity on Kubernetes

Deployed workloads within Kubernetes clusters necessitate Azure AD application credentials or managed identities for accessing Azure AD protected resources, like Azure Key Vault and Microsoft Graph. Azure AD Pod Identity, previously offered a means to circumvent the requirement for such secrets through the utilization of Azure managed identities.The open source Azure AD pod-managed identity in AKS has been deprecated and the project will be archived soon. Azure AD workload identity replaces pod-managed identity.

In contrast, Azure AD Workload Identity for Kubernetes seamlessly incorporates the Kubernetes capabilities to establish federation with external identity providers. This method is much more simpler and removes the complexity of AAD Pod Identities.

Authentication Sequence using OIDC

Authentication Sequence Courtesy: microsoft.com

How to deploy and configure AKS cluster

Microsoft Docs - workload-identity-deploy-cluster

How to retrieve the OIDC Issuer URL

1
az aks show -n myAKSCluster -g "${RESOURCE_GROUP}" --query "oidcIssuerProfile.issuerUrl" -otsv

By default, the Issuer is set to use the base URL https://{region}.oic.prod-aks.azure.com/{uuid} where the value for {region} matches the location the AKS cluster is deployed in. The value {uuid} represents the OIDC key.

OIDC Endpoints

  • {IssuerURL}/.well-known/openid-configuration Also known as the OIDC discovery document. This contains the metadata about the issuer’s configurations.

  • {IssuerURL}/openid/v1/jwks This contains the public signing key(s) that AAD uses to verify the authenticity of the service account token.

Create Federated identity credential

1
az identity federated-credential create --name ${FEDERATED_IDENTITY_CREDENTIAL_NAME} --identity-name "${USER_ASSIGNED_IDENTITY_NAME}" --resource-group "${RESOURCE_GROUP}" --issuer "${AKS_OIDC_ISSUER}" --subject system:serviceaccount:"${SERVICE_ACCOUNT_NAMESPACE}":"${SERVICE_ACCOUNT_NAME}" --audience api://AzureADTokenExchange

Service Account token mount location

The azure identity token is mounted at below location by default but this can be changed in the pod manifests.

1
/var/run/secrets/azure/tokens/azure-identity-token

The regular kubernetes serviceaccount token is mounted at: /var/run/secrets/kubernetes.io/serviceaccount

Environment Variables

  • AZURE_AUTHORITY_HOST The Azure Active Directory (AAD) endpoint.
  • AZURE_CLIENT_ID The client ID of the AAD application or user-assigned managed identity.
  • AZURE_TENANT_ID The tenant ID of the registered AAD application or user-assigned managed identity.
  • AZURE_FEDERATED_TOKEN_FILE The path of the projected service account token file.

Volume injected by the webhook

  • azure-identity-token The projected service account volume.

These values can be verified by running kubectl describe pod command

Jump pod manifest for verifying Kubernetes service account token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: jump
  namespace: ${NAMESPACE}
spec:
  containers:
  - image: smallstep/step-cli
    name: step-cli
    command:
    - /bin/sh
    - -c
    - cat /var/run/secrets/tokens/test-token | step crypto jwt inspect --insecure
    volumeMounts:
    - mountPath: /var/run/secrets/tokens
      name: test-token
  serviceAccountName: ${SERVICE_ACCOUNT_NAME}
  volumes:
  - name: test-token
    projected:
      sources:
      - serviceAccountToken:
          path: test-token
          expirationSeconds: 3600
          audience: test
EOF

The jump pod logs will contain the decoded JWT.

Note that the values like audience, expirationSeconds etc can be customized in the manifest while the azure-identity-token behaviour can be modified adding custom labels on the pod.

Jump pod for verifying access token

1
2
3
kubectl run az-cli -n default -l "azure.workload.identity/use=true" --image=mcr.microsoft.com/azure-cli -i --tty --rm --command /usr/bin/env --overrides='{"spec": { "serviceAccount": "workload-identity-sa" }}' -- sh
az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID
az account get-access-token

How to check the pod is labeled

1
kubectl get pods -A -o json | jq -r '["Namespace", "Pod-Name"], (.items[] | select(.metadata.labels."azure.workload.identity/use" == "true") | [.metadata.namespace, .metadata.name]) | @tsv' | column -t

Get all deployments with the labels on

1
kubectl get deployments --all-namespaces -o json | jq -r '.items[] | select(.spec.template.metadata.labels."azure.workload.identity/use" == "true") | "\(.metadata.namespace) \(.metadata.name)"'

Token comparison

Displayed below are three decoded tokens arranged side by side: the first is a standard service account token, the middle one represents an Azure identity token, and the third corresponds to an Azure access token. Token Comparison

Limitations

  • You can only have 20 federated identity credentials per managed identity.

Bookmarks

Microsoft Docs

Azure Workload Identity Gihub Pages

Deploy Script

Sample Application

Unveiling the Construction of This Blog

TechDocs in Backstage