Configure Azure Workload Identity on AKS
This page summarizes the elements to configure so that the Kubernetes discoveries of a Cyberwatch instance deployed on an AKS cluster authenticate to the Kubernetes API of the cluster with Azure Workload Identity.
Azure Workload Identity relies on OIDC federation between the AKS cluster and Microsoft Entra ID. Cyberwatch pods obtain a token without any secret stored in the cluster. A mutating webhook injects the Azure environment variables when the pods are created, and the application then uses them to query the Kubernetes API.
Azure-side configuration
AKS cluster
The cluster must have the following features:
- the OIDC issuer enabled (
oidcIssuerProfile.enabledset totrue) - Workload Identity enabled (
--enable-workload-identityoption when creating or updating the cluster). Theazure-wi-webhookmutating webhook is then present on the cluster - Kubernetes authorization with Azure RBAC enabled (
aadProfile.enableAzureRbacset totrue). Access rights to the Kubernetes API are then managed with Azure role assignments, not withClusterRoleBindingobjects
The OIDC issuer URL of the cluster is required for the next steps:
az aks show --resource-group <resource-group> --name <cluster-name> --query oidcIssuerProfile.issuerUrl
Managed identity
Create a dedicated managed identity, of type user-assigned, that will hold the access rights of the discovery.
Federated identity credential
Create a federated identity credential on the managed identity, with the following parameters:
- issuer: the OIDC issuer URL of the cluster
- subject: the identity of the dedicated service account described below
- audience:
api://AzureADTokenExchange
The subject uses the following format, where <namespace> is the namespace where Cyberwatch is deployed and <service-account> is the name of the ServiceAccount:
system:serviceaccount:<namespace>:<service-account>
Role assignments
Assign the following roles to the managed identity:
- Azure Kubernetes Service RBAC Reader on the AKS cluster scope. This role allows calls to the Kubernetes API of the cluster, such as listing pods, namespaces and workloads
- Reader on the subscription, or on a narrower scope, only if the discovery also enumerates Azure resources
A Reader role on the subscription does not grant access to the Kubernetes API. Without the Azure Kubernetes Service RBAC Reader role on the cluster, calls fail with the User does not have access to the resource in Azure error.
Kubernetes cluster-side configuration
The configuration applies to the namespace where Cyberwatch is deployed, cyberwatch in the examples below.
Dedicated service account
Create a ServiceAccount annotated with the client ID of the managed identity:
apiVersion: v1
kind: ServiceAccount
metadata:
name: workload-identity-sa
namespace: cyberwatch
annotations:
azure.workload.identity/client-id: <client-id>
Cyberwatch deployments
The Cyberwatch Helm chart exposes the two settings required for the deployment: extraLabels applies the label on the pod template and serviceAccountName sets the ServiceAccount of the pod. The ServiceAccount is not created by the chart and must already exist in the namespace.
web:
serviceAccountName: workload-identity-sa
extraLabels:
azure.workload.identity/use: "true"
sidekiq:
serviceAccountName: workload-identity-sa
extraLabels:
azure.workload.identity/use: "true"
sidekiqMaster:
serviceAccountName: workload-identity-sa
extraLabels:
azure.workload.identity/use: "true"
sidekiqNode:
serviceAccountName: workload-identity-sa
extraLabels:
azure.workload.identity/use: "true"
To apply the same ServiceAccount to every component, it can be set once with global.serviceAccountName.
Apply the Helm chart changes with a helm upgrade.
Check the setup
Once the pods are restarted, each affected pod must contain the AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_FEDERATED_TOKEN_FILE and AZURE_AUTHORITY_HOST environment variables, as well as a token projected in /var/run/secrets/azure/tokens/azure-identity-token:
kubectl -n cyberwatch exec deploy/web -- env | grep AZURE_
The Kubernetes discovery can then be created from the application by following the Kubernetes discoveries documentation.