Workload ID, Part 2: Practical Configuration & Best Practices

29.05

In part 1 of this blog post, we explained why traditional methods using secrets or certificates for authentication from AKS to Azure are problematic. We introduced Microsoft Entra Workload ID as the modern, secret-less solution and took a look under the bonnet at the OIDC federation and token exchange process. 

Now that the basics are clear, it’s time to get practical. In this second part, we’ll dive into the specific configuration steps, the pitfalls to watch out for, and best practices. Let’s get started!

How do you set up Workload ID? 

Setting up Workload ID involves configuration in both Azure and Kubernetes. Here are the six steps. 

1. Activate the OIDC Issuer on AKS 

First, check if the OIDC issuer feature is already enabled on your AKS cluster. This is a prerequisite, so don’t skip it! 

There are two options: either during the creation of your cluster (with –enable-oidc-issuer) or afterwards via an update command: 

az aks update --resource-group <your-resource-group> --name <your-aks-cluster-name> --enable-oidc-issuer 

Next, retrieve your cluster’s unique OIDC issuer URL. You’ll need this in step 3. 

az aks show --resource-group <your-resource-group> --name <your-aks-cluster-name> --query "oidcIssuerProfile.issuerUrl" -o tsv 

2. Create a User-Assigned Managed Identity (Azure) 

Create a User-Assigned Managed Identity (UAMI) in Azure. This can be done in three possible ways: 

  • Via the Azure portal 
  • Via the Azure CLI 
  • Via an Infrastructure as Code (IaC) tool of your choice (e.g. Bicep or Terraform) 

Be sure to also note the Client ID (also called Application ID) and Tenant ID of this new Managed Identity. 

P.S. As we mentioned in the first blog post, you can also opt for App Registration, but we generally recommend using a User Assigned Managed Identity. 

3. Create a Kubernetes Service Account 

Once the federated credential is set up, we need to create a Service Account in our Kubernetes configuration (YAML file). 

Specifically, we need to add the azure.workload.identity/client-id annotation to the metadata, using the Client ID of the User-Assigned Managed Identity created in step 2. This links the Kubernetes Service Account to the Azure identity. 

apiVersion: v1 
kind: ServiceAccount 
metadata: 
  name: <your-service-account-name> # Must match step 3 
  namespace: <your-namespace> # Must match step 3 
  annotations: 
    azure.workload.identity/client-id: "<client-id-of-managed-identity>" 
    # Optional: azure.workload.identity/tenant-id: "<your-tenant-id>" 

4. Configure the Federated Credential (Azure) 

In this step, you’ll establish a trust relationship that makes everything work. Here’s how: 

  1. Open the Azure Portal (or use IaC!) and go to the User-Assigned Managed Identity you just created. 
  2. Navigate to ‘federated credentials’.
  3. Click ‘add credential’ and choose the ‘Kubernetes accessing Azure resources’ scenario. 
  4. Fill in the following details: 
    1. Cluster Issuer URL: The OIDC issuer URL of your AKS cluster (from step 1).
    2. Namespace: The Kubernetes namespace where your Service Account (see step 4) will reside. 
    3. Service Account name: The name you will give to your Kubernetes Service Account. 
    4. Audience: Usually leave this set to the default value: api://AzureADTokenExchange 
    5. Credential name: Give the credential a clear, descriptive name. 
  5. Save the credential. 

5. Configure your pod or deployment 

In the YAML file of your deployment or pod, two more things need to be configured. First, reference the Service Account created in the previous step via spec.serviceAccountName: <your-service-account-name>. 

Second, add the azure.workload.identity/use: “true” label to spec.template.metadata.labels (for a deployment) or metadata.labels (for a pod). This label activates the Workload ID webhook for this pod. 

apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: my-application 
  namespace: <your-namespace> 
spec: 
  # ... replicas, selector ... 
  template: 
    metadata: 
      labels: 
        # ... other labels ... 
        azure.workload.identity/use: "true" # <-- ESSENTIAL LABEL 
    spec: 
      serviceAccountName: <your-service-account-name> # <-- Link to SA 
      containers: 
      # ... container definition ... 

6. Set Azure permissions 

Last but not least, you still need to assign the necessary permissions in Azure. Grant the User-Assigned Managed Identity from step 2 the appropriate Azure RBAC roles on the resources your application needs to access. For example, you might choose ‘Key Vault Secrets User’, ‘Storage Blob Data Reader’, or another role you’ve configured. 

Here’s a best practice to keep in mind: assign these roles to the specific resources your application uses, not just at the subscription level. 

Code & SDKs: what’s left to tweak? 

The good news is that your application code often won’t need any modifications to work with Workload ID. If you’re using recent versions of the Azure Identity SDKs, they’ll automatically detect that they’re running within an AKS pod with a Workload ID configuration. They find the injected token and use it for authentication. 

Just make sure you use at least the following SDK versions: 

Ecosystem  Library  Minimum version 
.NET  Azure.Identity  1.9.0 
C++  azure-identity-cpp  1.6.0 
Go  azidentity  1.3.0 
Java  azure-identity  1.9.0 
Node.js  @azure/identity  3.2.0 
Python  azure-identity  1.13.0 

Source

Pitfalls and best practices 

Workload ID makes authentication much easier than older methods, but (as with any technology) there are a few points to pay extra attention to during implementation. 

Pitfall: Kubernetes configuration

Correctly setting the azure.workload.identity/client-id annotation on the Service Account and the azure.workload.identity/use: “true” label on the Pod template is absolutely crucial. If you forget these or configure them incorrectly, the token exchange simply won’t work. So, always double-check these settings! 

Best practice: don’t forget to restart pods

If you modify the annotations on an existing Service Account (for instance, to link to a different Managed Identity), the pods using that Service Account will need to be restarted. Only then will they pick up the new configuration and be able to obtain the correct Entra ID tokens. 

Best practice: granularity

Always follow the least privilege principle: give a workload only the permissions that are strictly necessary. Ideally, have a separate User-Assigned Managed Identity (with its associated Federated Credential and Service Account) for each application or component that requires unique permissions. This ensures a clear separation and minimises the potential impact if an identity is ever compromised. 

Only bundle workloads under the same Managed Identity (a so-called many-to-one configuration) if they share the exact same set of Azure permissions. For example, consider multiple monitoring components that all need identical access to a Storage Account. 

The limit of a maximum of 20 federated credentials per User-Assigned Managed Identity encourages this granular approach. It almost forces you to consider splitting identities by workload or functional domain, which ultimately improves security. 

Pitfall: regional support

Workload ID is widely available in almost all Azure regions, including West Europe and North Europe. To be certain, check the official Microsoft documentation for the most up-to-date (and very short) list of exceptions, but it’s unlikely you’ll be restricted by this.  

Time to make the switch! 

As you’ve seen, configuring Workload ID requires attention to detail in both Azure and Kubernetes. But once it’s in place, you’ll reap the benefits of a significantly more secure, simpler, and modern way of authenticating. No more secret-related stress, better control, and a setup that fits perfectly into your GitOps workflow. 

So, as far as we’re concerned, Workload ID is the definitive way to set up secure communication between AKS and Azure. That’s why we’ve made it part of our AKS Baseline!

Need some help implementing Workload ID in your AKS environment, or want to learn more about our AKS Baseline? Feel free to get in touch – we’d be happy to help you further on your cloud journey. 

Smokescreen