OPA Image Security Templates¶
Image security policies control which container images can run in your cluster. These templates enforce registry allowlists, require immutable digests, and validate cryptographic signatures.
Image Tags Are Mutable
Tags like latest or v1.2.3 can be overwritten by attackers who compromise registries. Use digest-based references (sha256:...) for immutable deployments.
Why Image Security Matters¶
Container images are the primary attack vector for supply chain compromises:
- Registry Poisoning - Attackers push malicious images to public registries
- Tag Mutation -
latesttags updated with backdoored code - Typosquatting - Misspelled image names redirect to attacker-controlled registries
- Unsigned Images - No cryptographic proof of provenance
Available Templates¶
Registry Allowlist¶
Restrict container images to approved registries:
- Block public registries (Docker Hub, Quay, GCR)
- Allow only corporate registry domains
- Enforce namespace-specific registry restrictions
- Prevent deployment of untrusted images
Apply a policy:
Digest Enforcement¶
Require immutable digest references instead of mutable tags:
- Block tag-based image references (
nginx:latest) - Mandate digest-based references (
nginx@sha256:...) - Validate digest format and checksum integrity
- Prevent image tag mutation attacks
Apply a policy:
Image Scanning Requirements¶
Enforce vulnerability scanning and security assessments:
- Require scan annotations on all images
- Block images with high/critical CVEs
- Validate scan freshness (no stale scans)
- Enforce minimum scan score thresholds
Apply a policy:
Signature Verification¶
Validate cryptographic signatures using Cosign or Notary:
- Require valid signatures from trusted keys
- Block unsigned or invalidly signed images
- Enforce signature transparency logs (Rekor)
- Validate attestations for build provenance
Apply a policy:
Image Security Defense Layers¶
Implement multiple controls for defense in depth:
- Registry Allowlist - Only approved registries (base.yaml)
- Digest Enforcement - Immutable image references (digest.yaml)
- Vulnerability Scanning - No high/critical CVEs (security.yaml)
- Signature Verification - Cryptographic provenance (verification.yaml)
Each layer addresses different attack vectors. Use all four for production environments.
Common Enforcement Scenarios¶
Scenario 1: Block Public Registries¶
Prevent deployment of images from untrusted sources:
# Enforced by: base.yaml
# Result: Only images from registry.company.com allowed
# Impact: Eliminates supply chain attacks via public registries
Scenario 2: Prevent Tag Mutation¶
Require digest-based image references:
# Enforced by: digest.yaml
# Result: Image references must use @sha256:... format
# Impact: Guarantees deployed image matches approved version
Scenario 3: Block Vulnerable Images¶
Reject images with known CVEs:
# Enforced by: security.yaml
# Result: Images must have scan results with no high/critical vulnerabilities
# Impact: Prevents deployment of exploitable container images
Scenario 4: Verify Build Provenance¶
Validate cryptographic signatures on all images:
# Enforced by: verification.yaml
# Result: Images must be signed by trusted key in KMS
# Impact: Ensures images originated from approved CI/CD pipelines
Testing Image Security Policies¶
Validate enforcement without blocking legitimate workloads:
# Test registry allowlist (should fail for Docker Hub)
kubectl run docker-hub-test --image=nginx:latest
# Expected: Blocked by registry allowlist policy
# Test digest requirement (should fail for tag-based reference)
kubectl run tag-test --image=registry.company.com/nginx:v1.21
# Expected: Blocked by digest enforcement policy
# Test digest-based reference (should succeed if from approved registry)
kubectl run digest-test --image=registry.company.com/nginx@sha256:abcdef123456...
# Expected: Allowed by registry and digest policies
# Test unsigned image (should fail without valid signature)
kubectl run unsigned-test --image=registry.company.com/app@sha256:123456...
# Expected: Blocked by signature verification policy
# Test signed image (should succeed with valid Cosign signature)
# First, sign the image:
# cosign sign --key cosign.key registry.company.com/app@sha256:123456...
kubectl run signed-test --image=registry.company.com/app@sha256:123456...
# Expected: Allowed after signature verification
Signature Verification with Cosign¶
Deploy Cosign-based signature verification:
- Generate signing keys:
- Sign container images in CI/CD:
- Store public key in Kubernetes Secret:
-
Configure OPA policy to verify signatures: Policy references
cosign-pubSecret for signature validation. -
Validate signature verification:
kubectl run test-app --image=registry.company.com/app@sha256:...
# OPA validates signature before admission
Image Scanning Integration¶
Integrate vulnerability scanning into admission control:
Scan in CI/CD¶
Scan images during build and push scan results as annotations:
# Trivy example
trivy image --format json registry.company.com/app:v1.2.3 > scan.json
# Push image with scan annotation
crane mutate registry.company.com/app:v1.2.3 \
--annotation trivy.scan.result="$(cat scan.json)"
Enforce Scan Results¶
OPA policies read scan annotations and block vulnerable images:
# Pseudo-code: Full implementation in security.yaml
deny[msg] {
scan_result := input.metadata.annotations["trivy.scan.result"]
criticals := count(scan_result.Results[_].Vulnerabilities[_] | _.Severity == "CRITICAL")
criticals > 0
msg := sprintf("Image has %d critical vulnerabilities", [criticals])
}
Migrating from Tag-Based to Digest-Based Deployments¶
Transition existing workloads to use digests:
- Audit current image references:
kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{end}' | sort -u
- Convert tags to digests:
# Get digest for tagged image
crane digest registry.company.com/nginx:v1.21
# Output: sha256:abcdef123456...
# Update deployment to use digest
kubectl set image deployment/nginx nginx=registry.company.com/nginx@sha256:abcdef123456...
-
Deploy digest enforcement policy in audit mode: Set
enforcementAction: warnto identify non-compliant workloads. -
Fix violations and enable enforcement: After all workloads use digests, set
enforcementAction: deny.