Skip to content
CAMPUX Cloud Bootcamp Phase Four · Class Twenty-Seven
Phase Four — Operate, Secure & AI
Reading 20 min · Drills 4 · Part E of VII
AKS: Zero to Production
Class Twenty-Seven · Part E

Cluster security

A cluster answers two questions all day — who is allowed to touch me, and what may I touch back — and getting either wrong is how a signed partner contract turns into an incident report, so this part gives you a clean answer to each.

§1

Two doors — who touches the cluster, and what the cluster touches

Every security question about a cluster collapses into one of two doors. The first faces outward at the humans and pipelines that run kubectl against the API server — who they are, and what they are permitted to do once they are in. The second faces inward at the pods, which almost always need to reach back into Azure for a Key Vault secret, a storage account, a database — and the question there is how a pod proves who it is without you burying a password in a manifest. Keep the two doors separate in your head and the rest of this part is bookkeeping.

You have seen both doors before, one class each. Class Eight was role-based access control — the discipline of granting the smallest set of permissions a job needs, no more — and it applies here almost unchanged, only now the resource being guarded is the cluster and the verbs are things like "list pods" and "create deployments." Class Nine was managed identity — an Azure resource proving its identity to another Azure service with no stored secret. This part is those two ideas walked through the cluster's front and back doors, plus the machinery that hardens what runs inside once the doors are shut.

Authentication vs authorization
Authentication asks "who are you?" and is answered by an identity provider. Authorization asks "what may you do?" and is answered by a set of rules checked after identity is proven. The two are separate systems; a valid identity with no granted permissions can do nothing, which is exactly the state a new user should start in.
§2

The front door — Microsoft Entra ID for who, Azure RBAC for what

Split the front door into its two halves. Authentication — proving who is at the keyboard — is handed to Microsoft Entra ID. With Entra integration turned on, nobody authenticates to the cluster with a static certificate or a shared local admin account; they sign in as their Entra identity, which means the same account, the same conditional-access rules, and the same offboarding that governs the rest of your Azure estate also governs the cluster. When someone leaves the company and their Entra account is disabled, their cluster access dies in the same breath — you do not have to remember a second place to revoke it.

The second half — authorization, deciding what that proven identity may do — you can run one of two ways. Azure RBAC for Kubernetes lets you grant Kubernetes permissions using Azure role assignments, so cluster access is managed in the same place, and audited in the same log, as every other Azure permission. The alternative is native Kubernetes RBAC, where Roles and RoleBindings live inside the cluster as objects; you still authenticate with Entra, but you manage the grants in-cluster. Azure RBAC for Kubernetes is the tidier default for an Azure-native shop because it keeps one control plane for permissions; native RBAC wins when you want portable, in-cluster rules that travel with the manifests.

Prove who with Entra. Decide what with RBAC.

Either way, the rule from Class Eight holds without amendment: grant a namespace-scoped role, not cluster-admin, and grant it to a group rather than a person so that access follows the org chart instead of a wiki page nobody updates. A read-only role on one namespace is the correct starting point for almost everyone; the engineer who genuinely needs to deploy gets exactly that verb on exactly that namespace, and the blast radius of a stolen credential is bounded before it is ever stolen.

§3

The back door — Workload ID, a pod with a token and no secret

Now the inward door. A pod needs to read a secret from Key Vault. The lazy answer — the one that fails an audit — is to paste the secret, or a service-principal password, into a Kubernetes Secret and mount it. You saw in §27b that a Kubernetes Secret is only base64, not encrypted at rest by default, so that password is one kubectl get secret -o yaml away from anyone with read access to the namespace. The right answer is to store no credential in the cluster at all.

Microsoft Entra Workload ID is how. The cluster is registered as an OIDC issuer, and a Kubernetes service account is federated to a Microsoft Entra identity. When the pod needs an Azure token, its service-account token — a short-lived, cluster-signed JWT — is exchanged with Microsoft Entra ID for a real Azure access token, because Entra has been told to trust tokens from this specific issuer and subject. The pod ends up holding a normal Azure token it can use against Key Vault or any other service, and at no point did a long-lived secret sit in a manifest. This is the Class Nine managed-identity pattern, now reaching inside the cluster: identity proven by federation, not by a shared password.

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 being retired. Do not build anything new on pod-managed-identity; if you inherit it, the migration target is Workload ID. 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.

Fig. 1 · The token exchange — a pod trades a cluster-signed token for a real Azure token, no stored secret
A pod exchanges its cluster-signed service-account token with Microsoft Entra ID for an Azure token, then reads Key Vault. Pod SA token · signed JWT Microsoft Entra ID trusts issuer + subject Key Vault the secret SA token Azure token read with Azure token no password in the manifest
Read the exchange in order: the pod starts with only a short-lived token the cluster signed, hands it to Microsoft Entra ID, and — because Entra was configured to trust this cluster's issuer and this exact service account — gets back a real Azure token. Only then does it call Key Vault. The long-lived credential lives in Entra's trust configuration, not in anything you shipped in a YAML file.
§4

What runs inside — image scanning and pod hardening

Doors settle who may act; the next question is whether what is already running is trustworthy. Two surfaces matter: the images you pull, and the privileges the pods run with. For images, Microsoft Defender for Containers scans them where they sit in the registry — flagging known vulnerabilities in a base image or a pulled-in library before it ever reaches a node — and adds runtime threat detection that watches for the behaviour of a compromised container, the shell that should not have spawned, the connection that should not have opened. It is the difference between finding a bad image on a Tuesday scan and finding it in an incident post-mortem.

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. The profiles are 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.

Table 1 — The security surfaces of an AKS cluster, and the tool for each
SurfaceQuestion it answersThe tool
Who may run kubectlWho is this, really?Microsoft Entra ID (authentication)
What they may doWhich verbs on which objects?Azure RBAC for Kubernetes (or Kubernetes RBAC)
What a pod may reach in AzureHow does a pod prove itself with no stored secret?Microsoft Entra Workload ID (OIDC federation)
Whether an image is safeKnown vulnerabilities? Bad runtime behaviour?Microsoft Defender for Containers
How much a pod may do to its nodePrivileged? Root? Host access?Pod Security Admission · Azure Policy for AKS
§5

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.

Case File · Campux Retail

Two engineers with kubectl, one gateway pod with no password

the partner cluster, locked to exactly the people and permissions the contract needs

The partner-integration cluster is small and audited, and its access is set to match. Only two engineers can run kubectl against it: both authenticate as their Microsoft Entra identities, and both hold an Azure role scoped to the partner-gw namespace rather than cluster-admin, so a stolen laptop cannot take the whole cluster with it. When the audited network policy the contract demands needs changing, it is one of two named people making the change, in a log the partner's auditor can read.

The gateway pod itself never sees a password. It reads its upstream credential from Key Vault using Workload ID — the Class Nine pattern, now inside the cluster — so the manifest checked into Git holds a service-account name and a Key Vault reference, and nothing that would matter if the repo leaked. The engineer resists the tempting shortcut of a Kubernetes Secret with the credential pasted in, because that credential would then live, base64 and unencrypted, in a namespace the audit will read. Exactly the size of the contract, secured exactly to its terms.

On the job

Removing a leaver's access without hunting for it

You · Cloud Engineer · an engineer just left the team

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.

Class Twenty-Seven · Part E

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.

Drill 01Recall
A pod must read a secret from Key Vault, and the audit forbids any stored credential in the cluster. Which mechanism do you use?
Marked

B. Workload ID federates a cluster-signed service-account token for a real Azure token, so no long-lived credential ever lives in the cluster — exactly what the audit requires. A stores the secret as base64, unencrypted at rest by default, one kubectl get secret -o yaml from exposure. C is the right idea but the wrong tool: pod-managed-identity is deprecated and being retired, and Workload ID is its named replacement, so building on it now is building on something already scheduled for removal. D is worse than A — a ConfigMap is not even pretending to be a secret, and a service-principal password in it is a plaintext credential in a namespace the audit will read.

Drill 02Recall
In an Entra-integrated cluster, which statement correctly splits authentication from authorization?
Marked

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.

Drill 03Select three
Which three statements about AKS security are true?
Marked

The PSP removal, Defender's two jobs, and the Workload ID replacement. The two rejects are exactly the misreadings that cause incidents. A Kubernetes Secret is base64, not encrypted at rest by default — believing otherwise is how a password ends up readable to anyone with namespace access, which is why real secrets belong in Key Vault reached by Workload ID. And Azure RBAC handles authorization, not authentication: you still sign in as your Entra identity, and RBAC only decides what that identity may do once it is proven. Conflating the two is how someone assumes a permission grant also handles login, and leaves the front door unauthenticated in their mental model.

Drill 04Spot the error
A junior drafts this hardening plan for the partner cluster. One line is a security mistake that undoes much of the rest. Which?
# 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.
Marked

Line three. Lines one, two, and four are the plan doing its job — federated sign-in, least-privilege scoped roles, and the hardened Pod Security profile. Then line three drops a plaintext credential into the middle of it. A Kubernetes Secret is only base64-encoded, not encrypted at rest by default, so anyone who can read Secrets in partner-gw — including the auditor the contract invites in — can recover the Key Vault password with a single command. You have carefully narrowed who gets in and what they can run, then left the crown-jewel credential lying in a drawer they are all allowed to open.

The fix is Workload ID: the pod federates a token for Key Vault and holds no stored password at all, which is the whole point of the mechanism and the only line three that survives an audit. The lesson generalises past this plan — a hardening effort is only as strong as its softest secret, and a scoped role means nothing if the thing it protects is sitting unencrypted one namespace over. Narrowing access and then storing a plaintext secret inside that access is a contradiction, not a defence.

Situation 01Write before you reveal
A teammate found an old tutorial and proposes wiring pod-to-Azure access with the pod-managed-identity add-on and, for a quick secret, pasting the value into a Kubernetes Secret "since it's inside the cluster anyway." Talk them out of both — and teach the model behind the objection.
Two problems, one principle. Name the principle before you name the fixes.
Reasoning

Name the principle first: prove identity without storing a secret. Both halves of the proposal violate it, and saying the principle out loud is what turns two separate corrections into one idea they will remember. The goal is never "keep the password somewhere safe inside the cluster" — it is to have no long-lived password in the cluster at all, because a secret that exists is a secret that can leak, and "inside the cluster" is not a vault.

Then take the two mistakes in turn. The pod-managed-identity add-on is deprecated and being retired; its named replacement is Microsoft Entra Workload ID, which federates a cluster-signed token for a real Azure token — simpler, fewer moving parts, and not built on the old metadata-endpoint trick. Building anything new on the deprecated add-on is signing up to migrate it off later. And the pasted Kubernetes Secret is base64, not encrypted at rest by default, so "since it's inside the cluster anyway" is exactly backwards: inside the cluster is where the audit reads, and anyone with namespace read access recovers it in one command.

Close on the low-effort framing. The reason to insist is not purity — it is that the secure path is barely more work and removes an entire class of future incident. One Workload ID federation, done once, means the manifest in Git holds a service-account name and a Key Vault reference and nothing that matters if the repo leaks. Make the safe choice the easy choice and the teammate stops seeing it as extra ceremony.

Situation 02Write before you reveal
A manager, wanting to "move fast," asks you to grant the whole team cluster-admin on the shared cluster because "scoping roles per namespace is slowing people down." Give the answer you would actually give — one that respects the speed concern without conceding the security.
The premise is a false trade. Least privilege and speed are not actually opposed here.
Reasoning

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.

Examination record · first attempt
0/4
Class 27e · Complete
Retain this much

Five things worth carrying out of Part E

  1. 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.
  2. 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.
  3. Back door: Microsoft Entra Workload ID federates a token so a pod proves itself with no stored secret — the Class 9 pattern inside the cluster. It replaces the deprecated pod-managed-identity (aad-pod-identity).
  4. Images and runtime: Microsoft Defender for Containers scans registry images and detects runtime threats. Pod Security Admission hardens pods per namespace (baseline/restricted; enforce/audit/warn); PodSecurityPolicy was removed in 1.25 — do not use it. Azure Policy for AKS applies guardrails centrally.
  5. 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.
Notes
  1. "Encrypted at rest by default" is the phrase to watch. A Kubernetes Secret is base64-encoded, which is encoding, not encryption — anyone can decode it. AKS can encrypt secrets in etcd with a customer-managed key, and the managed etcd is itself encrypted at the platform level, so "readable by anyone" is too strong for the raw disk. The honest claim is narrower and still damning: a Secret is readable in plaintext by anyone with get secret permission in the namespace, which is the exposure that matters here, and the reason real credentials belong in Key Vault reached by Workload ID.
  2. Treat "deprecated" as a direction, not a date. pod-managed-identity is deprecated and Workload ID is the stated replacement — that much is settled and you should build on Workload ID today. The exact retirement timeline for the old add-on has moved before and may move again, so if you inherit a cluster still running it, verify the current end-of-support date against Microsoft Learn rather than trusting a number in any tutorial, including this one. The migration target does not change; only the deadline might.