Two doors — who touches the cluster, and what the cluster touches
Start with two identity questions. Who may call the cluster's API server through kubectl or a pipeline, and what may they do there? When a pod needs Key Vault or another Azure service, what identity does it use and what is that identity allowed to reach? These are different trust paths. Later you will also examine the image, runtime privileges, network, and application itself.
Class Eight introduced role-based access control: grant only the actions a job needs. Here those actions include listing pods and updating Deployments. Class Nine introduced managed identity for Azure resources. Workload ID extends that idea to a Kubernetes service account through federation. Neither identity path replaces pod hardening or application security; each solves a particular access problem.
The front door — Microsoft Entra ID for who, Azure RBAC for what
Split the front door into its two halves. Authentication proves who is at the keyboard. Microsoft Entra integration lets engineers sign in with their Entra identity so ordinary access follows the organization's account and offboarding controls. But Entra integration alone does not disable AKS local accounts: a cluster-admin credential may remain available unless you explicitly disable local accounts and protect any break-glass path. Check that setting as part of the design rather than assuming every API request uses Entra.
The second half — authorization, deciding what that proven identity may do — has more than one layer. Azure RBAC for Kubernetes can grant Entra users and groups Kubernetes API permissions through Azure role assignments. Native Kubernetes RBAC uses Roles and RoleBindings in the cluster and is also the mechanism the lab below tests for a Kubernetes service account. Choose the model that fits your users and tooling; Azure RBAC integration does not make every in-cluster RoleBinding disappear. In either model, granting a person the Azure role to fetch a kubeconfig is not the same as granting permission to list or change Kubernetes objects.
Prove who with Entra. Decide what with RBAC.
Start with the smallest scope the job needs. Grant engineers access through a maintained group where practical; use namespace-scoped permissions for namespace work, and reserve cluster-wide grants for tasks that actually require them. A developer may need to update Deployments in one namespace without permission to read Secrets or change the cluster's RBAC. Test the real grant with kubectl auth can-i rather than treating a role name as proof.
Ask the cluster what someone can do
Before workload identity or network policy, ask Kubernetes one question about one identity. On a cluster you created you are an administrator, so impersonate someone else:
kubectl auth can-i get pods --as=dev-ada --namespace shop # predict first kubectl auth can-i delete deployments --as=dev-ada --namespace shop
With no Role bound to dev-ada, both answers are no. That is the point: nothing is allowed until something grants it. The least-privilege lab binds a Role and asks again, then over-grants and narrows back. Do that before §3; pod identity to Azure builds on knowing who can do what inside the cluster.
Pod access to Azure — Workload ID without a static password
Now the pod's access to Azure. It needs to read a value from Key Vault. Pasting a long-lived service-principal password or upstream API key into a Kubernetes Secret creates a copy that anyone with permission to read that Secret can recover. Base64 is an encoding used in Secret manifests, not an access control. AKS encrypts managed-disk data at rest by default, and optional KMS encryption adds an application-layer protection for Secrets in etcd; neither prevents an authorized API reader or compromised pod from using the value.1 For Azure authentication, avoid a stored long-lived credential by using Workload ID.
Microsoft Entra Workload ID supplies that path. Enable the cluster's OIDC issuer and Workload ID support, then federate a Kubernetes service account with a Microsoft Entra identity. A projected service-account token is made available to the pod; the workload exchanges it with Entra for a short-lived Azure access token. Grant that identity only the Key Vault access it needs. This removes the static Azure credential from the manifest, but the token is still usable by code running in that pod while valid. A compromised application can act with the identity's permissions, so federation and least privilege must go together.
Say the deprecation plainly, because the old tutorials will mislead you. Workload ID replaces the earlier pod-managed-identity add-on (the aad-pod-identity project), which is deprecated and out of support. Microsoft archived the open-source project in 2023 and patched the AKS add-on only through September 2025. Do not build anything new on pod-managed-identity; if you inherit it, the migration target is Workload ID.2 The federation model is simpler, has fewer moving parts in the cluster, and does not depend on intercepting the node's instance-metadata endpoint the way the old add-on did.
Play it through
Three minutes, two things to do. Remove a long-lived key from a root-running pod, then use a narrowly scoped workload identity and non-root container settings. The final scene asks what an attacker could still do with a compromised application.
You reduced the pod's stored credentials and runtime privileges in the game. Do it for real on Kubernetes API permissions: AKS least privilege. Create a Role and RoleBinding in one namespace, test them with kubectl auth can-i, deliberately widen the grant, then narrow it. This service-account lab tests native Kubernetes RBAC; it does not configure Entra or Azure RBAC.
Go further when you are ready. Zero trust on AKS. A workload with no static secret at all: a Kubernetes service account federated to a managed identity, reading Key Vault just in time, behind a network policy. Longer and costlier than the labs above.
What runs inside — image scanning and pod hardening
Doors settle who may act; the next question is what runs inside. Microsoft Defender for Containers can report known vulnerabilities in images and detect suspicious runtime activity when its relevant plan and components are enabled. A scan finding alone does not block deployment: you need a policy or release gate that acts on it. Findings also do not replace image updates and incident response. For each finding, check the affected image, severity, exposure, and available fix before deciding what to deploy.
For privileges, the current tool is Pod Security Admission — a built-in Kubernetes admission controller you configure per namespace with a label, choosing a profile and a mode. There are three profiles: privileged (no restrictions at all), baseline (block the obviously dangerous — host networking, most privileged containers) and restricted (a hardened, least-privilege posture that also drops root and forbids privilege escalation). The modes are enforce (reject a non-compliant pod), audit (allow it but log the violation), and warn (allow it but warn the user applying it). The usual path is to label a namespace audit and warn at restricted first, read what breaks, then switch to enforce once nothing legitimate trips it.
One correction you must carry, because half the material online predates it: PodSecurityPolicy (PSP) was removed in Kubernetes 1.25. It no longer exists. Do not learn it, do not reach for it, do not copy a manifest that references it — the replacement is Pod Security Admission for the namespace-level baseline, and Azure Policy for AKS when you want those guardrails defined centrally, audited, and applied across every cluster in the subscription from one place rather than remembered namespace by namespace.
| Surface | Question it answers | The tool |
|---|---|---|
| Who may run kubectl | Who is this, really? | Microsoft Entra ID (authentication) |
| What they may do | Which verbs on which objects? | Azure RBAC for Kubernetes (or Kubernetes RBAC) |
| What a pod may reach in Azure | How does a pod prove itself with no stored secret? | Microsoft Entra Workload ID (OIDC federation) |
| Image and runtime findings | Known vulnerabilities? Suspicious behaviour? | Microsoft Defender for Containers, plus a response or release gate |
| How much a pod may do to its node | Privileged? Root? Host access? | Pod Security Admission · Azure Policy for AKS |
Least privilege, all the way down
Notice the single principle threading every row of that table: grant the least a thing needs, and prove identity without shipping a secret. The read-only namespace role, the restricted Pod Security profile, the federated token that replaces a password — each is the same instinct applied at a different layer. Security on a cluster is not one feature you switch on; it is a posture you hold at every door and inside every room, and the reason it reads as a discipline rather than a checklist is that the attacker only needs the one door you left generous.
The engineer's version of this is uncomfortable but worth saying: most breaches are not exotic. They are a cluster-admin credential handed out because narrowing the role was five minutes of work nobody did, or a service-principal password committed to a repo because federation looked like more setup on a Friday. The senior move is to make the secure path the low-effort path — a group with a scoped role, a Workload ID federation done once — so that the lazy choice and the safe choice are the same choice. That is the half of the model no provider will hold for you, and it is precisely the half you are paid to.
Two engineers with kubectl, one gateway pod with no password
The partner-integration cluster is small and audited. Two engineers are granted routine access through Microsoft Entra identities, with Kubernetes API permissions scoped to the partner-gw namespace. The team disables local cluster accounts, reviews break-glass access separately, and tests each engineer's allowed actions. That limits the reach of one stolen account; it does not make a compromised laptop harmless. Changes to the contract's network policy are made through a reviewed change path with an audit trail.
The gateway uses Workload ID to request its upstream credential from Key Vault. Its manifest names the service account and the vault reference rather than embedding a long-lived key. The identity receives permission only for the required secret. The pod still receives a projected token and, once it reads Key Vault, the credential in memory; an application compromise can use both. Keeping the key out of a Kubernetes Secret reduces stored copies, while non-root operation, network controls, monitoring, and a patched application address other parts of the risk.
Removing a leaver's access without hunting for it
Someone with cluster access resigns. Because access was wired to Microsoft Entra and granted through a group, the whole job is removing them from that group — or, if HR disabled their Entra account on their last day, nothing at all, because the account that authenticates is already dead. You do not grep manifests for a certificate, rotate a shared admin password, or hope a wiki listed every place they were added. One identity system, one place to revoke. When your interviewer asks how you handle offboarding on a cluster, that answer — "we never had a second place to revoke, by design" — is the one that lands.
Separate pod identity from network access
Use the fictional evidence below. This is a desk exercise; it does not provision Azure resources or measure a live service.
Pod A: service account shop-reader Federated trust subject: system:serviceaccount:shop:shop-reader Storage role: Blob Data Reader on image account Pod B: different service account
Match namespace and service-account name to the trust.
Predict whether Pod B qualifies for that same trust.
Follow the linked least-privilege lab; test access from the intended pod and a negative case.
Check your reasoning after you finish
Pod A matches the supplied subject. Pod B does not qualify merely because it runs in the same cluster. Workload Identity, Azure data roles and network reachability each require their own check.
Examination
Four drills, then two situations. The situations have no marking scheme — write your answer before you reveal the reasoning, or the exercise is worthless. Nothing is stored.
B. Workload ID lets the pod exchange a projected service-account token for an Azure token, without a stored long-lived Azure credential. A copies a value into a Kubernetes Secret; anyone granted read access to that Secret can decode it through the API, regardless of encryption at rest. C uses the deprecated pod-managed-identity add-on instead of its Workload ID migration path. D puts a password in a ConfigMap, which has no Secret-specific handling at all. Workload ID still gives the pod a usable identity, so limit its Key Vault permissions.
A. Authentication and authorization are separate systems: Entra answers "who are you?" and RBAC answers "what may you do?" B inverts them — RBAC never establishes identity, it only checks permissions against an already-proven one. C is wrong because RBAC absolutely governs in-cluster verbs like listing pods and creating deployments; that is its main job here. D is the dangerous belief this whole design guards against: a proven identity with no granted role can do nothing, and that empty-by-default state is the correct place for a new user to start. Assuming identity implies access is how a valid login becomes an accidental cluster-admin.
The PSP removal, Defender's findings, and the Workload ID migration. Base64 is reversible encoding, so an authorized reader of a Secret can recover its value. That access risk exists even when storage is encrypted at rest. Azure RBAC for Kubernetes authorizes actions after identity is established; it does not replace Entra sign-in. Defender can surface findings when enabled, but acting on them requires policy and response work.
# plan: lock down the partner cluster
1. Turn on Microsoft Entra integration for sign-in.
2. Grant each engineer a role scoped to the partner-gw
namespace, not cluster-admin.
3. Give the gateway pod its Key Vault password by pasting
it into a Kubernetes Secret and mounting it.
4. Label the namespace to enforce the restricted Pod
Security profile.
Line three. The plan copies a long-lived credential into a Kubernetes Secret. Anyone granted get on that Secret can recover the value through the API; base64 encoding is not a defense against that reader. AKS storage encryption protects a different boundary. Namespace-scoped permissions and Pod Security Admission are useful, but neither removes this stored credential.
For Azure access, configure a service account, federation, and a narrowly scoped Workload ID so the pod requests a token without a stored Azure password. If the application must still read an upstream API key, keep it in Key Vault and give the workload identity access only to that key. The app can use the key after retrieval, so patching the application and limiting its permissions remain necessary.
Separate the two risks. The old pod-managed-identity add-on avoids a static Azure password but is deprecated and should be migrated. Pasting an upstream key into a Kubernetes Secret creates a long-lived copy that authorized API readers and code in a mounting pod can use. The common goal is current, least-privilege identity design with as few stored credentials as the workload allows.
Take the two mistakes in turn. The deprecated pod-managed-identity add-on has Workload ID as its migration path. Workload ID exchanges a projected service-account token for an Azure token without a long-lived Azure credential in the pod manifest. A pasted Kubernetes Secret is different: anyone authorized to read that Secret can decode its value. Being "inside the cluster" does not change that. Check who can read Secrets in the namespace, including automated accounts, rather than assuming every namespace user can.
Close with a concrete migration. Configure the cluster OIDC issuer and Workload ID, federate this service account to a dedicated Entra identity, and grant that identity only the Key Vault permission it needs. Keep the upstream key in Key Vault rather than copying it into a manifest. Verify the pod can read the intended value and cannot read another. Then remove the old add-on and stored copy after the new path works.
The trap is the framing of speed against safety. Concede the real goal first — people should not be blocked waiting on access — because a strong answer agrees with the legitimate need before it refuses the proposed fix. Then show the fix is aimed at the wrong target: what slows people down is usually a slow request process, not the existence of scoping, and cluster-admin for everyone solves a paperwork problem by removing a safety rail.
Then price the downside in the manager's own currency. Cluster-admin for the whole team means any single compromised laptop, any one phished credential, is a total cluster compromise — on the audited partner cluster, that is a contract-breaching incident and a conversation with the partner's auditor, not an internal hiccup. The speed saved is minutes on an access request; the exposure bought is the entire blast radius, permanently, for everyone. That is a bad trade even for someone who only cares about velocity.
Close with the third option that gives them both. Wire roles to Entra groups so access follows the org chart and adding a person is one group change, not a ticket queue — fast to grant, scoped by default. Give the common case a ready-made namespace-scoped deploy role so nobody hand-crafts permissions. The honest position is not "security over speed"; it is that a little structure up front buys both, and cluster-admin-for-all buys speed you did not need at a price you cannot afford.
Five things worth carrying out of Part E
- Two doors: who may touch the cluster (front) and what a pod may touch back in Azure (back). Every security question is one or the other.
- Front door: Microsoft Entra ID proves who you are (authentication); Azure RBAC for Kubernetes, or native Kubernetes RBAC, decides what you may do (authorization). Scope roles to a namespace, grant to groups, never default to cluster-admin.
- Pod access to Azure: Workload ID exchanges a projected service-account token for an Azure token without a static Azure password. Scope the identity tightly because compromised pod code can use it.
- Images and runtime: Defender for Containers can report vulnerability and runtime findings when enabled; a policy or release gate must act on them. Pod Security Admission applies namespace profiles and modes; PodSecurityPolicy was removed in 1.25.
- One principle threads all of it: least privilege, and prove identity without shipping a secret. Make the secure path the low-effort path so the lazy choice and the safe choice are the same.
- A Secret's data field is base64-encoded in manifests and API output. AKS encrypts managed-disk data at rest by default; optional KMS encryption can protect Secrets before they are written to etcd. These storage protections do not stop a principal with permission to read a Secret through the API from recovering its value. Check actual RBAC grants, keep long-lived Azure credentials out of the cluster where possible, and scope Workload ID's Azure permissions. ↩
- pod-managed-identity is deprecated and Workload ID is the stated replacement — that much is settled, and you should build on Workload ID today. Microsoft archived the open-source aad-pod-identity project in September 2023 and supported the AKS add-on through September 2025. Dates like that have moved before, so if you inherit a cluster still running it, check the current support position on Microsoft Learn rather than trusting a number in any tutorial, including this one. The migration target does not change; only the deadline might. ↩
Run a cluster with least privilege: workload identity, no secrets in manifests, and a policy on what may run.
Play the lesson above to stamp this class.