Stage 5 · Platform
Supply-Chain Security
Image Policy Enforcement
Requiring signed images with Kyverno verifyImages, cosign public keys, and admission controls.
Image Policy Overview
Image policy enforcement ensures that only trusted, signed, and verified container images are deployed to your cluster. Without enforcement, any image from any registry can be deployed — including images with known vulnerabilities or malicious code.
Image policies enforce three requirements: the image must come from an approved registry, the image must be signed by a trusted identity, and the image must not have critical vulnerabilities. These requirements are enforced at admission time — before the image is pulled.
Kyverno Image Verification
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
background: false
rules:
- name: check-image-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestors:
- entries:
- keyless:
issuer: "https://token.actions.githubusercontent.com"
subject: "https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/heads/main"
rekor:
url: https://rekor.sigstore.dev
attestations:
- type: https://slsa.dev/provenance/v0.2
conditions:
- all:
- key: "{{builder.id}}"
operator: Equals
value: "https://github.com/actions/runner"
- type: https://cyclonedx.org/bom
conditions:
- all:
- key: "{{metadata.component.type}}"
operator: Equals
value: "application"This policy requires all images from ghcr.io/myorg/* to be signed by the expected GitHub Actions workflow. It also verifies SLSA provenance and CycloneDX SBOM attestations. Unsigned images are rejected at admission.
Cosign Key-Based Verification
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-cosign-signatures
spec:
validationFailureAction: Enforce
background: false
rules:
- name: verify-cosign
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
roots: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
rekor:
url: https://rekor.sigstore.dev
---
# Store the public key as a Secret
apiVersion: v1
kind: Secret
metadata:
name: cosign-public-key
namespace: kyverno
type: Opaque
stringData:
public-key: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----Key-based verification uses a cosign public key stored as a Kubernetes Secret. Only images signed with the corresponding private key are accepted. The rekor field enables transparency log verification.
Registry Restrictions
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-registries
spec:
validationFailureAction: Enforce
background: true
rules:
- name: allowed-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Images must come from approved registries"
pattern:
spec:
containers:
- image: "ghcr.io/myorg/* | docker.io/library/* | registry.k8s.io/*"
initContainers:
- image: "ghcr.io/myorg/* | docker.io/library/* | registry.k8s.io/*"
- name: block-latest-tag
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Images must not use the 'latest' tag"
pattern:
spec:
containers:
- image: "!*:latest"
initContainers:
- image: "!*:latest"
- name: require-image-digest
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production
validate:
message: "Production images must use digest pinning"
pattern:
spec:
containers:
- image: "*@sha256:*"Registry restrictions limit which image sources are allowed. The latest tag is blocked to ensure reproducible deployments. Production images must use digest pinning for exact version pinning.
Admission Reports
# Check admission reports
kubectl get admissionreports -A
# Get detailed report for a specific resource
kubectl get admissionreport <name> -o yaml
# Check Kyverno policy reports
kubectl get policyreports -A
kubectl get clusterpolicyreports
# View failed policies
kubectl get policyreports -o json | jq -r '.items[] | select(.summary.fail > 0) | .metadata.name'Admission reports show which policies passed and failed for each resource. Policy reports aggregate results across resources. Use these to monitor compliance and identify policy violations.
Enforcement Strategies
- Audit mode first — deploy policies in audit mode to identify violations without blocking.
- Gradual enforcement — enforce policies namespace by namespace, starting with non-critical environments.
- Exception handling — create exceptions for system namespaces and emergency overrides.
- Monitoring — alert on policy violations and track compliance over time.
A misconfigured policy can block all deployments. Test policies in a staging cluster first. Use Kyverno's policy reports to verify the policy works as expected. Have a rollback plan for policy changes.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.