> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure Image Provenance Image Policy Webhook Admission Controller

### More Info:

Configure Image Provenance for your deployment.

### Risk Level

Low

### Address

Security

### Compliance Standards

* CIS GKE

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Review current admission configuration for ImagePolicyWebhook**
           * On any machine with `kubectl` access, check whether an `ImagePolicyWebhook` admission configuration file is referenced in the API server flags (GKE Autopilot/managed control planes generally hide this, so this may not be visible):
             ```bash theme={null}
             kubectl get validatingwebhookconfiguration,mutatingwebhookconfiguration -A
             ```
           * Capture the output and look for any webhook explicitly dedicated to image provenance (for example, a name containing `image-policy`, `imageprovenance`, or your chosen image security tool).

        2. **Identify and inspect any image-policy–related webhook**
           * For each candidate webhook from step 1, describe it to confirm its purpose and scope:
             ```bash theme={null}
             kubectl describe validatingwebhookconfiguration <webhook-name>
             kubectl describe mutatingwebhookconfiguration <webhook-name>
             ```
           * Verify it is configured to intercept `CREATE` and preferably `UPDATE` operations on `pods` (and optionally `deployments`, `daemonsets`, etc.) and that it is reachable (no failing webhook calls reported in `Events` sections).

        3. **Verify that image provenance checks are actually enforced**
           * From the webhook descriptions in step 2, confirm that the webhook’s rules or configuration refer to image provenance or an external policy engine that validates image signatures, attestations, or trusted registries (for example, using cosign, Binary Authorization, or another signing/verification system).
           * If the webhook is only logging/monitoring and not rejecting non-compliant images, update its policy configuration (per your chosen image provenance solution’s documentation) so that it denies pod creation when images are not verified or are from untrusted sources.

        4. **Deploy or integrate an ImagePolicyWebhook solution if none exists**
           * If step 1 finds no suitable webhook, choose and deploy an image provenance solution that integrates via ImagePolicyWebhook or an equivalent admission webhook (for example, a tool that verifies image signatures/attestations). Follow that solution’s installation guide to:
             * Deploy the controller components (usually a Deployment/Service in a dedicated namespace).
             * Create a `ValidatingWebhookConfiguration` (and `MutatingWebhookConfiguration` if required) that targets `CREATE` (and `UPDATE`) of `pods` and relevant workload resources in all namespaces where enforcement is desired.

        5. **Test enforcement using a non-compliant image**
           * Attempt to create a pod using an image that should fail provenance checks (for example, an unsigned image or one from a disallowed registry):
             ```bash theme={null}
             cat << 'EOF' | kubectl apply -f -
             apiVersion: v1
             kind: Pod
             metadata:
               name: image-provenance-test
             spec:
               containers:
               - name: test
                 image: gcr.io/google-containers/busybox:latest
                 command: ["sh", "-c", "sleep 3600"]
             EOF
             ```
           * Confirm that the pod creation is rejected with an admission error message from your image policy webhook indicating failed provenance/signature/attestation checks.

        6. **Re-verify cluster-wide coverage and document the policy**
           * Re-list webhook configurations to ensure your image provenance webhook is present and cluster-wide:
             ```bash theme={null}
             kubectl get validatingwebhookconfiguration,mutatingwebhookconfiguration -A
             ```
           * Confirm that:
             * All target namespaces and resource types are covered by the webhook’s rules.
             * The webhook’s failure policy and timeouts are set per your risk appetite (typically fail-closed for production).
           * Document the configured image provenance policy (what is required for images to be admitted, which registries/signers are trusted, and any exemptions) for future audits and change control.
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) Check which admission plugins are enabled on the API server
        #    (GKE Autopilot/Standard uses managed control planes; this is informational)
        # Run on: any machine with kubectl access
        kubectl get pod -n kube-system -l component=kube-apiserver -o yaml | grep -iE 'admission-control|enable-admission-plugins|admission-plugins' -n
        ```

        **What to look for (problem indicators)**

        * On self-managed control planes, **ImagePolicyWebhook** is **missing** from the enabled admission plugins.
        * On fully managed GKE control planes you typically won’t see or be able to modify these flags; absence of `ImagePolicyWebhook` means it is not in use.

        ***

        ```bash theme={null}
        # 2) Discover any ImagePolicyWebhook-related configuration objects
        #    (ConfigMap, Secret) that might define webhook settings
        # Run on: any machine with kubectl access
        kubectl get configmaps,secrets -A | grep -i imagepolicy || true
        ```

        **Problem indicators**

        * No ConfigMap/Secret exists that appears to configure an image policy webhook, while your security policy requires image provenance enforcement.
        * Stale/unused webhook configs (e.g. legacy ConfigMap present but no corresponding admission plugin/webhook enabled).

        ***

        ```bash theme={null}
        # 3) List all Mutating and ValidatingWebhookConfigurations
        #    to see if any webhooks enforce image provenance
        # Run on: any machine with kubectl access
        kubectl get mutatingwebhookconfigurations,validatingwebhookconfigurations
        ```

        ```bash theme={null}
        # 3a) Inspect details of potential image-related webhooks
        # Replace <WEBHOOK_NAME> with a name from the list above that looks image-related
        kubectl get validatingwebhookconfiguration <WEBHOOK_NAME> -o yaml
        kubectl get mutatingwebhookconfiguration   <WEBHOOK_NAME> -o yaml
        ```

        **Problem indicators**

        * No webhook configuration with a purpose related to image validation/provenance (no mention of “image”, “cosign”, “notary”, “policy”, etc. in names/annotations).
        * Existing image-related webhook does **not** include `pods` in `rules.resources` and `create`/`update` in `rules.operations`.
        * `failurePolicy: Ignore` for a critical image provenance webhook (allows unverified images if the webhook is down, which may violate your policy).
        * `namespaceSelector` or `objectSelector` excludes namespaces where you expect image provenance to be enforced (e.g. `default`, `prod-*`).

        ***

        ```bash theme={null}
        # 4) Examine how images are currently used in pods
        #    (to help assess whether provenance policies are being followed)
        # Run on: 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
        ```

        **Problem indicators**

        * Images from untrusted/unapproved registries based on your organization’s policy.
        * Images without digests (e.g. `:latest` tags only), when your policy requires digests or signed images.
        * Wide variety of arbitrary public images, suggesting there is no enforcement on allowed sources or signatures.

        ***

        ```bash theme={null}
        # 5) (If you already have an image-policy webhook) test its behavior with a sample pod
        #    Create a minimal pod spec using an image that should be rejected under your policy
        # Run on: any machine with kubectl access
        cat << 'EOF' > /tmp/test-untrusted-image-pod.yaml
        apiVersion: v1
        kind: Pod
        metadata:
          name: test-untrusted-image
          namespace: default
        spec:
          containers:
          - name: c
            image: docker.io/library/busybox:latest
            command: ["sh", "-c", "sleep 3600"]
        EOF

        kubectl apply -f /tmp/test-untrusted-image-pod.yaml
        ```

        Then check the result:

        ```bash theme={null}
        kubectl describe pod test-untrusted-image -n default
        ```

        **Problem indicators**

        * Pod is admitted and runs successfully even though it clearly violates your defined image provenance policy (for example, untrusted public registry, unsigned image, tag-only).
        * No admission webhook-related events or error messages appear in `kubectl describe pod`, indicating no policy check occurred.

        ***

        These commands surface:

        * Whether any admission mechanism that can enforce image provenance (ImagePolicyWebhook or equivalent webhook) appears to be configured.
        * Whether existing webhooks actually cover pod creations/updates.
        * How images are currently used, so a human can compare observed practice with the organization’s required image provenance policy.

        Deciding whether the current configuration is acceptable, and what changes to make, requires human review against your organization’s security policy and the Kubernetes image provenance guidance.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Purpose: Report cluster-wide state related to ImagePolicyWebhook / image provenance
        # Scope: Run on any machine with kubectl access and current context set

        set -euo pipefail

        echo "=== 1) Check for ImagePolicyWebhook admission plugin on API server(s) ==="
        echo "NOTE: On GKE, control-plane flags are managed by Google; this check can only"
        echo "      infer usage from API behavior, not by reading API server flags."

        echo
        echo "--- 1a) Attempt to discover admission configuration (v1 AdmissionConfiguration) ---"
        # This will normally be forbidden on managed control planes; that's expected.
        kubectl get validatingadmissionpolicies,validatingwebhookconfigurations,mutatingwebhookconfigurations \
          -A -o wide 2>&1 | sed 's/^/  /'

        echo
        echo "=== 2) Look for evidence of ImagePolicyWebhook configuration objects ==="
        echo "--- 2a) Cluster-wide search for objects whose name suggests image policy usage ---"
        kubectl get mutatingwebhookconfigurations,validatingwebhookconfigurations \
          -A -o json 2>/dev/null | jq -r '
          .items[]
          | select(
              (.metadata.name|test("imagepolicy|image-policy|image_provenance|provenance"; "i"))
              or ([.webhooks[].name]|join(",")|test("imagepolicy|image-policy|image_provenance|provenance"; "i"))
            )
          | "Kind: \(.kind), Name: \(.metadata.name)\n  Webhooks: \([.webhooks[].name] | join(", "))\n"
        ' || echo "  (No webhook configurations matching common image policy naming patterns found.)"

        echo
        echo "--- 2b) Search for Gatekeeper / Kyverno / similar policy engines that might enforce image provenance ---"
        echo "  (These do not guarantee provenance, but they can be part of the implementation.)"
        kubectl get ns 2>/dev/null | sed 's/^/  /'
        echo
        echo "  Checking for common policy-engine namespaces:"
        for ns in gatekeeper-system kyverno opa opa-system constraint-system; do
          if kubectl get ns "$ns" >/dev/null 2>&1; then
            echo "  - Found namespace: $ns"
            kubectl get deploy,ds -n "$ns" -o wide | sed 's/^/      /'
          else
            echo "  - Namespace not present: $ns"
          fi
        done

        echo
        echo "=== 3) Inspect cluster-wide pod image usage (to assess reliance on untrusted registries/images) ==="
        echo "--- 3a) List unique image registries in use ---"
        kubectl get pods -A -o json | jq -r '
          [.items[].spec.containers[].image? // empty,
           .items[].spec.initContainers[].image? // empty] 
          | unique[]
        ' 2>/dev/null | awk -F/ '
          {
            if (NF==1) { print "docker.io/library (implicit) :: " $0 }
            else if ($1 ~ /.+\..+/) { print $1 " :: " $0 }
            else { print "docker.io :: " $0 }
          }
        ' | sort -u | sed 's/^/  /'

        echo
        echo "--- 3b) List pods using images from registries other than an expected trusted domain (edit TRUSTED_DOMAIN) ---"
        TRUSTED_DOMAIN="gcr.io"   # CHANGE to your org's trusted registry root, e.g. "gcr.io/my-project" or "us-docker.pkg.dev/your-org"
        echo "  Using TRUSTED_DOMAIN=${TRUSTED_DOMAIN} for heuristic check."
        echo "  Pods using images NOT starting with this trusted domain:"
        kubectl get pods -A -o json | jq -r --arg td "$TRUSTED_DOMAIN" '
          .items[]
          | {
              ns: .metadata.namespace,
              pod: .metadata.name,
              node: .spec.nodeName,
              images: (
                [.spec.containers[].image? // empty,
                 .spec.initContainers[].image? // empty] | unique
              )
            }
          | select([.images[] | startswith($td)] | any | not)
          | "ns=\(.ns) pod=\(.pod) node=\(.node) images=\(.images|join(","))"
        ' 2>/dev/null | sed 's/^/  /'

        echo
        echo "=== 4) Optional: Look for annotations/labels hinting at image provenance policies ==="
        echo "--- 4a) Search namespaces for policy-related labels/annotations ---"
        kubectl get ns -o json | jq -r '
          .items[]
          | {
              name: .metadata.name,
              labels: (.metadata.labels // {}),
              ann: (.metadata.annotations // {})
            }
          | select(
              ( [ ( .labels|to_entries[]?.key ), ( .ann|to_entries[]?.key ) ]
                | flatten[]
                | tostring
                | test("imagepolicy|image-policy|provenance|sigstore|cosign|slsa"; "i")
              )
            )
          | "Namespace: \(.name)\n  Labels: \(.labels)\n  Annotations: \(.ann)\n"
        ' 2>/dev/null || echo "  (No namespaces with obvious image-provenance-related labels/annotations.)"

        echo
        echo "=== 5) Summary / How to interpret this output ==="
        cat <<'EOF'
        INTERPRETATION (what indicates a potential problem):

        1) No clear ImagePolicyWebhook or equivalent:
           - If section 2a shows no webhook configurations whose names/webhook names suggest image policy
             or provenance, there is likely NO ImagePolicyWebhook-based protection configured.
           - Managed control planes (like GKE) may hide API-server flags, but you should still expect to
             see some webhook or policy engine explicitly guarding image usage if provenance is required.

        2) No policy engines enforcing image rules:
           - If section 2b shows NONE of the common policy namespaces (gatekeeper-system, kyverno, etc.),
             and your organization has not documented another mechanism, image provenance is probably NOT
             centrally enforced.

        3) Broad use of arbitrary/untrusted registries:
           - In section 3a, many distinct public registries (e.g. docker.io, quay.io) without restriction
             suggests weak control over image sources.
           - In section 3b, a large number of pods listed as "NOT starting with TRUSTED_DOMAIN" indicates
             workloads pulling from outside your intended trusted registry; provenance controls are likely
             incomplete or absent.

        4) Lack of policy-related labels/annotations:
           - If section 4a shows no namespaces with labels/annotations referring to image policy,
             provenance, sigstore, cosign, SLSA, etc., there may be no documented, namespace-scoped
             provenance enforcement.

        This script does NOT prove compliance or non-compliance by itself. Its output should be
        reviewed together with your cluster design and documented security controls to decide whether
        ImagePolicyWebhook (or an equivalent mechanism) is configured to enforce image provenance
        for all relevant workloads.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://github.com/kubernetes/community/blob/master/contributors/design-proposals/image-provenance.md](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/image-provenance.md)
