Threat-modeling a cluster
Trace pivots, control each hop, rank by blast radius.
Threat modeling turns the attack surface and ATT&CK vocabulary into a defensible design. The exercise is disciplined: identify what you are protecting, who might attack it, how they would move, and which controls break each path.
Trace the pivots, shrink the radii
For each entry point — an internet-facing app, a CI pipeline that deploys, a developer with kubectl — trace the chain of trust an attacker would follow and ask what stops them at each hop. A compromised app pod: does it have a token, and what can that token do? If it reaches the API, can it read Secrets or create pods? If it reaches the node, what else is co-located? Each answered question is a control to add: automountServiceAccountToken off where unused, least-privilege RBAC, network default-deny, node isolation for sensitive workloads. The goal is that no single compromise cascades into cluster takeover.
# For a compromised frontend pod, walk the chain and pin a control to each hop:## Q: does it mount a token? → automountServiceAccountToken: false# Q: what can that SA do? → least-privilege Role, no secrets/exec/create-pods# Q: can it reach other services? → NetworkPolicy default-deny + explicit allows# Q: can it reach the node/IMDS? → block 169.254.169.254, restrict hostPath/privileged# Q: would we see it? → audit log + runtime rule for exec/secret access## Every "yes it can" without a control is a finding.
Prioritize by blast radius
Not every gap is equal — rank them by blast radius. A path that leads from a public pod to cluster-admin is a fire; a low-privilege token that can only read one ConfigMap is not. Focus first on the escalation primitives (privileged pods, RBAC escalation verbs, secret sprawl, exposed control-plane services) that turn a single foothold into total compromise. Threat modeling is not a one-time document but a lens you apply to every new workload and every RBAC grant, so the cluster’s design stays defensible as it grows.