Configure Azure Workload Identity on AKS
This page summarizes the elements to configure so that the Kubernetes via kubeconfig 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 managed identity the Azure Kubernetes Service RBAC Reader role on each AKS cluster to scan. This role allows calls to the Kubernetes API of the cluster, such as listing pods, namespaces and workloads.
The federated identity credential only needs to be configured once, for the cluster hosting Cyberwatch. The other clusters to scan only need this role and must belong to the same Microsoft Entra tenant as the managed identity.
Without this role on the cluster, calls to the Kubernetes API 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 via kubeconfig discovery can then be created from the application by following the Kubernetes via kubeconfig discoveries documentation.