Hedronite · Cert-Prep Lesson · CNCF / CKS · Track K8s Day 16 · Fri 2026-08-07 · Trio #82

CKS — Supply Chain Security the domain the graders like

Four scored bullets, four tools, and one admission plugin that fails open if you get the default wrong.

Lesson Class: Cert-Prep (CKS — Certified Kubernetes Security Specialist)
Domain: Supply Chain Security — 20%, the largest untouched CKS domain on this arc
Track / Day: K8s — round-robin day 16; k8s_day_counter 5, odd, CKS-emphasis
Word Count: ~2,400
Grounding: Rice, Container Security — ch. 6 (pp. 91-98) & ch. 7 (pp. 105-113) · Poulton, The Kubernetes Book — ch. 16 CI/CD (pp. 226-227) · Burns et al., K8s: Up & Running 3rd ed — ch. 15 (pp. 262-267), ch. 1 Optimizing Image Sizes (p. 35) · Sovereign-Bootcamp CKS-PREP-2025 q06, q11, q18, q21, q35, q44
Knowledge Gap: Keyless signing and admission-time signature verification (cosign / Notation / Ratify) — zero hits on both corpora
Paired Ops: Kubernetes Supply Chain Security on AKS
Paired Dev: Python and the Image Admission Gate
CKS Domain: Supply Chain Security 20% trivy · kubesec · bom · ImagePolicyWebhook Performance-based · 2 hrs CKA-before-CKS sit order

Every task in this domain produces a file or an object the grader can check. That is why it is worth the drill.

§IFrame

Two CKS domains are closed on this arc. Minimize Microservice Vulnerabilities came in on 07-26 with Pod Security Standards and the securityContext. Cluster Setup came in on 08-01 with kube-bench, ingress TLS, and metadata protection. Supply Chain Security is the biggest one left, and it is the one the exam graders like, because every task in it produces a file or an object they can check without ambiguity.

The blueprint names four things: minimize base image footprint, secure the supply chain by whitelisting allowed registries and signing images, use static analysis on user workloads, and scan images for known vulnerabilities.

Today's Ops lesson carried the concepts at depth. This one drills the terminal. Rice's chapter on images is the reading behind it, and the chapter on vulnerabilities supplies the caution the exam rewards you for already knowing.

§IIMinimize base image footprint

The scored move is arithmetic. Fewer packages in the image means fewer CVEs in the scan report, and Rice's Installed Packages section is blunt about the cause: most of what a scanner reports came from the base image, not from your code.

Four techniques, in the order they cut the most.

Pick a smaller base. alpine over ubuntu. distroless over alpine where the language runtime allows it. scratch for a static Go binary, which Burns and co-authors flag in the image-size section as the case where the container carries almost nothing to attack.

Multi-stage build. The compiler, the package manager cache, and the build dependencies live in the first stage and never reach the second. This is the single largest cut on most images.

FROM golang:1.23 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /out/gateway ./cmd/gateway

FROM gcr.io/distroless/static-debian12
COPY --from=build /out/gateway /gateway
USER 65532:65532
ENTRYPOINT ["/gateway"]

Run as a named non-root user. USER 65532:65532 in the Dockerfile, and a matching runAsNonRoot: true in the Pod spec. The exam's Dockerfile-fix questions score this and the base-image pin together.

Pin the base image, never latest. Rice's best-practices section lists this beside the secrets rule. A FROM ubuntu:latest is a build that produces a different artifact every week.

Two traps the graders reuse A RUN apt-get install followed by a later RUN rm does not shrink the image; the layer keeps the file even when the final filesystem does not show it. And a secret passed with ARG is visible in docker history forever.

§IIIScan images for known vulnerabilities

trivy is the tool the exam expects. The Bootcamp's q18 gives the shape exactly: scan a list of images for HIGH and CRITICAL, write every result to one file.

for img in ubuntu:18.04 registry.k8s.io/kube-apiserver:v1.24.0 postgres:12; do
  trivy image --severity HIGH,CRITICAL "$img" >> /opt/trivy-vulnerable.txt
done

Three flags carry the domain. --severity HIGH,CRITICAL filters. --exit-code 1 turns the report into a gate, which is what a pipeline task is really asking for. --quiet keeps progress noise out of the file when a task says store the output, and graders do parse those files.

The other common task shape: scan the images running in a namespace and delete the workloads whose images fail. Get the image list from the Pods, then scan each.

kubectl get pods -n production \
  -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort -u

Rice's cautions are the exam's discriminators between a pass and a strong pass. A scan is a comparison against a database with a date on it. Some findings are marked won't fix by the distribution maintainer and will never clear, so a policy of zero findings fails to ship anything. And zero-days exist before the database knows them, which is why Regular Scanning argues for re-scanning what is deployed rather than trusting the build-time report.

kubesec covers the other half of static analysis, and it scans manifests rather than images.

kubesec scan pod.yaml

It scores a Pod spec on securityContext fields: runAsNonRoot, readOnlyRootFilesystem, dropped capabilities, privileged, hostNetwork. That is the 07-26 restricted-profile checklist read back by a tool. When a task says analyze the workload rather than scan the image, reach for kubesec.

§IVSBOM generation

The Bootcamp's q44 is the clearest statement of what the exam wants here. Two tools, two formats, one scan-of-an-SBOM.

bom generate -o /opt/candidate/13/sbom1.json --format json \
  --image registry.k8s.io/kube-apiserver:v1.32.0

trivy image --format cyclonedx -o /opt/candidate/13/sbom2.json \
  registry.k8s.io/kube-controller-manager:v1.32.0

trivy sbom /opt/candidate/13/sbom_check.json -o /opt/candidate/13/sbom_result.json

Hold the pairing. bom is the Kubernetes SIG tool and produces SPDX. trivy --format cyclonedx produces CycloneDX. Task text names the format, and picking the wrong tool for the named format is the whole failure mode.

The third command is the one candidates skip. trivy sbom takes an existing SBOM as input and scans it, which is faster than re-pulling the image and is how a fleet answers which of our four hundred images contain this package when a CVE lands. Rice's argument for regular scanning is what an SBOM makes cheap.

Verify by looking. An SPDX file carries spdxVersion and SPDXID fields; a CycloneDX file carries bomFormat and specVersion. One head -5 tells you which you produced.

§VWhitelisting registries: the ImagePolicyWebhook

The blueprint bullet says secure your supply chain: whitelist allowed image registries. Two mechanisms answer it, and the exam prefers the built-in one.

ImagePolicyWebhook is an API-server admission plugin. Three files, and every one of them is a scored step.

First, enable the plugin and point it at a config file:

- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
- --admission-control-config-file=/etc/kubernetes/confcontrol/admission_config.yaml

Second, the admission configuration naming the plugin's own config:

apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
  - name: ImagePolicyWebhook
    configuration:
      imagePolicy:
        kubeConfigFile: /etc/kubernetes/confcontrol/kubeconf
        allowTTL: 50
        denyTTL: 50
        retryBackoff: 500
        defaultAllow: false

Third, the kubeconfig giving the API server the webhook's URL and CA.

defaultAllow: false is the whole question. The task says deny all non-compliant images, and the default is true, which means an unreachable backend admits everything. Flip it to false and an unreachable backend blocks everything. That is the implicit deny the grader checks, and it is the same fail-closed choice the day's Dev lesson makes with failurePolicy: Fail.

Two operational notes worth carrying The three files must be mounted into the kube-apiserver static Pod under volumeMounts, or the API server starts and cannot read its own config. And editing /etc/kubernetes/manifests/kube-apiserver.yaml restarts the API server, so kubectl goes away for thirty to sixty seconds. Wait. Do not edit again in a panic; a second edit while the first restart is in flight is how candidates lose a cluster mid-exam.

Gatekeeper or Kyverno is the other mechanism. Burns and co-authors walk the Gatekeeper install and the admission flow in the policy chapter, and the K8sAllowedRepos constraint template is the registry-prefix answer. The exam is likelier to hand you a broken ImagePolicyWebhook than to have you install Gatekeeper under time pressure. Know both; expect the plugin.

Signing sits in this bullet too. Rice's Signing Images section gives the concept: a signature binds a digest to a builder identity. The current tooling is cosign for signing and a policy controller for admission-time verification. This is the one corner where the shelf and the Bootcamp set both come up empty, so treat it as concept-level for the exam and read the tool docs before sitting.

§VIExam drill

Q1 · Format pairing
A task requires an SPDX-JSON SBOM for registry.k8s.io/kube-apiserver:v1.32.0. Which tool, and which flag?
Resolution
bom generate -o <path> --format json --image <image>. bom is the SPDX tool. Reaching for trivy --format spdx-json also produces SPDX, and the task text usually names bom explicitly; read the tool the task names.
Q2 · The silent default
You configure ImagePolicyWebhook, the backend is unreachable, and Pods with :latest tags are admitted anyway. Name the bug.
Resolution
defaultAllow is true, either explicitly or by omission. Set defaultAllow: false in the imagePolicy block of the admission configuration.
Q3 · Layer persistence
A Dockerfile does RUN wget https://internal/creds.txt then RUN rm creds.txt. Is the credential in the image?
Resolution
Yes. The file persists in the layer created by the first RUN. Anyone who pulls the image can extract it. Multi-stage build, or mount the secret at build time; deletion in a later layer removes nothing.
Q4 · Scan-then-delete
Scan every image running in namespace production and delete workloads with CRITICAL findings. What is the first command?
Resolution
Extract the image list. kubectl get pods -n production -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort -u. Then trivy image --severity CRITICAL --exit-code 1 each one and delete the owning Deployment, not the Pod, or the ReplicaSet recreates it.
Q5 · Wrong tool
A task says perform static analysis on the workload definition. Trivy or kubesec?
Resolution
kubesec. Trivy scans images for package CVEs. Kubesec scores a manifest's securityContext posture. The word definition is the tell.
Q6 · Restart discipline
You edited kube-apiserver.yaml to add the admission plugin and kubectl get nodes now returns a connection refused error. What do you do?
Resolution
Wait sixty seconds. The kubelet is restarting the static Pod. If it is still down after that, read /var/log/pods/ or crictl ps -a for the container's exit reason, and check that the config files are mounted via volumeMounts and volumes with hostPath.

§VIIThe Trio Interlock

Ops carried the four attach points and the AKS worked example, which is where the registry boundary gets drawn in a real cloud. Dev built the resolver and the webhook that turns a tag into a digest and hands the author the string to paste. This lesson is the same ground at exam pace, by hand, against a clock.

Coverage note for the next CKS day: Cluster Hardening (15%), System Hardening (15%), and Monitoring, Logging and Runtime Security (20%) are the three CKS domains still untouched by this arc. The Bootcamp set carries falco, seccomp, AppArmor, and audit-logging questions against all three.

Set a twelve-minute timer. Do the three SBOM commands in §IV from memory, then the ImagePolicyWebhook three-file setup in §V without scrolling back. The step you forget is almost certainly defaultAllow.

🫡 ⚖️ 📜
Leo.Syri — Praetor Consulate, Imperium Luminaura
Filed 2026-08-07 · Fajr anchor · sprint track K8s day 16 · k8s_day_counter 5 CKS-emphasis · trio #82
Paired Ops: Kubernetes Supply Chain Security on AKS · Paired Dev: Python and the Image Admission Gate
Prior arc: CKS — Cluster Setup (2026-08-01)