Signed Images & Trusted Registries (CKS)
Only run what you built: allowed registries and signatures verified at admission.
An interactive Kubernetes lesson: 18 steps, about 30 minutes, on a live simulation in your browser.
The shop builds its payments api in CI and pushes it to its own registry, registry.shop.io. Two replicas are serving the frontend.
Then a developer, chasing a bug, pastes a pod manifest from a blog post. Its image is docker.io/freetools/debug:latest. Nobody at the shop built it, scanned it or has ever seen its Dockerfile. The cluster pulls it and runs it next to the payments pods: debug is Running.
What you will learn
Anything runs
- A default cluster runs anything: By default the only test an image must pass is: can the node pull it?
- The same tag, different content: A tag is a pointer that anyone with push rights can move. It names a place in the registry, not a piece of content.
- A digest cannot be moved: A tag says what the image is called. A digest says what the image is.
Permitted registries
- An allow-list of registries: Admission is the one place every pod must pass through. Put the image rule there and it holds for everyone.
- What about the pod already running?: A new admission rule protects the future. Cleaning up what is already running is a separate job, and it is yours.
- Break it: the webhook stops answering: defaultAllow: false fails closed: nothing new starts. true fails open: the check disappears without a sound.
- The same rule without a webhook
Signing what you build
- The right registry is not enough: An allow-list checks where an image came from. A signature checks who made it.
- Sign the image, then verify it: A signature binds a key to a digest. Move the tag and the signature stays behind with the old content.
- Drill: verify a signature
- Signing without a long-lived key: Keyless signing replaces "whoever holds this key" with "this named workflow, as attested by this issuer".
Verifying at admission
- Require a signature at admission: Sign in CI, verify at admission. One without the other is either a lock with no door or a door with no lock.
- Break it: a Deployment with zero pods: A rejected pod gives you an error. A rejected pod from a controller gives you silence and an event on the ReplicaSet.
- Drill: find the refusal
- Sign it, and the pods appear
- Move the tag again: With signatures verified at admission, push access to the registry is no longer enough to run code in the cluster.
Recap & playground
- Cheat sheet
- Playground