Use Azure Workload Identity to allow your Kubernetes pods to access Azure Key Vault without managing long-lived secrets. This method uses federated identity credentials between your Kubernetes Service Account and an Azure AD Application or User-Assigned Managed Identity.
Prerequisites
- AKS Cluster: Version 1.21+ with OIDC Issuer enabled.
- Secrets Store CSI Driver: v1.1.0 or higher.
- Azure Key Vault Provider: v1.1.0 or higher.
- Azure CLI: version
2.40.0 or higher.
Setup Steps
1. Create an Identity
Either create an Azure AD Application (Service Principal) or a User-Assigned Managed Identity:
Azure AD Application:
export APPLICATION_NAME="<your application name>"
az ad sp create-for-rbac --name "${APPLICATION_NAME}"
export APPLICATION_CLIENT_ID=$(az ad sp list --display-name ${APPLICATION_NAME} --query '[0].appId' -otsv)
User-Assigned Managed Identity:
export RESOURCE_GROUP=<resource group name>
export USER_ASSIGNED_IDENTITY_NAME="<your user-assigned managed identity name>"
az identity create -g ${RESOURCE_GROUP} -n ${USER_ASSIGNED_IDENTITY_NAME}
export USER_ASSIGNED_IDENTITY_CLIENT_ID=$(az identity show -g ${RESOURCE_GROUP} -n ${USER_ASSIGNED_IDENTITY_NAME} --query clientId -otsv)
2. Grant Key Vault Permissions
Assign the necessary permissions to the identity to access keys, secrets, or certificates:
# Replace $KEYVAULT_NAME and the identity ID with your values
az keyvault set-policy -n $KEYVAULT_NAME --key-permissions get --spn ${IDENTITY_CLIENT_ID}
az keyvault set-policy -n $KEYVAULT_NAME --secret-permissions get --spn ${IDENTITY_CLIENT_ID}
az keyvault set-policy -n $KEYVAULT_NAME --certificate-permissions get --spn ${IDENTITY_CLIENT_ID}
3. Establish Federated Identity Credential
First, retrieve your AKS OIDC issuer URL:
export SERVICE_ACCOUNT_ISSUER=$(az aks show --resource-group <resource_group> --name <cluster_name> --query "oidcIssuerProfile.issuerUrl" -otsv)
Then, create the federation based on your identity type:
For Azure AD Application:
export SERVICE_ACCOUNT_NAME=<name of the service account>
export SERVICE_ACCOUNT_NAMESPACE=<namespace of the service account>
export APPLICATION_OBJECT_ID="$(az ad app show --id ${APPLICATION_CLIENT_ID} --query id -otsv)"
cat <<EOF > params.json
{
"name": "kubernetes-federated-credential",
"issuer": "${SERVICE_ACCOUNT_ISSUER}",
"subject": "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}",
"description": "Kubernetes service account federated credential",
"audiences": [
"api://AzureADTokenExchange"
]
}
EOF
az ad app federated-credential create --id "${APPLICATION_OBJECT_ID}" --parameters @params.json
For User-Assigned Managed Identity:
az identity federated-credential create \
--name "kubernetes-federated-credential" \
--identity-name "${USER_ASSIGNED_IDENTITY_NAME}" \
--resource-group "${RESOURCE_GROUP}" \
--issuer "${SERVICE_ACCOUNT_ISSUER}" \
--subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}"
4. Deploy SecretProviderClass
In your SecretProviderClass, set usePodIdentity: "false" and provide the clientID of your identity.