Skip to main content
RunBook Academy

KubernetesLXIV · Kubernetes Supply Chain SecuritySupply chain security

Cosign — image signing and verification

Advanced⏱ ~14 minkubectlcosignkyverno

What you'll learn

  • Sign a container image with Cosign using a key pair
  • Use keyless signing with Fulcio (Sigstore) and Rekor transparency log
  • Verify the signature at admission with Kyverno or a webhook
  • Manage Cosign keys securely (key rotation, HSM-backed keys)

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

Cosign is the Sigstore project’s tool for signing and verifying container images. It uses public-key cryptography (or keyless signing via Fulcio + Rekor) to produce a signature that is stored in the registry alongside the image. Admission (Kyverno, webhook) verifies the signature at deployment time. This lesson covers the signing workflow, the key management, the verification, and the production patterns.

The Cosign signing model

Cosign signs images with a public/private key pair:

flowchart LR
    A[Image] --> B[Sign with private key]
    B --> C[Signature]
    C --> D[Attach to registry]
    E[Admission] --> F[Fetch signature]
    F --> G[Verify with public key]

The private key is held by the signer (the CI pipeline). The public key is distributed to verifiers (Kyverno, admission webhooks).

Signing an image

Key-based signing:

# Generate a key pair
cosign generate-key-pair
# Enter password for private key
# cosign.pub and cosign.key are written

# Sign the image
cosign sign --key cosign.key myapp:v1.0
# Outputs: pushed signature to <registry>/myapp:sha256-abc.sig

Keyless signing:

# Authenticate to Fulcio via OIDC (e.g., GitHub Actions OIDC token)
cosign sign --fulcio-url=https://fulcio.sigstore.dev \
  --rekor-url=https://rekor.sigstore.dev \
  myapp:v1.0
# The signature is logged to Rekor; the certificate is from Fulcio

The signature is an OCI artifact in the registry. The artifact is referenced by the image’s digest.

Verifying the signature at admission

Kyverno’s verifyImages rule:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signatures
spec:
  validationFailureAction: Enforce
  rules:
  - name: verify-signatures
    match:
      resources:
        kinds: ["Pod"]
    verifyImages:
    - imageReferences:
      - "registry.example.com/*"
      attestors:
      - entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              ...
              -----END PUBLIC KEY-----

A Pod whose image is not signed (or whose signature is invalid) is rejected at admission. The image’s trust chain is the public key.

flowchart LR
    A[Pod admission] --> B[Fetch image signature]
    B --> C{Signature valid?}
    C -->|yes| D[Allow]
    C -->|no| E[Reject]

Key management

A Cosign key pair is the root of trust. The operational discipline:

  1. Generate the key pair. cosign generate-key-pair. The private key is stored in a vault (HashiCorp Vault, cloud KMS, or HSM).
  2. Distribute the public key. Every verifier (Kyverno, admission webhook) has the public key.
  3. Rotate the key. Every 90 days (or per the organisation’s policy). The rotation is a documented procedure: sign with both old and new keys during the overlap window, then remove the old key.
  4. Compromise response. If the private key is compromised, rotate immediately and re-sign every image.

Production patterns

  1. Keyless signing in CI. The CI pipeline signs with Fulcio + Rekor; no long-lived key to manage.
  2. Key-based signing for production. Production builds use a hardware-backed key (HSM, YubiHSM).
  3. Verify at admission. Every Pod is checked against the public key.
  4. Rotate keys quarterly. The rotation procedure is documented.

Production failure modes

  1. Public key not distributed. The verifier has no public key; all signatures fail. The fix is to distribute the public key to every verifier.
  2. Private key in plaintext. The CI pipeline stores the key in a config file. The fix is to use a vault or HSM.
  3. Key rotation is not documented. The team cannot rotate the key without breaking all signatures. The fix is to document the rotation procedure.
  4. Signature verification is disabled. The team turns off verification to debug; verification is not re-enabled. The fix is to enforce verification in CI/CD.

Cross-course references

  • The Linux course covers public-key cryptography (RSA, ECDSA, Ed25519).
  • The Observability course covers the audit log entries for signature verification.

Quiz

Knowledge check · 4 questions

  1. Q1. What is keyless signing with Cosign?

  2. Q2. Every verifier (Kyverno, admission webhook) must have the Cosign public key to verify signatures.

  3. Q3. Your CI pipeline stores the Cosign private key in a plaintext config file. An attacker gains read access to the config file via a compromised CI runner. The attacker now has the signing key. Walk the response.

    The CI pipeline signs every image with the Cosign private key. The private key is at `/etc/cosign/cosign.key` on the CI runner. An attacker who compromises the runner has read access to the key. The attacker can now sign malicious images.

  4. Q4. Name three key-management best practices for Cosign signing keys.

Passing score: 75%. Answers are checked in this browser.

Production discipline

Cosign is the right primitive for image signing. A defensible signing programme uses keyless signing for CI pipelines and hardware-backed keys for production, verifies signatures at admission with Kyverno or a webhook, rotates keys quarterly, and stores keys in a vault or HSM. A cluster whose images are all signed and verified has a supply chain that is auditable; a cluster whose images are not signed has a supply chain that is not.