
Binary Authorization + Artifact Registry: Only Signed Images Reach GKE | 2026
Container registry access controls alone do not prevent malicious or untested container images from being deployed to production GKE clusters. Binary Authorization is a deploy-time admission control security service that verifies cryptographic signatures (attestations) before allowing a container to launch. This guide walks through setting up an Artifact Registry repository, creating a Cloud KMS asymmetric key ring, building a Binary Authorization Attestor in Terraform, signing images in GitHub Actions using Sigstore Cosign, and enforcing `ENFORCE` mode on GKE clusters.
By Mateusz Chmielewski · Aug 22, 2026 · 16 min read
What is Binary Authorization?
Binary Authorization is a Google Cloud security service that integrates with GKE admission control to enforce deploy-time constraints. It ensures that only container images that have been built, vulnerability-scanned, and cryptographically signed by authorized CI/CD pipelines can run in your Kubernetes clusters.
Think of your Artifact Registry like a warehouse loading dock, and GKE like an elite concert venue. Storing an image in the warehouse doesn't grant it access to the stage. Binary Authorization is the security bouncer at the stage door. Even if a container arrives at the door, the bouncer checks its wristband (KMS digital signature). No valid signature = entry denied on the spot.
| Concept | Explanation | When to use |
|---|---|---|
| Policy | The organization-wide or cluster-scoped rules defining admission constraints (e.g., 'Require signatures from prod-attestor'). | Applied to GKE clusters in audit or enforcement mode. |
| Attestor | A named entity holding a public key (Cloud KMS) that verifies cryptographic signatures attached to container images. | Create one attestor per pipeline gate (e.g. build-signer, sec-scanner-signer). |
| Container Analysis Note | The metadata storage anchor in GCP where attestations are indexed against container digests. | Linked 1:1 with a Binary Authorization Attestor. |
| Cosign / Sigstore | Open-source container signing tool that signs OCI artifacts directly in Artifact Registry using KMS asymmetric keys. | Standard tool for signing images in CI/CD pipelines. |
| Break-Glass Override | An emergency override mechanism allowing emergency un-signed image deployments, creating a critical Cloud Audit Log entry. | Used during catastrophic production outages when CI signing pipelines are unavailable. |
Why Image Signing is Essential for Zero-Trust Kubernetes
If an attacker compromises developer credentials or an Artifact Registry IAM role, they can overwrite a container image tag (e.g., `:latest` or `:v1.2.0`) with malicious code. Kubernetes will pull and run the compromised image without warning because registry permissions were valid.
Binary Authorization checks the immutable sha256 container digest and cryptographic signature, not the tag. If an image binary is tampered with or built outside the authorized CI pipeline, GKE rejects the pod creation request instantaneously.
| Feature | thisService | altA | altB |
|---|---|---|---|
| Security Layer | Binary Auth: GKE Admission Control (Deploy-Time) | Artifact Registry IAM (Upload-Time) | Vulnerability Scanning (Static Analysis) |
| Protection Target | Blocks unauthorized container binaries from executing | Restricts who can push images to registry | Identifies known CVEs in code layers |
| Verification Basis | Immutable `sha256` digest & KMS signature | Mutable container tags (`:latest`) | Package dependency list |
| Bypass Protection | Cannot be bypassed without explicit Break-Glass log | Bypassed if IAM credentials leak | Does not block execution by default |
| Integration | Native GKE & Cloud Run integration | Registry level | CI pipeline level |
Prerequisites
- GKE Cluster (Standard or Autopilot) running Kubernetes v1.26+
- GCP Project with Binary Authorization API (`binaryauthorization.googleapis.com`), Container Analysis API (`containeranalysis.googleapis.com`), and Cloud KMS API (`cloudkms.googleapis.com`) enabled
- Terraform CLI v1.6+
- Sigstore Cosign CLI installed locally or in CI (`cosign` v2.2+)
Step-by-Step Guide
Step 1: Provision Cloud KMS Asymmetric Key Pair for Signing
Create a Cloud KMS Key Ring and an Asymmetric CryptoKey with purpose `ASYMMETRIC_SIGN` in Terraform. Binary Authorization requires an asymmetric key pair (Elliptic Curve or RSA). The private key remains securely inside KMS for signing, while the public key is registered with the Attestor.
# kms_signing.tf — Asymmetric Signing Key Pair
resource "google_kms_key_ring" "binauthz" {
name = "binauthz-signing-keyring"
location = "europe-west1"
project = var.project_id
}
resource "google_kms_crypto_key" "attestor_key" {
name = "prod-build-attestor-key"
key_ring = google_kms_key_ring.binauthz.id
purpose = "ASYMMETRIC_SIGN"
version_template {
algorithm = "EC_SIGN_P256_SHA256"
protection_level = "SOFTWARE" # Use HSM for Hardware Security Module
}
lifecycle {
prevent_destroy = true
}
}
# Fetch public key for Attestor binding
data "google_kms_crypto_key_version" "attestor_key_ver" {
crypto_key = google_kms_crypto_key.attestor_key.id
version = 1
}
Step 2: Create Container Analysis Note and Attestor in Terraform
Create a Container Analysis Note and link it to a `google_binary_authorization_attestor` in Terraform. Container Analysis Notes act as metadata anchors for attestations. The Attestor object binds the KMS public key to the Note metadata.
# binauthz_attestor.tf — Container Analysis Note & Attestor
resource "google_container_analysis_note" "build_note" {
name = "prod-build-note"
project = var.project_id
attestation_authority {
hint {
human_readable_name = "Production CI Build Pipeline Signature"
}
}
}
resource "google_binary_authorization_attestor" "build_attestor" {
name = "prod-build-attestor"
project = var.project_id
attestation_authority_note {
note_reference = google_container_analysis_note.build_note.name
public_keys {
id = data.google_kms_crypto_key_version.attestor_key_ver.id
pkix_public_key {
public_key_pem = data.google_kms_crypto_key_version.attestor_key_ver.public_key[0].pem
signature_algorithm = data.google_kms_crypto_key_version.attestor_key_ver.public_key[0].algorithm
}
}
}
}
Step 3: Configure Binary Authorization Policy on GKE Cluster
Apply a `google_binary_authorization_policy` to require attestations from the created Attestor for all cluster deployments. Setting `evaluation_mode = ENFORCE_POLICY` instructs GKE admission controllers to block pod execution if the container digest lacks a valid signature.
# binauthz_policy.tf — Binary Authorization Cluster Policy
resource "google_binary_authorization_policy" "policy" {
project = var.project_id
default_admission_rule {
evaluation_mode = "REQUIRE_ATTESTATION"
enforcement_mode = "ENFORCE_BLOCK_AND_AUDIT_LOG"
require_attestations_by = [
google_binary_authorization_attestor.build_attestor.id
]
}
# Whitelist system container images (e.g. GKE system components)
cluster_admission_rules {
cluster = "europe-west1.prod-gke-cluster"
evaluation_mode = "REQUIRE_ATTESTATION"
enforcement_mode = "ENFORCE_BLOCK_AND_AUDIT_LOG"
require_attestations_by = [google_binary_authorization_attestor.build_attestor.id]
}
global_policy_evaluation_mode = "ENABLE"
}
Step 4: Sign Container Images using Cosign and Cloud KMS in CI/CD
Build, push, and sign container images in Artifact Registry using `cosign` and Cloud KMS private keys. Signing must occur immediately after image build and vulnerability scan in your CI pipeline, binding the exact sha256 digest to the KMS signature.
# build_and_sign.sh — CI/CD Pipeline Build & Sign Workflow
IMAGE_TAG="europe-west1-docker.pkg.dev/${PROJECT_ID}/app-repo/my-service:v1.0.0"
KMS_KEY_PATH="gcpkms://projects/${PROJECT_ID}/locations/europe-west1/keyRings/binauthz-signing-keyring/cryptoKeys/prod-build-attestor-key/cryptoKeyVersions/1"
# Step 1: Build and Push container to Artifact Registry
docker build -t ${IMAGE_TAG} .
docker push ${IMAGE_TAG}
# Step 2: Extract immutable sha256 digest
IMAGE_DIGEST=$(gcloud artifacts docker images describe ${IMAGE_TAG} --format='value(image_summary.digest)')
FULL_IMAGE_URI="europe-west1-docker.pkg.dev/${PROJECT_ID}/app-repo/my-service@${IMAGE_DIGEST}"
# Step 3: Sign container image digest using Cosign + Cloud KMS
cosign sign --key ${KMS_KEY_PATH} ${FULL_IMAGE_URI}
# Step 4: Verify signature stored in Artifact Registry
cosign verify --key ${KMS_KEY_PATH} ${FULL_IMAGE_URI}
Step 5: Test GKE Enforcement and Unsigned Image Blocking
Attempt to deploy an unsigned container image to GKE and verify admission controller rejection. Testing deployment failures proves that Binary Authorization admission control is actively defending your GKE cluster against unauthorized workloads.
# Step 1: Try deploying an unsigned public image (e.g. nginx)
kubectl create deployment test-unsigned --image=nginx:latest
# Expected output: Admission webhook rejection error!
# Error from server (Forbidden): admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request:
# Image nginx:latest denied by Binary Authorization policy.
# Step 2: Deploy validly signed image digest
kubectl create deployment test-signed --image=europe-west1-docker.pkg.dev/${PROJECT_ID}/app-repo/my-service@sha256:abc123...
# Verify pod status
kubectl get pods -l app=test-signed
Step 6: Emergency Break-Glass Override Procedure
Execute an emergency break-glass deployment for critical production incidents when image signing pipelines are down. Break-glass mechanisms ensure system availability during operational emergencies while creating an immutable audit trail for post-incident review.
# pod_breakglass.yaml — Emergency Break-Glass Pod Spec
apiVersion: v1
kind: Pod
metadata:
name: emergency-hotfix-pod
annotations:
# Break-glass annotation bypasses Binary Auth policy block
alpha.image.policy.k8s.io/break-glass: "true"
spec:
containers:
- name: hotfix
image: europe-west1-docker.pkg.dev/PROJECT_ID/app-repo/my-service:unsigned-hotfix
Verification & Health Check
Best Practices
- Sign Images by Immutable Digest, Never by Tag
- Separate Build Attestors from Security Scanner Attestors
Common Mistakes
- {"errorCode":"BINAUTHZ_ADMISSION_DENIED","symptoms":"Kubernetes pod fails creation with Forbidden error: denied by Binary Authorization policy.","rootCause":"The container image digest was pushed to Artifact Registry but not signed with the specified KMS attestor key.","fixCommand":"cosign sign --key $KMS_KEY_PATH $FULL_IMAGE_DIGEST_URI","code":"# Execute signing step in CI pipeline\ncosign sign --key gcpkms://projects/PROJ/locations/eu-west1/keyRings/ring/cryptoKeys/key/cryptoKeyVersions/1 $IMAGE_URI\n","language":"bash","filename":"fix_signing.sh","prevention":"Enforce image signing as a mandatory blocking step in CI/CD pipeline definitions."}
Cost Analysis
| Feature | metric | cost1k | cost10k | cost100k | cost1m |
|---|---|---|---|---|---|
| Binary Authorization Policy Engine | $0.00 | $0.00 | $0.00 | $0.00 / month | |
| Cloud KMS Asymmetric Key ($0.06/key/mo) | $0.06 | $0.06 | $0.06 | $0.72 / yr | |
| KMS Asymmetric Sign Operations (3,000 ops/mo) | $0.09 | $0.09 | $0.09 | $1.08 / yr | |
| Container Analysis Metadata Storage | < $0.05 | < $0.05 | < $0.05 | < $0.60 / yr | |
| Total Monthly Supply Chain Security Cost | ~$0.20 / month | ~$0.20 / month | ~$0.20 / month | ~$2.40 / yr |