Workload Identity integration
Context: All about "workload identity"
Workload Identity is an easy yet powerful way to federate a workload in Kubernetes with rights in Azure.
The official documentation by Microsoft is available here: https://azure.github.io/azure-workload-identity/docs/
The differences between service account, managed identity, pod identity and workload identity
Identity management in Azure is an advanced topic, and even more so when coupled with Kubernetes.
Let's start by demystifying some common concept:
- Service account: Special type of account that is intended to represent a non-human entity such as an application, API, or other service. There are three types of service accounts native to Azure Active Directory: Managed identities, service principals, and user-based service accounts.
- Managed identity: Automatically managed identity in Azure Active Directory (Azure AD) for applications to use when connecting to resources that support Azure AD authentication. All credentials are managed by Azure ! (unlike service principals). Also it is an azure resource, so it needs to be located in a resource group, and the RBAC can be easily managed.
- Pod identity: Deprecated. Old way to bind an Azure managed identity with a Kubernetes workload. It has been replaced by workload identity.
- Workload identity: integrates with the capabilities native to Kubernetes to federate with external identity providers. It is a managed identity that federate a workload in kubernetes.
What are the benefits of using a workload identity ?
In short, a workload identity is an Azure Managed Identity that federates a workload in Kubernetes. So we get all the advantages of a managed identity (especially managed credentials and security), and an easy way to propagate the managed id rights in Azure to a workload in kubernetes.
For example, a workload identity can be used by a pod in Kubernetes to mount a secret in an Azure Keyvault. That's the use case we use in the tutorial section below.
Limitations
The Microsoft documentation "Managed identities for Azure resources frequently asked questions" have a section "Limitation" with all the detailed capabilities and limitations: https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/managed-identities-faq#limitations
Some important facts are:
- Managed identities can be used in multiple regions. While user assigned managed identities are created as regional resources the associated service principal (SP) created in Azure AD is available globally.
- Managed identities cannot be used in multiple Tenants.
- Managed identities limits have dependencies on Azure service limits, Azure Instance Metadata Service (IMDS) limits, and Azure Active Directory service limits.
- Managed identities cannot be moved to another resource group/region.
K8saas Workload Identity as a service
Our architecture
The service account in the kubernetes cluster is k8saas-customer-sa-workload-id in the namespace customer-namespaces.
How to ask for a workload identity
To have a dedicated workload idenity federated in your Kubernetes cluster, please Use the dedicated Postit item "Request k8saas Workload Identity "
Once completed your managed identity will be visible in Azure in your cluster resource group.
How to see your workload identity
Login to Azure portal and search at the top for the resource "Managed identity".
You should see the managed identity.
You need to have Devops right on the cluster to be able to see the workload identity. If you can't, contact your cluster service owner to be added to the cluster's devops Azure AD group.
How to give rights to your workload identity
Now that you have reader permission to the managed identity, you can get the corresponding principal id and client id.
You can assign rbac rights from the az cli
using these credentials.
Or in the Azure portal, select one of your resource, select IAM, Add role assignment, and select your user assigned managed identity.
How to use your workload identity in your kubernetes cluster
Although it depends of your end-goals, the minimum is to refer your kubernetes service account (which is federated by the managed identity) and add the label azure.workload.identity/use: "true"
to your pods.
Tutorial: Mount Azure keyvault secrets using workload identity
This tutorial show a simple interaction with an Azure Keyvault. But it is one of many use cases for workload idenities. In fact workload identities can be used to interact from within your Kubernetes cluster to any Azure components (Databases for examples).
Alright ! Let's get down to business with a simple but real-world example: mount a secret from your Azure key vault in a pod of your kubernetes cluster using a workload identity.
Prerequisites
In this example you'll need to already have your own Azure keyvault or be able to create one in the same tenant as the managed identity.
The two conditions for this tutorial are:
- Own an Azure keyvault or be able to create one in the same tenant as the managed identity
- Have Devops right on the kubernetes cluster
Give permission to the Managed identity in Azure
Check that you have access to your managed identity in Azure. On the portal, select Managed Identity, and select your managed identity:
Then, we'll give it access to your keyvault. For this, you'll need to have access to an existing keyvault or be able to create one for the duration of this tutorial.
On the keyvault screen, select the menu blade "Access Control (IAM)", and click on "+ Add" to add a new role assignment:
We'll choose the role Key Vault Secret User
so the managed identity can access the secrets content:
And then assign the role to your managed identity:
Review+Assign, and hop ! Your managed identity can read secrets in the keyvault, and therefore the federated service account in your kubernetes cluster.
Mount secret in Azure
Create an example secret
In your Azure Keyvault, create an example secret wid-tuto-password
with for value a randomly generated string, for example q7F35R}+>6)Cwy#
:
Then we'll mount the secret in a pod in your kubernetes cluster.
Log in to your pod using az cli
:
INSTANCE_NAME=<YOUR-INSTANCE-NAME> #example: teh-sandbox
az login
az aks get-credentials --resource-group k8saas-$INSTANCE_NAME --name k8saas-$INSTANCE_NAME --overwrite-existing
Then check your federated service account (with the name and namespace from the postit ticket):
kubectl get serviceaccount k8saas-customer-sa-workload-id -n customer-namespaces -o yaml
You can see in the template that service account has for reference the managed identity:
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: AZURE-MANAGED-IDENTITY-PRINCIPAL-ID
name: k8saas-customer-sa-workload-id
namespace: customer-namespaces
Now, set up some environment variables:
export KEYVAULT_URL="https://YOUR_KEYVAULT_NAME.vault.azure.net/" #ex: https://my-teh-client-keyvault.vault.azure.net/
export KEYVAULT_SECRET_NAME="wid-tuto-password"
export KEYVAULT_NAME="YOUR_KEYVAULT_NAME" #ex: my-teh-client-keyvault
export KEYVAULT_RESOURCE_GROUP="YOUR_KEYVAULT_RESOURCE_GROUP" #ex: my-teh-rg
export USER_ASSIGNED_IDENTITY_NAME="YOUR_WORKLOAD_ID" #ex: k8saas-teh-c-334-1-sandbox-customer-workload-id
export SERVICE_ACCOUNT_NAMESPACE="YOUR_SERVICE_ACCOUNT" # ex: customer-namespaces
export SERVICE_ACCOUNT_NAME="YOUR NAMESPACE" #ex: k8saas-customer-sa-workload-id
Let's create a pod that mount the secrets, using these variables:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: tutorial-wid-keyvault-pod
namespace: ${SERVICE_ACCOUNT_NAMESPACE}
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: ${SERVICE_ACCOUNT_NAME}
containers:
- image: ghcr.io/azure/azure-workload-identity/msal-go
name: oidc
env:
- name: KEYVAULT_URL
value: ${KEYVAULT_URL}
- name: SECRET_NAME
value: ${KEYVAULT_SECRET_NAME}
nodeSelector:
kubernetes.io/os: linux
EOF
# pod/tutorial-wid-keyvault-pod created
The most important part to notice in the pod definition template are:
- the label
azure.workload.identity/use: "true"
- the field
spec.serviceAccountname
with the name of the federated kubernetes service account
Finally let's see if the secret was mounted successfully in the pod
kubectl logs tutorial-wid-keyvault-pod --container oidc -n customer-namespaces
# I0720 21:30:16.494254 1 main.go:63] "successfully got secret" secret="q7F35R}+>6)Cwy#"
Bravo ! You can see the Azure Keyvault secret value in the pod logs !
To go further
Here is the Microsoft documentation on :
- the use of Azure AD workload identity with Azure Kubernetes Services: https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview
- Mount Azure Keyvault secrets as kubernetes secrets with csi driver and workload identity: https://learn.microsoft.com/en-us/azure/aks/csi-secrets-store-identity-access