AKS Platform: Identity and Access¶
This page describes who and what can access the platform and through which mechanism: human access, Kubernetes and Azure authorisation, workload identity, CI/CD identities, the Key Vault and break-glass access. The principle is no static credentials: everything uses Entra ID, managed identities or federated identities.
Reference design, your deployment may differ
Group and identity names are the patterns of the reference configuration. For the MCP-wide model see Identity and access model and Access, groups and PIM.
Principles¶
- Humans get permissions through Entra ID groups only, never as individual assignments.
- Production and non-production have separate groups. Production developer access is view-only by default.
- Separation of duties: infrastructure deployment, image build and GitOps updates are separate identities.
- Azure resource access is managed with Terraform. In-cluster authorisation is managed as YAML in the GitOps repository and changed by pull request.
- Local Kubernetes accounts are disabled. Sign-in goes through Entra ID with MFA.
Identity types¶
| Identity | Authenticates through | Authorised at | Mechanism |
|---|---|---|---|
| Human users | Entra ID (MFA) | Kubernetes API | Kubernetes RBAC bound to Entra ID groups |
| AKS cluster identity | User-assigned managed identity | Azure Resource Manager | Azure RBAC (Cluster baseline) |
| Workload pods | Service account to federated credential | Azure services | Workload identity and Azure RBAC |
| CI/CD pipelines | GitHub OIDC federated credential | Azure and Kubernetes | Azure RBAC and cluster roles |
| Break-glass | Entra ID with PIM, MFA | Whole cluster | cluster-admin binding |
Groups¶
Group names follow grp-aks-<scope>-<role>[-<team>][-<env>]. The Terraform identity layer creates the groups listed in the
entra_groups map of the configuration, plus the break-glass group.
| Group | Role | Cluster |
|---|---|---|
grp-aks-platform-admins |
Platform administrators, cluster-admin |
Both |
grp-aks-platform-operators |
Manage ingress, monitoring and certificates | Both |
grp-aks-auditors |
Read-only, cluster-wide | Both |
grp-aks-breakglass |
Emergency access | Both |
grp-aks-<team>-leads-<env> |
Team leads | Per environment |
grp-aks-<team>-devs-<env> |
Team developers | Per environment |
The platform admin group and the break-glass group are passed to the cluster as its Entra ID admin groups. The hub-integrated
configuration uses its own group set with an -integrated suffix, so the two clusters do not share groups.
Group membership and PIM activation are not configured in Terraform (limited provider support). The platform team or the customer's identity team manages them.
Kubernetes authorisation¶
Kubernetes RBAC is native (roles and bindings as manifests), deployed by GitOps. Azure RBAC for Kubernetes authorisation is switched on at the cluster, and the pipeline identities use the Azure role Azure Kubernetes Service RBAC Admin.
| Role | Kind | Purpose |
|---|---|---|
cluster-admin |
Built-in | Platform admins and break-glass |
platform-operator |
ClusterRole | Manage platform namespaces: workloads, services, secrets, gateway and certificate resources, monitoring resources, network policies. View nodes and events |
auditor |
ClusterRole | Read-only across the cluster |
namespace-admin |
Role | Full management of a team namespace |
namespace-developer |
Role | Deploy and debug applications, including exec and routes |
namespace-viewer |
Role | Read and pod logs |
Access matrix¶
| Role | dev | test | accp | prod |
|---|---|---|---|---|
| Developer | namespace-developer |
namespace-developer |
namespace-viewer |
namespace-viewer |
| Team lead | namespace-admin |
namespace-admin |
namespace-admin |
namespace-developer |
| Platform operator | View, cluster-wide | View, cluster-wide | View, cluster-wide | View, cluster-wide |
| Auditor | View, cluster-wide | View, cluster-wide | View, cluster-wide | View, cluster-wide |
| Platform admin | cluster-admin |
cluster-admin |
cluster-admin |
cluster-admin |
Namespaces are named <team>-<env> (for example team-a-dev). The networking design document shows <env>-<team>; the RBAC
manifests, the identity configuration and the load test all use <team>-<env>.
Protected platform namespaces¶
kube-system, gateway-system, cert-manager, monitoring, logging, argocd, policy-system and similar platform
namespaces are protected: no role bindings for application teams, platform labels, admission policies that deny bindings by
non-platform subjects, and GitOps-only changes in production. Labels use a configurable domain
(<labelDomain>/type, <labelDomain>/protected, <labelDomain>/team, <labelDomain>/environment), set per customer in the
GitOps repository.
Break-glass access¶
| Aspect | Design |
|---|---|
| Group | grp-aks-breakglass, bound to cluster-admin |
| Members | Two or three senior platform engineers at most |
| Activation | PIM, time-limited, maximum 4 hours, MFA and justification required |
| Monitoring | Alert on PIM activation and on Kubernetes audit activity of the group |
| Review | Quarterly membership review |
Workload identity¶
Each application gets its own user-assigned managed identity per environment, federated to one Kubernetes service account. Identities are not shared between applications, teams or environments.
sequenceDiagram
participant Pod
participant SA as Service account
participant OIDC as AKS OIDC issuer
participant Entra as Entra ID
participant KV as Key Vault
Pod->>SA: Runs as the annotated service account
SA->>OIDC: Projected token
OIDC->>Entra: Token exchange (federated credential)
Entra-->>Pod: Azure token of the managed identity
Pod->>KV: Read secret (Azure RBAC)
What Terraform creates for each entry of the workload_identities map:
| Resource | Name pattern | Notes |
|---|---|---|
| Managed identity | mi-<map key>-<env> |
In rg-<env>-identity |
| Federated credential | fc-<env>-<namespace>-<service account> |
Issuer is the cluster's OIDC issuer, subject is system:serviceaccount:<namespace>:<service account> |
| Role assignments | As listed per entry, for example Key Vault Secrets User on the Key Vault | Least privilege per application |
workload_identities = {
"orders-api-prod" = {
namespace = "team-a-prod"
service_account_name = "orders-api"
roles = [
{
role_definition_name = "Key Vault Secrets User"
scope = "<key-vault-resource-id>"
}
]
}
}
Two steps on a new cluster
The workload identity module only runs when oidc_issuer_url is set, and the issuer URL exists only after the cluster has
been created. On a new environment, deploy the cluster first, copy the issuer URL into the configuration, then apply
again. On Azure Local the bootstrap script prints the URL.
CI/CD identities¶
Each entry in cicd_identities becomes a user-assigned managed identity mi-cicd-<name> with a federated credential
fc-github-<name> for the GitHub OIDC issuer. The subject names a repository and a GitHub Environment, so only runs of that
environment can use the identity. No client secrets exist.
| Identity | Responsibility | Should not |
|---|---|---|
infra-deploy |
Deploy infrastructure | Push images, modify GitOps, deploy apps |
image-build |
Build and push images | Deploy infrastructure, read Key Vault, change the cluster |
gitops-update (design) |
Update GitOps manifests | Deploy infrastructure, push images, access Azure |
Pipeline access to the cluster (for example for the load test) is granted as an Azure role assignment on the cluster
(cicd_aks_role_assignments), kept outside the identity module on purpose. See Deployment.
Azure role assignments for people¶
The design gives the platform admins Azure Kubernetes Service Cluster Admin Role on the cluster, operators and auditors
Cluster User Role, and the auditors Reader. In the code these are supplied through the identity_role_assignments map,
which is empty or commented out in the reference files. Fill it in per environment.
Key Vault¶
| Setting | Value |
|---|---|
| Authorisation | Azure RBAC, no access policies |
| Network | Public network access disabled, default ACL action deny, private endpoint only (Azure variant) |
| Protection | Purge protection on, soft delete 90 days (configurable) |
| SKU | standard (can be premium for HSM-backed keys) |
| Name | Globally unique, kv-<purpose>-<env> pattern, set in the configuration |
| Logging | AuditEvent and policy evaluation logs to Log Analytics when a workspace is set |
Workloads get only Key Vault Secrets User. The design chooses SDK-based access with workload identity over the CSI driver: each application uses its own identity, no secrets are copied into Kubernetes Secret objects, and the application controls caching. The CSI driver add-on is nevertheless switched on in the reference configuration files (see Cluster baseline). Rules for Kubernetes Secrets (no plaintext secrets in Git, prefer Key Vault, ownership labels) are in Security policy.
Audit¶
The design lists events to monitor and send to Log Analytics: Azure role assignment changes, managed identity and federated
credential changes, break-glass activation, cluster-admin binding changes, failed Kubernetes sign-ins and service principal
secret creation. Diagnostic settings are off by default in the reference configuration, so these need a Log Analytics
workspace and the matching switches before go-live.