CIS Benchmarks & API Hardening (CKS)
Audit an inherited control plane with kube-bench, close what it finds, and check what you run before you run it.
An interactive Kubernetes lesson: 22 steps, about 34 minutes, on a live simulation in your browser.
The shop starts taking card payments next month, and an auditor visits on Thursday. The cluster was set up two years ago by a contractor who has since left. It works: web calls api and every request comes back 200.
Working tells you nothing about safe. A control plane has hundreds of flags, and a handful of them decide whether a stranger can read your Secrets. You cannot review them from memory, and you do not have to.
What you will learn
Audit before you trust
- A cluster you did not build: A benchmark is a numbered checklist of component settings. You do not argue with it from memory; you run it, read the FAIL lines and fix them one by one.
- kube-bench reads the flags for you: kube-bench turns the CIS benchmark into PASS and FAIL lines. Each FAIL names one flag in one file on one node.
Who may use the API
- A stranger asks for the Secrets: Authentication asks who you are. Authorization asks what you may do. A request is only stopped if one of them says no.
- Never AlwaysAllow: AlwaysAllow removes the question 'may you?' for everyone. Node,RBAC is the only authorization mode a kubeadm cluster should run.
- Turn strangers away at the first gate: Forbidden means: we know who you are and the answer is no. Unauthorized means: we do not know who you are. Strangers should get the second.
- What a kubelet may touch: Node authorizer: a kubelet reads only what its own pods need. NodeRestriction: it writes only its own Node and pods.
- Break it: the CI token leaks: cluster-admin is every verb on every resource. Know every subject that holds it, and expect that list to be very short.
Harden the components
- One flag, one restart, one re-check: Hardening a component is a loop: read the FAIL, edit one flag in its manifest, wait for the restart, re-run the check.
- Break it: a fix that stops the API: A static pod sees only what its manifest mounts. Every flag that names a file on the node needs a hostPath volume and a volumeMount.
- The audit log: who did what: An audit policy is first-match-wins: each request gets the level of the first rule it matches. Secrets get Metadata, never their bodies.
- Secrets on etcd's disk: Encryption at rest applies on write. Turn it on, then rewrite every Secret, then check one in etcd.
- Break it: ask the kubelet directly: The kubelet has its own API on 10250. Anonymous off and authorization Webhook put it behind the same identities and RBAC as the API server.
Verify what you run
- Is this the real Kubernetes?: A checksum either matches completely or the file is not the one that was published. Let sha512sum --check do the comparing.
- Check the binary that is running: Verify twice: the download against the published checksum, and the running binary against the verified download.
Upgrade to stay safe
- A fix you do not have yet: The API server is always the newest component. Control plane first, kubelets after, one node at a time.
- Then the nodes, one at a time: Drain, upgrade, uncordon, next node. A routine that is quick and boring is one you will actually run on the day a fix is released.
At exam speed
- What the auditor will ask: Hardening is three questions: who can get in, how is each component configured, and is the software genuine and current.
- Drill: run the benchmark
- Drill: what can a stranger do
- Drill: fingerprint a binary
Recap & playground
- Cheat sheet
- Playground