This guide demonstrates how to use the Sigstore Policy Controller to verify image signatures before admitting an image into a Kubernetes cluster. In this guide, you will create a ClusterImagePolicy that checks for a keyless Cosign image signature, and then test the admission controller by running a signed nginx image.
To follow along with this guide outside of the terminal that is embedded on this page, you will need the following:
If you are using the terminal that is embedded on this page, then all the prerequsites are installed for you. Note that it make take a minute or two for the Kubernetes cluster to finish provisioning. If you receive any errors while running commands, retry them after waiting a few seconds.
Once you have everything in place you can continue to the first step and confirm that the Policy Controller is working as expected.
Before creating a ClusterImagePolicy, check that the Policy Controller is deployed and that your default namespace is labeled correctly. Run the following to check that the deployment is complete:
kubectl -n cosign-system wait --for=condition=Available deployment/policy-controller-webhook && \
kubectl -n cosign-system wait --for=condition=Available deployment/policy-controller-policy-webhook
When both deployments are finished, verify the default namespace is using the Policy Controller:
kubectl get ns -l policy.sigstore.dev/include=true
You should receive output like the following:
NAME STATUS AGE
default Active 24s
Once you are sure that the Policy Controller is deployed and your default namespace is configured to use it, run a pod to make sure admission requests are handled and denied by default:
kubectl run --image cgr.dev/chainguard/nginx:latest nginx
Since there is no ClusterImagePolicy defined yet, the Policy Controller will deny the admission request with a message like the following:
Error from server (BadRequest): admission webhook "policy.sigstore.dev" denied the request: validation failed: no matching policies: spec.containers.image
In the next step, you will define a policy that verifies Chainguard Images are signed and apply it to your cluster.
Now that you have the Policy Controller running in your cluster, and have the default namespace configured to use it, you can now define a ClusterImagePolicy to admit images.
Open a new file with nano or your preferred editor:
Copy the following policy to the /tmp/cip.yaml file:
catalog.chainguard.dev/title: Chainguard Images
catalog.chainguard.dev/description: Enforce Chainguard images are signed
- glob: cgr.dev/chainguard/**
- issuer: https://token.actions.githubusercontent.com
The glob: cgr.dev/chainguard/** line, working in combination with the authorities section, will allow any image in the cgr.dev/chainguard image registry that has a keyless signature to be admitted into your cluster.
The - keyless options instruct the Policy Controller what to check for when it examines the signature on any image from the cgr.dev/chainguard registry. The specific fields are:
Save the file and then apply the policy:
kubectl apply -f /tmp/cip.yaml
You will receive output showing the policy is created:
Now run the cgr.dev/chainguard/nginx:latest image again:
Since the image matches the policy, you will receive a message that the pod was created successfully:
In the background, the Policy Controller queries the specified ctlog from the policy that you created to find a record in the log that matches the image being requested (cgr.dev/chainguard/nginx:latest). The Policy Controller ensures that the SHA256 hash of the image matches the hash that is recorded in the certificate issued by the OIDC issuer when the image was first signed. Finally, the Policy Controller verifies the issued certificate was signed by the specified Certiciate Authority’s (https://fulcio.sigstore.dev) root signing certificate. Once the Policy Controller verifies the signature of the image’s hash in the transparency log matches the computed hash of the image, and the certificate’s validity based on the CA chain of trust, it will admit the pod into the cluster.
Delete the pod once you’re done experimenting with it:
kubectl delete pod nginx
To learn more about how the Policy Controller uses Cosign to verify and admit images, review the Cosign Sigstore documentation.
While it is useful to use the Policy Controller to manage admission into a cluster, once a workload is running any vulnerability or policy violations that occur after containers are running will not be detected.
Chainguard Enforce is designed to address this issue by continuously verifying whether a container or cluster contains any vulnerabilities or policy violations over time. This includes what packages are deployed, SBOMs (software bills of materials), provenance, signature data, and more.
If you’re interested in learning more about Chainguard Enforce, you can request access to the product by selecting Chainguard Enforce on the inquiry form.