Installation
The policy-controller is a Kubernetes admission controller that enforces image signing policies at deploy time. Install it on your cluster via a Helm chart.
Prerequisites
- Kubernetes cluster — policy-controller
> 0.10.xsupports Kubernetes 1.27, 1.28, and 1.29; starting with v0.12.0, supported versions are Kubernetes 1.29, 1.30, 1.31, and 1.32. See the policy-controller support matrix. - Helm 3.x
kubectlconfigured to access your cluster
Install with Helm
Add the Sigstore Helm repository and install the chart into the cosign-system namespace:
helm repo add sigstore https://sigstore.github.io/helm-charts
helm repo update
kubectl create namespace cosign-system
helm install policy-controller -n cosign-system sigstore/policy-controller
The chart installs the ClusterImagePolicy and TrustRoot Custom Resource Definitions (CRDs) automatically.
Enable Policy Enforcement for Namespaces
The admission controller validates resources only in namespaces that have opted in. Label the namespaces you want protected:
kubectl label namespace my-namespace policy.sigstore.dev/include=true
See Enable policy-controller Admission Controller for Namespaces.
Configure Image Validation Behavior
Unmatched images
Images that do not match any ClusterImagePolicy are denied by default. Edit the config-policy-controller ConfigMap to change this:
kubectl patch configmap config-policy-controller -n cosign-system \
--type merge \
-p '{"data":{"no-match-policy":"warn"}}'
Valid values: deny (default), warn, allow.
Policy resync period
The controller resyncs ClusterImagePolicy resources every 10 hours by default. Adjust this with --policy-resync-period on the policy-webhook deployment:
helm upgrade policy-controller -n cosign-system sigstore/policy-controller \
--set webhook.extraArgs.policy-resync-period=2h
See time.ParseDuration for valid duration string formats. The TrustRoot resync period defaults to 24 hours and is controlled by --trustroot-resync-period.
Using a Private Sigstore Instance
If you run a private instance of Sigstore components, mount your TUF (The Update Framework) root.json into the webhook container and point to it at startup.
Create a Secret with your root:
kubectl create secret generic tuf-root -n cosign-system \
--from-file=root=./root.json
Mount the Secret into the webhook container via your Helm values file:
webhook:
volumes:
- name: tuf-root
secret:
secretName: tuf-root
volumeMounts:
- name: tuf-root
mountPath: /var/run/tuf
readOnly: true
Then point the webhook at the mounted root:
helm upgrade policy-controller -n cosign-system sigstore/policy-controller \
-f your-values.yaml \
--set webhook.extraArgs.tuf-root=/var/run/tuf/root \
--set webhook.extraArgs.tuf-mirror=https://tuf.example.com
To disable TUF entirely (for air-gapped environments or when using only sigstoreKeys-based TrustRoot resources):
helm upgrade policy-controller -n cosign-system sigstore/policy-controller \
--set webhook.extraArgs.disable-tuf=true
Test a Policy Without a Cluster
The policy-tester tool validates a ClusterImagePolicy against an image locally without a running cluster. Clone the repository and build it:
git clone https://github.com/sigstore/policy-controller
cd policy-controller
make policy-tester
./policy-tester --policy=my-policy.yaml --image=ghcr.io/example/app:v1.0.0