DevOps Peach

Security (DevSecOps) · Software supply chain security · Lesson 3 of 4

Signing and verifying images with cosign

A signature proves who built an image and that it has not been altered; Sigstore’s cosign signs with a key or keylessly through OIDC, stores signatures next to the image in the registry, and clusters can reject unsigned images.

Practice interactively →

Why sign images

Registries or transport can be compromised, and tags can be overwritten. A signature binds an image (by digest) to the identity of the person or pipeline that built it, so the deploy side can check: "this image was built by example-org's pipeline from the myapp repo and has not been altered".

Sigstore and cosign

Sigstore is an OpenSSF project made of:

Component Role
cosign CLI to sign and verify images, blobs and attestations
Fulcio A CA issuing short-lived certificates based on OIDC identity
Rekor A public transparency log recording every signature

Signing with a key pair

cosign generate-key-pair                       # creates cosign.key (password-protected) and cosign.pub
cosign sign --key cosign.key registry.example.com/myapp@sha256:EXAMPLE
cosign verify --key cosign.pub registry.example.com/myapp@sha256:EXAMPLE

The private key can live in a KMS (--key awskms://..., azurekms://...) instead of a file.

Keyless: no keys to manage

In CI with OIDC (GitHub Actions, GitLab), cosign takes the workflow's identity token, Fulcio issues a certificate valid for minutes, and the signature is recorded in Rekor. There is no long-lived private key to leak.

cosign sign registry.example.com/myapp@sha256:EXAMPLE
cosign verify registry.example.com/myapp@sha256:EXAMPLE \
  --certificate-identity-regexp '^https://github.com/example-org/myapp/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

Keyless verification must state the expected identity and issuer; otherwise a signature by anyone is accepted.

sequenceDiagram
  participant CI as CI workflow
  participant F as Fulcio
  participant R as Rekor
  participant REG as Registry
  CI->>F: workflow OIDC token
  F-->>CI: short-lived certificate
  CI->>REG: push signature next to the image
  CI->>R: record in the transparency log

Attestations

Beyond signatures, cosign attaches signed attestations: an SBOM, scan results, SLSA provenance.

cosign attest --predicate sbom.cdx.json --type cyclonedx registry.example.com/myapp@sha256:EXAMPLE

Enforcing at deploy time

Signing without checking is pointless. In Kubernetes, Kyverno (verifyImages) or the Sigstore policy-controller reject Pods using unsigned images or images signed by an unexpected identity.

Traps: signing a tag instead of a digest; keyless verification without an identity restriction; keeping cosign.key in the repo; signing while the cluster never checks.

Practice interactively →