18 - Supply Chain Security & Admission Control
Why this matters
Hardening the cluster and the pods doesn't help if you're deploying a compromised or vulnerable image in the first place. This is "shift left" security applied to k8s.
Read this first — Definitions & Explanations
Supply chain risk
Attackers target images, dependencies, CI pipelines, and registries — not only running Pods.
Admission control for policy
Validating/mutating webhooks (OPA/Gatekeeper, Kyverno) can block bad images, force labels, deny :latest, require signatures, etc.
Image scanning
Scan for CVEs in CI and continuously in registries. Don’t ship known critical vulns blindly.
Image signing / verification
Ensure images come from trusted builders and weren’t tampered with (Sigstore/cosign-style workflows).
Avoid :latest in production
:latest moves. You lose reproducibility and auditability. Pin digests or immutable tags.
Official docs (read for detail)
- Dynamic Admission Control
- ImagePolicyWebhook
- Kyverno docs
- Signing Container Images (sigstore / cosign overview)
Key Concepts
- Image scanning: Trivy, Grype — CVE scanning of container images
- Image provenance: signing (cosign/Sigstore), verifying signatures before deploy
- Admission controllers as policy enforcement: OPA Gatekeeper vs Kyverno
- Policy-as-code: "no
:latesttags", "only images from our registry", "must have resource limits" - SBOM (Software Bill of Materials) — know what it is and why it's increasingly required
- Private registry auth,
imagePullSecrets
YouTube search terms
- "Trivy container image scanning tutorial"
- "OPA Gatekeeper Kubernetes policy tutorial"
- "Kyverno Kubernetes policy tutorial"
- "cosign image signing Sigstore explained"
Hands-on lab (on prod-sim)
# Scan an image for CVEs with Trivy
brew install trivy # or use the trivy container image
trivy image nginx:1.19 # old version, will show real CVEs
trivy image nginx:latest # compare
# Install Kyverno and write a real policy: block :latest tag cluster-wide
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
cat <<EOF | kubectl apply -f -
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Enforce
rules:
- name: require-image-tag
match:
any:
- resources:
kinds: ["Pod"]
validate:
message: "Using ':latest' tag is not allowed"
pattern:
spec:
containers:
- image: "!*:latest"
EOF
# Prove it blocks a bad deployment
kubectl run bad --image=nginx:latest # should be denied by Kyverno
kubectl run good --image=nginx:1.27 # should succeed
# Add a second policy: require resource limits on every container
cat <<EOF | kubectl apply -f -
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Enforce
rules:
- name: check-resources
match:
any:
- resources:
kinds: ["Pod"]
validate:
message: "CPU and memory limits are required"
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
EOF
kubectl run nolimit --image=nginx:1.27 # should be denied (no limits set)
Notes
(fill in your own words after watching + labbing)