Lesson 0013 · 45 minutes · Supply Chain Security
Enforce immutable container images at admission
A tag can be moved after review; a digest identifies immutable content. This drill combines workload remediation with a native admission control that blocks the next mutable image.
Timed task: 35 minutes
Apply lab/lesson-13-fixture.yaml. Create lab/lesson-13-answer.yaml from scratch. Do not alter the fixture.
Your answer must contain all resources needed to meet these requirements:
- Update Deployment
frontendso its container image is an immutable digest reference from the official Docker Hub library. Preserve its name, namespace, replica count, labels, container name, and command. - Create a native
ValidatingAdmissionPolicyandValidatingAdmissionPolicyBinding. - Within only the
supply-chainnamespace, reject Pod creates and updates unless every regular container image starts withdocker.io/library/and contains an image digest (@sha256:). - The policy must deny invalid workloads with a helpful message. Do not use a webhook, Kyverno, or a cluster-wide binding.
Retrieve the digest from the running fixture Pod rather than guessing it: inspect .status.containerStatuses[0].imageID. The admission expression must validate all containers, not merely the first one.
Verification
kubectl --context kind-cks-lab apply -f .\lab\lesson-13-fixture.yaml
kubectl --context kind-cks-lab -n supply-chain get pod -l app=frontend -o jsonpath='{.items[0].status.containerStatuses[0].imageID}{"\n"}'
kubectl --context kind-cks-lab apply -f .\lab\lesson-13-answer.yaml
kubectl --context kind-cks-lab -n supply-chain rollout status deployment/frontend --timeout=90s
kubectl --context kind-cks-lab -n supply-chain run mutable-test --image=busybox:1.37 --restart=Never
kubectl --context kind-cks-lab -n default run outside-scope --image=busybox:1.37 --restart=NeverExpected: the rollout succeeds; mutable-test is rejected by admission; outside-scope is admitted because the binding is limited to supply-chain. Remove outside-scope after testing.
Retrieval check
Question
Why is busybox:1.37 weaker supply-chain evidence than docker.io/library/busybox@sha256:…?
Documentation target
Use the Kubernetes Validating Admission Policy reference and inspect the schema locally with kubectl explain validatingadmissionpolicy.spec.validations.
What to send me
Paste your policy, binding, and Deployment update, followed by the two admission outcomes. I’ll evaluate the CEL logic, namespace scope, and image-reference enforcement.