Hedronite · Cert Lesson · CNCF CKS · Sat 2026-10-03

CKS attestation admission enforced block versus dry-run audit

A prefix check asks where the image came from. An attestor asks whether this digest was signed.

Lesson Class: Cert (T2 · CKS supply-chain admission)
Referent: GKE Binary Authorization evaluationMode + enforcementMode
Not a repeat: not 08-07 prefix webhook · not 09-12 PSA · not 09-30 HPA · not 09-27 drain
Paired Ops: project policy + cluster flag
Paired Dev: image-reference match guards
evaluationMode
ALWAYS_ALLOW, ALWAYS_DENY, or REQUIRE_ATTESTATION.
enforcementMode
Block and log, or admit and still log.
Two exemptions
Google system images, and your namePattern list. Not a namespace label.
Dry-run changes the action, not the attestor list.

<!-- hal:authoritative:yaml -->

A prefix check asks where the image came from. An attestor asks whether someone signed this digest. Dry-run changes the action, not the question.

§I. Frame

CKS day, odd counter. Recent CNCF lessons already took HPA (09-30), upgrade skew plus drain and eviction (09-27), StorageClass/PVC/PV (09-24), and ServiceAccount hardening with EKS Pod Identity (09-21). PSA restricted enforce was 09-12. AppArmor and seccomp on the node were 08-31.

Supply chain was 08-07: smaller base images, vulnerability scan, SBOM, and an ImagePolicyWebhook. The vault sample for that webhook still does one thing. Its README says the program allows only images that start with gcr.io/. That is a string prefix. It is not a signature.

The claim for today: admission can instead require a verified attestation on the image digest. GKE Binary Authorization is the managed form used in the Ops lesson. The CKS skill is the split between the check and the action, and the difference between a prefix webhook and an attestor.

§II. Two fields, not one knob

The policy YAML reference names the default rule defaultAdmissionRule.

evaluationMode is the check:

enforcementMode is the action when the check fails:

Dry-run is how you watch a new attestor before it blocks deploys. It is not a second, weaker attestor. The attestor list stays the same.

A cluster-specific rule lives under clusterAdmissionRules, keyed LOCATION.CLUSTER_NAME (the Terraform docs use us-central1-a.prod-cluster). If the cluster has no key, the default rule is the one that runs.

§III. What the attestor is checking

Attestors sign image digests, not floating tags. A Pod that says app:1.4.2 can still pass if, at admission, that tag resolves to a digest the attestor has already signed. The same tag can fail tomorrow because it moved. A spec that already contains @sha256: names the digest the attestor must have signed. The Rust census in the Dev lesson only detects that shape. Passing the census is not a CKS "allowed" answer.

requireAttestationsBy entries are attestor resource ids, projects/PROJECT/attestors/NAME. The attestor has to exist before the policy references it. Creating the note and the key is a separate admin step. The exam-shaped question is which rule field lists them, not how to mint a KMS key.

§IV. What is allowed without your signature

Two exemption mechanisms show up in the same policy file. Do not merge them.

globalPolicyEvaluationMode: ENABLE tells Binary Authorization to use Google's own system-image evaluation. GKE-managed images then do not need your attestor. Leave it off, and a policy of REQUIRE_ATTESTATION can reject the images the control plane is trying to run.

admissionWhitelistPatterns is a list of namePattern strings you write. A pattern such as us-central1-docker.pkg.dev/payments-prod/break-glass/* skips the rule for matching names. That is the break-glass door. It is also the door an attacker uses if the pattern is *.

Neither mechanism is a namespace label. pod-security.kubernetes.io/enforce=restricted is PSA. It does not turn attestation on or off. ImagePolicyWebhook, the 08-07 control, is also not this list. That webhook is a Kubernetes admission plugin with its own backend. The study-guide backend hard-codes a registry prefix. Binary Authorization's whitelist is a field on the project policy, evaluated by GKE's enforcer, and it still is not a signature check.

§V. Drill

Answer from the field, not from the product nickname.

  1. The Pod is created, and Cloud Audit Logs still show an attestation miss. Which value is set? enforcementMode: DRYRUN_AUDIT_LOG_ONLY with a failing evaluationMode. Blocked Pods mean ENFORCED_BLOCK_AND_AUDIT_LOG.
  2. You want every non-exempt image to need the build attestor, and one cluster to deny all images. Default rule REQUIRE_ATTESTATION plus that attestor. The special cluster gets clusterAdmissionRules with ALWAYS_DENY.
  3. A webhook that allows only gcr.io/ would still admit an unsigned image from that registry. An attestor rule would not, unless the name is whitelisted or the mode is dry-run.
  4. Putting requireAttestationsBy on an ALWAYS_ALLOW rule is invalid. The list is required only for REQUIRE_ATTESTATION, and it must be empty otherwise.

§VI. Close

CKS supply chain already covered scan, SBOM, and a prefix webhook. This lesson adds the attestor question and the enforce-versus-dry-run action. GKE expresses both as evaluationMode and enforcementMode on one admission rule, with system images and name patterns as the only exemptions in that policy.

Paired Ops declares the cluster flag and the project policy in Terraform, then censuses image strings. Paired Dev matches those strings. Neither pair proves the signature. The policy does, at admission time.

Related