Stage 5 · Platform
Security, Identity & Admission
Image Policy
Admission webhooks, digest pinning, cosign verification, SBOM checks, and registry allowlists.
Image Security Overview
Image security ensures only trusted, verified images run in your cluster. Layers: registry allowlists (restrict sources), digest pinning (prevent tag mutation), signature verification (prove authorship), and vulnerability scanning (find known issues).
- Registry allowlists — Only pull from approved registries
- Digest pinning — Use sha256 digests instead of tags
- Signature verification — Verify image signatures with cosign
- SBOM verification — Verify software bill of materials
- Vulnerability scanning — Scan for known CVEs
Digest Pinning
Tags are mutable — they can point to different images over time. Digests are immutable — sha256:abc123 always points to the same image. Pin to digests to prevent supply chain attacks where tags are overwritten.
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
spec:
template:
spec:
containers:
- name: app
image: ghcr.io/my-org/my-app@sha256:abc123def456...
imagePullPolicy: IfNotPresent
initContainers:
- name: init
image: ghcr.io/my-org/init@sha256:789xyz012abc...Using @sha256: ensures the exact image is always pulled. A tag can be moved to point to a different image, but a digest is immutable. This prevents attackers from replacing images behind your back.
Cosign Verification
Cosign signs and verifies container images. Sign images in CI/CD, verify at admission time. Kyverno can enforce signature verification — pods using unsigned images are rejected.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
rules:
- name: check-cosign-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/my-org/*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
rekor:
url: https://rekor.sigstore.devverifyImages checks cosign signatures against the public key. rekor provides transparency log verification. Pods using images from ghcr.io/my-org without valid signatures are rejected.
Registry Allowlists
Restrict which registries pods can pull from. This prevents pulling from untrusted sources (Docker Hub public images, malicious registries). Use Kyverno or Gatekeeper to enforce registry policies.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-registries
spec:
validationFailureAction: Enforce
rules:
- name: validate-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Images must come from approved registries"
pattern:
spec:
containers:
- image: "ghcr.io/my-org/* | gcr.io/my-project/* | registry.k8s.io/*"
initContainers:
- image: "ghcr.io/my-org/* | gcr.io/my-project/* | registry.k8s.io/*"This policy only allows images from three approved registries. Any pod using images from other registries is rejected. The | operator means OR — images from any of the registries are allowed.
SBOM Verification
SBOM (Software Bill of Materials) lists all components in an image. Verify SBOMs to ensure you know what's running. Cosign can attest SBOMs alongside signatures.
# Generate SBOM with syft
syft ghcr.io/my-org/my-app:1.0 -o spdx-json > sbom.json
# Attach SBOM to image
cosign attest --predicate sbom.json \
--type spdxjson \
ghcr.io/my-org/my-app:1.0
# Verify SBOM
cosign verify-attestation \
--type spdxjson \
--key cosign.pub \
ghcr.io/my-org/my-app:1.0syft generates SBOMs in SPDX format. cosign attest attaches the SBOM to the image as an attestation. Verification ensures the image has a valid SBOM signed by the trusted key.
Admission Webhook
Custom admission webhooks enforce image policies beyond what Kyverno provides. Check image provenance, scan for vulnerabilities, and verify compliance before allowing images to run.
apiVersion: v1
kind: Config
preferences: {}
clusters:
- name: image-policy-webhook
cluster:
certificate-authority: /etc/kubernetes/pki/image-policy-ca.crt
server: https://image-policy.example.com:8443/policy
users:
- name: kube-apiserver
user:
client-certificate: /etc/kubernetes/pki/apiserver-webhook-client.crt
client-key: /etc/kubernetes/pki/apiserver-webhook-client.key
current-context: image-policy-webhook
contexts:
- context:
cluster: image-policy-webhook
user: kube-apiserver
name: image-policy-webhookThe API server calls the webhook for every image pull. The webhook checks the image against your policy (registry, signature, vulnerability status) and returns allow/deny. This is a powerful but complex mechanism.
Scan images in CI/CD before pushing to the registry. Use Trivy, Grype, or Snyk to check for CVEs. Block deployment of images with critical vulnerabilities. This catches issues before they reach production.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.