Quasa
Use QUASA App
Join the pioneer of Web3 crypto freelancing today!
Open
Technology

A Signed Container Image Is Not Enforced Until Admission Checks It

|Author: QUASA Editorial Team|5 min read| 4
A Signed Container Image Is Not Enforced Until Admission Checks It

To make Kubernetes reject untrusted container images automatically, put signature verification in the admission path. Define the protected repositories and trusted signer identity, install Sigstore policy-controller, apply a blocking policy, and opt each workload namespace into validation.

A successful local Cosign check proves that one artifact satisfied the supplied constraints; it does not govern later deployment requests. Admission enforcement evaluates matching workloads before Kubernetes accepts them, while digest references keep the approved content explicit.

1. Establish the signing contract

Cosign verifies the expected signer and issuer before the approved container digest is recorded for deployment.

Start with a signed image produced by your delivery pipeline. Record its repository, immutable digest, certificate identity and OIDC issuer; for keyless signing, the identity should describe the automation principal authorized to release the image, not every account using the same issuer.

Run Cosign verification outside the cluster with the expected identity and issuer. The Kubernetes verification instructions show both constraints, recommend referencing a verified image by digest and identify admission control as the mechanism for deploy-time verification.

Use the approved reference in the form registry.example.com/team/app@sha256:…. A digest identifies specific content, whereas a tag can later resolve to different content; policy-controller can resolve tags during admission, but digest-pinned manifests also make review, promotion and rollback decisions explicit.

2. Install policy-controller without expanding its scope

Begin in a staging cluster or with non-critical namespaces. The official Sigstore installation procedure lists Kubernetes access, kubectl and Helm v3 as prerequisites, then installs the official chart in the cosign-system namespace and checks that its webhook pods are running.

  1. Add the official Sigstore Helm repository and update its index.
  2. Create the cosign-system namespace and install sigstore/policy-controller there.
  3. Wait until the policy-controller pods are running; a recorded Helm release does not prove that the webhook is available.
  4. Pin the chart version and preserve the deployed values so upgrades and rollback are reproducible.
  5. Keep application namespaces outside validation until an applicable policy has been reviewed and applied.

Installation and enforcement are separate states. The webhook may be healthy while application namespaces remain outside its default selector, so pod readiness alone does not show that workloads are protected.

3. Express the trusted signer in a ClusterImagePolicy

A ClusterImagePolicy accepts the authorized release identity and rejects a signature from an unrelated workflow.

Create a ClusterImagePolicy whose image glob covers the intended repository and whose authority represents the trusted signer. For keyless signatures, configure an identity with the expected issuer and subject; use issuerRegExp or subjectRegExp only when necessary, and keep either expression narrow enough to exclude unrelated workflows.

The policy-controller configuration reference says that every matching ClusterImagePolicy must pass, while authorities inside one policy are alternatives. It also documents keyless issuer and subject constraints, tag-to-digest resolution, default rejection for policy failures, the optional warning mode and the namespace label policy.sigstore.dev/include=true.

Review these boundaries before applying the policy:

  • Image scope: the glob must cover every protected repository without absorbing registries that use another trust model.
  • Signer scope: the issuer and subject must identify the approved release workflow, service account or principal.
  • Failure behavior: leave the policy in its blocking default for enforcement. Setting spec.mode to warn permits a noncompliant image and returns a warning instead.
  • Unmatched images: policy-controller rejects them by default, but no-match-policy can be configured to allow or warn. Check that setting before treating namespace opt-in as a complete deny boundary.

Inventory init containers, sidecars, injected agents and operational utilities before tightening the scope. Each image created in an opted-in namespace needs either a matching trust policy or a deliberate, documented exception.

4. Opt in one namespace and prove rejection

An opted-in Kubernetes namespace admits the trusted digest and blocks unsigned or wrongly signed workloads.

Apply the policy, then label one non-critical namespace with policy.sigstore.dev/include=true. Under the default webhook configuration, that label brings resources in the namespace into scope; without it, the presence of a ClusterImagePolicy does not establish namespace-level enforcement.

Use a controlled test matrix that exercises both acceptance and rejection:

  1. Deploy the approved image by its recorded digest and confirm that admission succeeds.
  2. Submit an unsigned image covered by the same image pattern and confirm that the API request is denied.
  3. Submit an image signed by an identity or issuer outside the configured authority and confirm another denial.
  4. If normal manifests use tags, submit an approved tag and verify that the admitted object refers to the resolved immutable content.
  5. Repeat the test with the higher-level workload objects your teams actually submit, such as Deployments, StatefulSets, Jobs or CronJobs.

Save the admission response for each rejected request and check that it names the expected image or policy boundary. A failed request proves the intended control only when the rejection came from signature policy rather than malformed configuration or inaccessible registry data.

5. Roll out with a recovery boundary

Expand enforcement namespace by namespace. Before opting in a critical namespace, enumerate every container it may create—including mutation-injected sidecars and emergency utilities—and assign each image a matching trust decision.

Prepare recovery before changing essential workloads. Preserve the previous Helm release and policy manifests, define who may authorize a temporary warning mode or namespace opt-out, and time-box any relaxation; either action restores scheduling at the cost of suspending the signature boundary.

The completion criterion is observable: an approved digest from the authorized signer is admitted, while an unsigned artifact and a signature from the wrong identity are rejected in every opted-in namespace. At that point, signing is an enforced Kubernetes admission control rather than a manual release check.

Also read:

Share:

Subscribe to our newsletter

Get the latest Web3, AI, and crypto news delivered straight to your inbox.

0