Trust Boundaries: Authentication and Authorization
A threat model is a map of boundaries, and Kubernetes has four that matter: the human at a terminal, the Pod holding a token, the apiserver deciding twice about every request, and the node underneath. This guide crosses each one from inside a running Pod, using curl rather than kubectl so that nothing is hidden.
Kubernetes Threat Model Guide 26 of 42 Intermediate
- Kubernetesapiserver v1.36.4, kubelet v1.36.3
- Runtimecontainerd 2.2.6
- CNICilium 1.18.1
- Built withkubeadm v1.36.3
- TimeAbout 16 min
Anonymous requests reach the apiserver as system:anonymous on a default kubeadm cluster, which is why the refusal below is a 403 and not a 401. Projected ServiceAccount tokens are the default since 1.24.
- Host kernel7.0.0-29
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| CKA5001 | 192.168.0.41 | Ubuntu 26.04 LTS | Control Plane Node (tainted NoSchedule) | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE01 | 192.168.0.42 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE02 | 192.168.0.43 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE03 | 192.168.0.44 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
This guide includes
Use this when a threat model has to be more than a diagram. This matters because Kubernetes has four boundaries that matter, and every request crosses two separate gates - authentication says who you are, authorization says what you may do, and the two fail quite differently.
- starting from your own credential, which is the boundary you cross most often
- finding the Pod identity that was mounted without anyone asking for it
- decoding the JWT and reading what the token says about itself
- calling the API from inside the Pod and being stopped at the second gate, then sending it with no credential and meeting the first
- finding the boundary that holds with no policy configured, because the kernel provides it
Before you start
-
The human identity, and what it actually is
-
The Pod identity, mounted without being asked for
-
What the token says about itself
-
Crossing into the apiserver, and being stopped at the second gate
-
The same request with no credential at all
-
The boundary that holds with no policy at all