Configure Image Provenance ImagePolicyWebhook Admission
More Info:
Configure Image Provenance for your deployment.
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Review current admission controller configuration (managed control plane: use cloud console/CLI; self-managed: control plane node)
- Self-managed:
# On each control plane nodegrep -E -- '--admission-control|--enable-admission-plugins' /etc/kubernetes/manifests/kube-apiserver.yaml
- Managed (EKS/AKS/GKE/OKE):
- Open the cluster configuration in the provider console or CLI and locate the API server admission plugins section.
- Decision: If
ImagePolicyWebhook(or an equivalent image provenance admission plugin for your platform) is not enabled, image provenance via ImagePolicyWebhook is not configured.
- Self-managed:
-
Identify any existing image policy webhook configuration (any machine with kubectl access)
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations -A \-o wide | grep -i image || truekubectl get clusterrole,clusterrolebinding -A | grep -i image || true- Decision: If you see webhook configurations, ClusterRoles, or bindings clearly tied to image policy/provenance, note their names for detailed inspection.
-
Inspect image policy webhook behavior (any machine with kubectl access)
# Replace with actual names found in step 2, if anykubectl get validatingwebhookconfigurations <name> -o yamlkubectl get mutatingwebhookconfigurations <name> -o yaml- Verify:
- Scope: rules include
pods(and optionallydeployments,replicasets, etc.). - Failure policy: typically
Failto enforce provenance (not just audit). - Service/URL: points to a reachable webhook that validates image signatures/provenance.
- Scope: rules include
- Decision: If these conditions are not met, image provenance is not effectively enforced.
- Verify:
-
Assess current workload image provenance (any machine with kubectl access)
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}' \| sort | uniq- Manually review a sample of images:
- Determine whether they come from a trusted registry that supports signing/attestation.
- Confirm that your intended image-signing or attestation tools (e.g., cosign, Notary, in-toto) are actually being used for these images.
- Decision: If unsigned/unanalyzed images are allowed without webhook enforcement, provenance is not assured.
- Manually review a sample of images:
-
Design or refine the image policy and webhook (any machine with kubectl access)
- Based on your chosen provenance mechanism (e.g., cosign + policy engine):
- Draft or update the webhook’s policy to:
- Require images from specific registries or repositories.
- Require valid signatures/attestations for allowed images.
- Optionally block
:latestor untagged images.
- Draft or update the webhook’s policy to:
- Implement by applying or updating manifests:
# Example placeholder; replace with your actual manifestskubectl apply -f image-policy-webhook-deployment.yamlkubectl apply -f image-policy-webhook-service.yamlkubectl apply -f image-policy-validatingwebhookconfiguration.yaml
- Note: You must obtain or write these manifests according to the image provenance solution you adopt and the Kubernetes documentation; they are not auto-generated.
- Based on your chosen provenance mechanism (e.g., cosign + policy engine):
-
Verify enforcement of image provenance (any machine with kubectl access)
- Test pod creation with:
# Known non-compliant image (e.g., unsigned or from disallowed registry)kubectl run test-bad-image --image=registry.example.com/unsigned:test || true# Known compliant image (properly signed/attested)kubectl run test-good-image --image=registry.example.com/signed:test
- Confirm results:
- Non-compliant pod is rejected with an error message from the image policy webhook.
- Compliant pod is admitted and runs.
- If both are admitted or both are denied without reference to image policy, revisit steps 2–5 and adjust configuration and policy until the observed behavior matches your intended image provenance requirements.
- Test pod creation with:
Using kubectl
# 1) Check if any ImagePolicyWebhook configuration exists in the cluster
# Run on: any machine with kubectl access
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations \
-o wide
- Potential problem indication:
- No webhook configuration objects related to image policy or provenance (names typically contain
imagepolicy,image-provenance,image-signature, etc.). - Or only generic webhooks that clearly do not enforce image provenance.
- No webhook configuration objects related to image policy or provenance (names typically contain
# 2) Inspect details of any candidate webhook that might enforce image provenance
# Replace the name with any likely candidate from the previous output
kubectl get validatingwebhookconfigurations <WEBHOOK_NAME> -o yaml
kubectl get mutatingwebhookconfigurations <WEBHOOK_NAME> -o yaml
Review in the YAML:
rules:- Problem indication: rules do not target
apiGroups: [""],apiVersions: ["v1"],resources: ["pods"](or other workload types where images are used), or only apply to irrelevant resources.
- Problem indication: rules do not target
clientConfig:(URL/service):- Problem indication: points to a non-existent service, an HTTP (not HTTPS) endpoint, or uses invalid CA bundle, causing the webhook to be effectively bypassed.
failurePolicy:- Problem indication: set to
Ignoreso that if the image policy service fails, pod creation continues without image provenance checks.
- Problem indication: set to
namespaceSelector/objectSelector:- Problem indication: selectors exclude all or most namespaces/workloads where image provenance should be enforced (e.g., only selected namespaces, leaving production unprotected).
matchPolicy/sideEffects/admissionReviewVersions:- Problem indication: misconfiguration that would prevent the webhook from reliably receiving pod admission requests.
# 3) See what images are currently in use across the cluster
# Run on: any machine with kubectl access
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}' | sort
- Problem indication:
- Widespread use of untrusted or unverifiable image registries (e.g., random public registries) without any corresponding image policy webhook that validates signatures or provenance.
- Inconsistent image sources that suggest lack of a controlled provenance strategy (e.g., mix of arbitrary Docker Hub images with no signed/private alternatives).
# 4) Check if any admission configuration references an ImagePolicyWebhook configuration (self-managed clusters)
# NOTE: This only works if the apiserver manifest is accessible via a DaemonSet or hostPath pod.
# Run on: a pod/container that can read /etc/kubernetes/manifests on control-plane nodes
kubectl -n kube-system get pods -o wide
# (Identify any pod that mounts /etc/kubernetes/manifests and exec into it, then:)
kubectl -n kube-system exec -it <POD_NAME> -- \
grep -R "admission-control-config-file" -n /etc/kubernetes/manifests
- Problem indication:
- No
--admission-control-config-file(or equivalent) flag present pointing to a configuration that includesimagePolicy/imagePolicyWebhooksettings. - Or a referenced admission config file exists but does not define any
imagePolicystanza.
- No
(If you cannot access the API server manifest or flags from within the cluster, this part of the review must be done on the control-plane nodes directly and is outside the scope of kubectl.)
# 5) For managed Kubernetes (EKS/AKS/GKE/OKE), inspect for known image or admission integrations
# Run on: any machine with kubectl access
kubectl get ns
kubectl get pods -A
kubectl get crd
- Problem indication:
- No vendor- or add-on–specific components that typically implement image provenance or admission enforcement (e.g., no image policy controllers, no Sigstore/Notary/Gatekeeper-style integrations), combined with the lack of webhooks found earlier.
Use the results above to decide:
- Whether an ImagePolicyWebhook (or equivalent admission mechanism) exists and is correctly wired to enforce image provenance on pod creation.
- Whether the scope (namespaces/resources), failure behavior, and connectivity would realistically prevent unsigned/untrusted images from being admitted.
Any absence or ineffective configuration indicates the cluster is not enforcing image provenance and requires a design and implementation decision rather than an automatic fix.
Automation
#!/usr/bin/env bash
#
# Audit script for CIS Kubernetes 5.5.1:
# "Configure Image Provenance using ImagePolicyWebhook admission controller"
#
# Run on: any machine with kubectl access and cluster-admin privileges.
set -euo pipefail
echo "==[ 1. Check for ImagePolicyWebhook admission plugin on API servers ]=="
# Try common API server discovery methods
echo "[*] Discovering kube-apiserver endpoints..."
APISERVER_ENDPOINTS=$(kubectl get pods -A -l component=kube-apiserver -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' 2>/dev/null || true)
if [[ -n "${APISERVER_ENDPOINTS}" ]]; then
echo "[*] Found kube-apiserver pods:"
echo "${APISERVER_ENDPOINTS}"
echo
# Inspect pod specs for admission plugins / ImagePolicyWebhook mentions
echo "[*] Searching kube-apiserver pod specs for ImagePolicyWebhook configuration..."
kubectl get pods -A -l component=kube-apiserver -o yaml | \
awk '
BEGIN{found=0}
/kube-apiserver/ {pod=$0}
/--enable-admission-plugins/ || /--admission-control=/ || /ImagePolicyWebhook/ {
print "----"; print "POD CONTEXT: " pod; print $0; found=1
}
END{ if(found==0) print "NO ImagePolicyWebhook references found in kube-apiserver pod specs." }
'
else
echo "[!] No kube-apiserver pods discovered via label component=kube-apiserver."
echo " If this is a managed control plane (EKS/AKS/GKE/OKE), ImagePolicyWebhook"
echo " enablement must be checked in the provider's control-plane configuration."
fi
echo
echo "==[ 2. Check for Mutating/ValidatingWebhookConfiguration objects ]=="
echo "[*] Listing admission webhooks that might enforce image provenance..."
kubectl get mutatingwebhookconfigurations,validatingwebhookconfigurations -o name || true
echo
echo "[*] Detailed search for webhooks referencing images, signatures, or policy engines..."
kubectl get mutatingwebhookconfigurations,validatingwebhookconfigurations -o yaml 2>/dev/null | \
awk '
/kind: (MutatingWebhookConfiguration|ValidatingWebhookConfiguration)/{cfg=$0}
/name: /{name=$0}
/image/ || /provenance/ || /cosign/ || /notary/ || /connaisseur/ || /kyverno/ || /gatekeeper/ {
print "----"; print cfg; print name; print $0;
}
' || true
echo
echo "==[ 3. Check for ImagePolicyWebhook Configuration objects ]=="
echo "[*] Searching for ImagePolicyWebhook configuration resources (if any CRD is in use)..."
kubectl get crds 2>/dev/null | grep -i imagepolicy || echo "[*] No obvious image policy CRD names found."
echo
echo "==[ 4. Summary interpretation guidance ]=="
cat <<'EOF'
What output indicates a potential problem (non-compliance with CIS 5.5.1):
1. API server flags:
- If no kube-apiserver pod specs show:
--enable-admission-plugins=...ImagePolicyWebhook...
or equivalent admission configuration referencing ImagePolicyWebhook,
then ImagePolicyWebhook is likely NOT enabled on this cluster.
2. Webhook configurations:
- If 'kubectl get mutatingwebhookconfigurations,validatingwebhookconfigurations'
returns either nothing, or only webhooks unrelated to image verification
(e.g., no refs to image provenance, signatures, cosign, notary, etc.),
then there may be NO admission webhook enforcing image provenance.
3. CRDs / Policy engines:
- Absence of any CRD or webhook associated with image-policy / image-signature
solutions (e.g., Cosign, Notary, Connaisseur, Kyverno policies about images)
suggests that image provenance is not being validated.
This script only reports state; configuring ImagePolicyWebhook and the backing
policy/verification service must be done manually following Kubernetes and
your tooling's documentation.
EOF