Skip to content

troy-chainguard-dev/cosign-policy-controller

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Verifying Chainguard Image Provenance in Kubernetes

This demo shows how to enforce cryptographic provenance verification for container images in Kubernetes using the Sigstore Policy Controller and Chainguard Images.

What is Provenance?

Provenance is cryptographic proof of where a container image came from and how it was built. Unlike a simple signature that says "this is authentic," provenance tells you:

  • Who built it - The identity of the build system (verified via OIDC)
  • Where it was built - The specific CI/CD pipeline and repository
  • How it was built - Build parameters, dependencies, and toolchain
  • What's inside - Software Bill of Materials (SBOM)

All of this is cryptographically signed and recorded in a tamper-evident transparency log.

Why Provenance Matters

Without provenance, you're trusting that:

  • The image tag hasn't been overwritten with malicious content
  • The image actually came from the claimed source
  • The build process wasn't compromised

With provenance verification, you have cryptographic proof of the entire supply chain.

Chainguard Image Provenance

Every Chainguard image includes:

Attestation Purpose
Signature Proves the image is authentic and unmodified
SLSA Provenance Proves where and how the image was built
SBOM Proves what software packages are inside

All attestations are signed using Sigstore's keyless signing and recorded in the Rekor transparency log.

Prerequisites

  • Kubernetes cluster with admin access
  • kubectl configured to access your cluster
  • helm CLI installed
  • cosign CLI (for manual verification)
  • jq (optional, for readable output)

Part 1: Manual Provenance Verification

Before setting up cluster policies, let's manually verify a Chainguard image's provenance.

View Supply Chain Artifacts

cosign tree cgr.dev/chainguard/nginx:latest

Output shows the image's signatures and attestations:

πŸ“¦ Supply Chain Security Related artifacts for an image: cgr.dev/chainguard/nginx:latest
└── πŸ’Ύ Attestations for an image tag: cgr.dev/chainguard/nginx:sha256-...
   β”œβ”€β”€ πŸ’ sha256:... (SLSA Provenance)
   β”œβ”€β”€ πŸ’ sha256:... (SBOM)
   └── πŸ’ sha256:... (Build Config)
└── πŸ” Signatures for an image tag: cgr.dev/chainguard/nginx:sha256-...
   └── πŸ’ sha256:...

Verify the Signature

cosign verify \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity=https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main \
  cgr.dev/chainguard/nginx:latest

This verifies:

  • The signature is valid
  • The signing certificate was issued by the trusted OIDC provider (GitHub Actions)
  • The signer identity matches Chainguard's release workflow
  • The signature is recorded in the Rekor transparency log

Verify SLSA Provenance

cosign verify-attestation \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity=https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main \
  --type=https://slsa.dev/provenance/v1 \
  cgr.dev/chainguard/nginx:latest

This proves the image has a valid SLSA provenance attestation showing exactly how it was built.

Verify SBOM Attestation

cosign verify-attestation \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity=https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main \
  --type=https://spdx.dev/Document \
  cgr.dev/chainguard/nginx:latest

This proves the image has a verified Software Bill of Materials.

Compare: Upstream Image (No Provenance)

Try the same commands on an upstream Docker Hub image:

cosign tree docker.io/library/nginx:latest

Most upstream images have no signatures or attestations - you're trusting blindly.

Part 2: Enforcing Provenance in Kubernetes

Now let's enforce provenance verification automatically for all pods.

Step 1: Install the Policy Controller

# Create namespace
kubectl create namespace cosign-system

# Add Helm repo
helm repo add sigstore https://sigstore.github.io/helm-charts
helm repo update

# Install
helm install policy-controller -n cosign-system sigstore/policy-controller --devel

# Wait for ready
kubectl -n cosign-system wait --for=condition=Available deployment/policy-controller-webhook --timeout=120s

Step 2: Create a Test Namespace

# Create namespace
kubectl create namespace chainguard-test

# Enable policy enforcement
kubectl label namespace chainguard-test policy.sigstore.dev/include=true

Step 3: Apply the Provenance Policy

kubectl apply -f policies/chainguard-provenance-required.yaml

This policy requires:

  1. Images must match cgr.dev/chainguard/**
  2. Images must have a valid keyless signature
  3. Images must have a verified SLSA provenance attestation

View the policy:

kubectl get clusterimagepolicy chainguard-provenance-required -o yaml

Step 4: Test Provenance Enforcement

Test 1: Chainguard Image with Provenance (ALLOWED)

kubectl run nginx-chainguard --image=cgr.dev/chainguard/nginx:latest -n chainguard-test

Expected: pod/nginx-chainguard created

The pod is admitted because:

  • βœ“ Image matches policy glob cgr.dev/chainguard/**
  • βœ“ Signature verified against Chainguard's OIDC identity
  • βœ“ SLSA provenance attestation verified

Test 2: Upstream Image without Provenance (DENIED)

kubectl run nginx-upstream --image=docker.io/library/nginx:latest -n chainguard-test

Expected:

Error from server (BadRequest): admission webhook "policy.sigstore.dev" denied the request: 
validation failed: no matching policies: spec.containers[0].image
index.docker.io/library/nginx:latest@sha256:...

The pod is denied because it has no matching policy (and no provenance to verify).

Test 3: Other Images without Provenance (DENIED)

kubectl run redis --image=redis:latest -n chainguard-test
kubectl run alpine --image=alpine:latest -n chainguard-test

All denied - only images with verified Chainguard provenance are allowed.

Cleanup

kubectl delete pod nginx-chainguard -n chainguard-test

Policy Files

File Description
policies/chainguard-provenance-required.yaml Requires SLSA provenance - verifies signature AND build provenance
policies/chainguard-signed-images.yaml Signature only - verifies keyless signature (no attestation check)
policies/chainguard-static-allow.yaml Allow only - no verification (not recommended for production)

Understanding the Provenance Policy

spec:
  images:
    - glob: "cgr.dev/chainguard/**"
  authorities:
    - name: chainguard-provenance
      keyless:
        url: https://fulcio.sigstore.dev
        identities:
          - issuer: https://token.actions.githubusercontent.com
            subject: https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main
      ctlog:
        url: https://rekor.sigstore.dev
      attestations:
        - name: must-have-slsa-provenance
          predicateType: https://slsa.dev/provenance/v1    # <-- Requires provenance!

Key components:

  • keyless - Uses Sigstore's keyless signing (no keys to manage)
  • identities - Verifies the signer is Chainguard's GitHub Actions workflow
  • ctlog - Checks the Rekor transparency log
  • attestations - Requires SLSA provenance attestation

Key Takeaways

  1. Provenance β‰  Signature - A signature proves authenticity; provenance proves the entire build chain
  2. Keyless signing - No keys to manage, rotate, or secure
  3. Transparency logs - All signatures are publicly auditable
  4. Policy enforcement - Kubernetes automatically rejects images without valid provenance
  5. Supply chain security - Cryptographic proof from source code to running container

Troubleshooting

Check Policy Controller

kubectl get pods -n cosign-system
kubectl logs -n cosign-system -l app.kubernetes.io/name=policy-controller

Verify Namespace Label

kubectl get ns -l policy.sigstore.dev/include=true

View Policies

kubectl get clusterimagepolicy
kubectl describe clusterimagepolicy chainguard-provenance-required

References

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published