Migrate from pod managed-identity to workload identity
This article focuses on migrating from a pod-managed identity to Microsoft Entra Workload ID for your Azure Kubernetes Service (AKS) cluster. It also provides guidance depending on the version of the Azure Identity client library used by your container-based application.
If you aren't familiar with Microsoft Entra Workload ID, see the following Overview article.
Before you begin
The Azure CLI version 2.47.0 or later. Run az --version
to find the version, and run az upgrade
to upgrade the version. If you need to install or upgrade, see Install Azure CLI.
Migration scenarios
This section explains the migration options available depending on what version of the Azure Identity SDK is installed.
For either scenario, you need to have the federated trust set up before you update your application to use the workload identity. The following are the minimum steps required:
- Create a managed identity credential.
- Associate the managed identity with the kubernetes service account already used for the pod-managed identity or create a new Kubernetes service account and then associate it with the managed identity.
- Establish a federated trust relationship between the managed identity and Microsoft Entra ID.
Migrate from latest version
If your application is already using the latest version of the Azure Identity SDK, perform the following steps to complete the authentication configuration:
- Deploy workload identity in parallel with pod-managed identity. You can restart your application deployment to begin using the workload identity, where it injects the OIDC annotations into the application automatically.
- After verifying the application is able to authenticate successfully, you can remove the pod-managed identity annotations from your application and then remove the pod-managed identity add-on.
Migrate from older version
If your application isn't using the latest version of the Azure Identity SDK, you have two options:
You can use a migration sidecar that we provide within your Linux applications, which proxies the IMDS transactions your application makes over to OpenID Connect (OIDC). The migration sidecar isn't intended to be a long-term solution, but a way to get up and running quickly on workload identity. Perform the following steps to:
- Deploy the workload with migration sidecar to proxy the application IMDS transactions.
- Verify the authentication transactions are completing successfully.
- Schedule the work for the applications to update there SDK's to a supported version.
- Once the SDK's are updated to the supported version, you can remove the proxy sidecar and redeploy the application.
Note
The migration sidecar is not supported for production use. This feature is meant to give you time to migrate your application SDK's to a supported version, and not meant or intended to be a long-term solution. The migration sidecar is only available for Linux containers, due to only providing pod-managed identities with Linux node pools.
Rewrite your application to support the latest version of the Azure Identity client library. Afterwards, perform the following steps:
- Restart your application deployment to begin authenticating using the workload identity.
- Once you verify the authentication transactions are completing successfully, you can remove the pod-managed identity annotations from your application and then remove the pod-managed identity add-on.
Create a managed identity
If you don't have a managed identity created and assigned to your pod, perform the following steps to create and grant the necessary permissions to storage, Key Vault, or whatever resources your application needs to authenticate with in Azure.
Use the Azure CLI az account set command to set a specific subscription to be the current active subscription. Then use the az identity create command to create a managed identity.
az account set --subscription "subscriptionID"
az identity create --name "userAssignedIdentityName" --resource-group "resourceGroupName" --location "location" --subscription "subscriptionID"
export USER_ASSIGNED_CLIENT_ID="$(az identity show --resource-group "resourceGroupName" --name "userAssignedIdentityName" --query 'clientId' -otsv)"
Grant the managed identity the permissions required to access the resources in Azure it requires. For information on how to do this, see Assign a managed identity access to a resource.
To get the OIDC Issuer URL and save it to an environmental variable, run the following command. Replace the default values for the cluster name and the resource group name.
export AKS_OIDC_ISSUER="$(az aks show --name myAKSCluster --resource-group myResourceGroup --query "oidcIssuerProfile.issuerUrl" -o tsv)"
The variable should contain the Issuer URL similar to the following example:
https://eastus.oic.prod-aks.azure.com/00000000-0000-0000-0000-000000000000/00000000-0000-0000-0000-000000000000/
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.
Create Kubernetes service account
If you don't have a dedicated Kubernetes service account created for this application, perform the following steps to create and then annotate it with the client ID of the managed identity created in the previous step. Use the az aks get-credentials command and replace the values for the cluster name and the resource group name.
az aks get-credentials --name myAKSCluster --resource-group "${RESOURCE_GROUP}"
Copy and paste the following multi-line input in the Azure CLI.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: ${USER_ASSIGNED_CLIENT_ID}
name: ${SERVICE_ACCOUNT_NAME}
namespace: ${SERVICE_ACCOUNT_NAMESPACE}
EOF
The following output resembles successful creation of the identity:
Serviceaccount/workload-identity-sa created
Establish federated identity credential trust
Use the az identity federated-credential create command to create the federated identity credential between the managed identity, the service account issuer, and the subject. Replace the values resourceGroupName
, userAssignedIdentityName
, federatedIdentityName
, serviceAccountNamespace
, and serviceAccountName
.
az identity federated-credential create --name federatedIdentityName --identity-name userAssignedIdentityName --resource-group resourceGroupName --issuer ${AKS_OIDC_ISSUER} --subject system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME} --audience api://AzureADTokenExchange
Note
It takes a few seconds for the federated identity credential to be propagated after being initially added. If a token request is made immediately after adding the federated identity credential, it might lead to failure for a couple of minutes as the cache is populated in the directory with old data. To avoid this issue, you can add a slight delay after adding the federated identity credential.
Deploy the workload with migration sidecar
Note
The migration sidecar is not supported for production use. This feature is meant to give you time to migrate your application SDK's to a supported version, and not meant or intended to be a long-term solution. The migration sidecar is only for Linux containers as pod-managed identities was available on Linux node pools only.
If your application is using managed identity and still relies on IMDS to get an access token, you can use the workload identity migration sidecar to start migrating to workload identity. This sidecar is a migration solution and in the long-term applications, you should modify their code to use the latest Azure Identity SDKs that support client assertion.
To update or deploy the workload, add these pod annotations only if you want to use the migration sidecar. You inject the following annotation values to use the sidecar in your pod specification:
azure.workload.identity/inject-proxy-sidecar
- value istrue
orfalse
azure.workload.identity/proxy-sidecar-port
- value is the desired port for the proxy sidecar. The default value is8000
.
When a pod with the above annotations is created, the Azure Workload Identity mutating webhook automatically injects the init-container and proxy sidecar to the pod spec.
The webhook that is already running adds the following YAML snippets to the pod deployment. The following is an example of the mutated pod spec:
apiVersion: v1
kind: Pod
metadata:
name: httpbin-pod
labels:
app: httpbin
azure.workload.identity/use: "true"
annotations:
azure.workload.identity/inject-proxy-sidecar: "true"
spec:
serviceAccountName: workload-identity-sa
initContainers:
- name: init-networking
image: mcr.microsoft.com/oss/azure/workload-identity/proxy-init:v1.1.0
securityContext:
capabilities:
add:
- NET_ADMIN
drop:
- ALL
privileged: true
runAsUser: 0
env:
- name: PROXY_PORT
value: "8000"
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
- name: proxy
image: mcr.microsoft.com/oss/azure/workload-identity/proxy:v1.1.0
ports:
- containerPort: 8000
This configuration applies to any configuration where a pod is being created. After updating or deploying your application, you can verify the pod is in a running state using the kubectl describe pod command. Replace the value podName
with the image name of your deployed pod.
kubectl describe pods podName
To verify that pod is passing IMDS transactions, use the kubectl logs command. Replace the value podName
with the image name of your deployed pod:
kubectl logs podName
The following log output resembles successful communication through the proxy sidecar. Verify that the logs show a token is successfully acquired and the GET operation is successful.
I0926 00:29:29.968723 1 proxy.go:97] proxy "msg"="starting the proxy server" "port"=8080 "userAgent"="azure-workload-identity/proxy/v0.13.0-12-gc8527f3 (linux/amd64) c8527f3/2022-09-26-00:19"
I0926 00:29:29.972496 1 proxy.go:173] proxy "msg"="received readyz request" "method"="GET" "uri"="/readyz"
I0926 00:29:30.936769 1 proxy.go:107] proxy "msg"="received token request" "method"="GET" "uri"="/metadata/identity/oauth2/token?resource=https://management.core.windows.net/api-version=2018-02-01&client_id=<client_id>"
I0926 00:29:31.101998 1 proxy.go:129] proxy "msg"="successfully acquired token" "method"="GET" "uri"="/metadata/identity/oauth2/token?resource=https://management.core.windows.net/api-version=2018-02-01&client_id=<client_id>"
Remove pod-managed identity
After you've completed your testing and the application is successfully able to get a token using the proxy sidecar, you can remove the Microsoft Entra pod-managed identity mapping for the pod from your cluster, and then remove the identity.
Run the az aks pod-identity delete command to remove the identity from your pod. This should only be done after all pods in the namespace using the pod-managed identity mapping have migrated to use the sidecar.
az aks pod-identity delete --name podIdentityName --namespace podIdentityNamespace --resource-group myResourceGroup --cluster-name myAKSCluster
Next steps
This article showed you how to set up your pod to authenticate using a workload identity as a migration option. For more information about Microsoft Entra Workload ID, see the following Overview article.
Azure Kubernetes Service