🟡 Intermediate

Sigstore a Cosign — Podpisovanie Container Images

Sigstore je open-source projekt pod Linux Foundation / OpenSSF, ktorý prináša jednoduché, bezplatné a automatizovateľné digitálne podpisovanie softvérových artefaktov — container images, binárok, git tagov, SBOM súborov — bez potreby manuálne spravovaných kľúčov.

Jeho hlavná myšlienka je radikálne zjednodušiť podpisovanie: namiesto dlhodobých GPG alebo PGP kľúčov používa krátke, jednorazové certifikáty viazané na OIDC identitu (GitHub, Google, GitLab, Microsoft, custom IdP). Výsledok: podpis môžete overiť späť na konkrétny GitHub Actions workflow alebo konkrétneho človeka bez toho, aby ste si spravovali súkromný kľúč.


Prečo supply-chain security je problém

Za posledných päť rokov sa útoky na softvérový supply-chain stali bežnou praxou:

  • SolarWinds (2020) — útočník vsadil backdoor do build pipeline, ktorá sa rozšírila na 18 000 zákazníkov.
  • Codecov (2021) — kompromitovaný bash uploader získal env premenné tisícov CI behov.
  • ua-parser-js (2021) — npm package s 8M downloads týždenne bol injektovaný malware.
  • xz-utils (2024) — backdoor v utility, ktorý bol takmer nasadený do ssh vo veľkých distribúciách.

Klasická odpoveď bola: "podpíšte svoj softvér GPG kľúčom". V praxi to nefunguje — developeri strácajú kľúče, CI runnery nemajú kam bezpečne uložiť privátny kľúč, rotácia je ťažká, verifikácia sa nerobí.

Sigstore nabúral tento model tým, že kľúče sú krátkodobé (platia 10 minút) a podpis je viazaný na identitu v čase podpisu (OIDC token), nie na dlhodobý kľúč.


Komponenty Sigstore

Sigstore stojí na troch hlavných komponentoch:

1. Fulcio — certifikačná autorita

Krátkodobá CA, ktorá vystaví X.509 certifikát platný 10 minút na základe overeného OIDC tokenu. Certifikát obsahuje identitu (napr. user@example.com alebo https://github.com/org/repo/.github/workflows/release.yml@refs/tags/v1.2.3).

2. Rekor — transparency log

Verejný, append-only log, do ktorého sa zapisujú všetky podpisy. Podobný Certificate Transparency logom pre TLS certifikáty. Ak niekto použije identitu na podpis, zanechá verejne dohľadateľnú stopu.

3. Cosign — CLI a knižnica

Klientský nástroj, ktorý orchestuje celé signing/verify kroky: získa OIDC token, požiada Fulcio o certifikát, podpíše artefakt, zapíše do Rekoru a nahrá podpis ako OCI artefakt vedľa imagu v registry.

Verejná inštancia Sigstore (Fulcio + Rekor) je prevádzkovaná OpenSSF zadarmo. Firmy môžu prevádzkovať vlastnú (napr. cez sigstore/scaffolding).


Keyless signing — ako to funguje

┌─────────┐                   ┌─────────┐
│ Cosign  │─── OIDC login ───►│ OIDC    │
│ (local) │                   │ Provider│
└────┬────┘                   │ (GitHub)│
     │                        └────┬────┘
     │    ◄──── token ─────────────┘
     │
     │ token + pubkey
     ▼
┌─────────┐
│ Fulcio  │──► certifikát (10 min)
└────┬────┘
     │
     ▼
┌─────────┐
│ Rekor   │◄── zapis hash + podpis
└────┬────┘
     │
     ▼
┌─────────┐
│ OCI     │◄── signature artifact pripojeny k imagu
│ Registry│
└─────────┘

Z pohľadu developera je to jedna komanda:

cosign sign ghcr.io/myorg/myapp:v1.2.3

Cosign otvorí browser, prihlási sa cez GitHub, získa token, zavolá Fulcio, podpíše, zapíše do Rekoru. Hotovo.


Praktický príklad 1 — signing a verify lokálne

# Nainštaluj cosign
curl -LO https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign-linux-amd64 && sudo mv cosign-linux-amd64 /usr/local/bin/cosign

# Podpíš image (interaktívne OIDC)
cosign sign ghcr.io/myorg/myapp:v1.2.3

# Overenie
cosign verify ghcr.io/myorg/myapp:v1.2.3 \
  --certificate-identity=user@example.com \
  --certificate-oidc-issuer=https://github.com/login/oauth

cosign verify skontroluje:

  1. Podpis matchuje digest imagu.
  2. Certifikát bol vystavený Fulciom a obsahuje očakávanú identitu.
  3. Záznam v Rekor logu existuje a tagovanie časom je konzistentné.

Ak overenie zlyhá, exit code != 0. Vhodné na CI gate alebo admission controller v Kubernetes.


Praktický príklad 2 — GitHub Actions

V GH Actions netreba žiadny interaktívny login — OIDC token sa generuje automaticky z workflow:

name: Build and Sign

on:
  push:
    tags: ["v*"]

permissions:
  contents: read
  id-token: write     # povoli OIDC
  packages: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        id: build
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}

      - name: Install Cosign
        uses: sigstore/cosign-installer@v3

      - name: Sign image (keyless)
        run: |
          cosign sign --yes \
            ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}

Identita v certifikáte bude niečo ako:

https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/tags/v1.2.3

Toto je cryptographically verifiable provenance — ktorá konkrétna verzia ktorého workflow v ktorom repe podpísala tento image. Pri verifikácii to viete presne skontrolovať.


Attestations — SBOM a SLSA provenance

Cosign dokáže pripojiť nielen podpis, ale aj attestácie — podpísané metadáta o tom, ako bol image vyrobený:

# SBOM attestation (CycloneDX)
cosign attest --yes \
  --predicate sbom.cdx.json \
  --type cyclonedx \
  ghcr.io/myorg/myapp:v1.2.3

# SLSA provenance
cosign attest --yes \
  --predicate provenance.json \
  --type slsaprovenance \
  ghcr.io/myorg/myapp:v1.2.3

Pri verifikácii:

cosign verify-attestation \
  --type cyclonedx \
  --certificate-identity-regexp='https://github.com/myorg/.*' \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  ghcr.io/myorg/myapp:v1.2.3

Dostanete späť podpísaný SBOM. Tým sa odomkýnajú policy otázky ako: "Nasadím iba image, ktorý má SBOM, kde žiadna komponenta nemá CVE nad severity 8.5". SBOM sa nedá ex-post podhodiť.

Detailnejší pohľad na supply chain security a SLSA nájdete v článku Supply Chain Security.


Policy enforcement — admission controllers

Samotný podpis je zbytočný, ak ho nikto pri deployi neoveruje. V Kubernetes sa na to používajú admission controllery:

1. Kyverno + Cosign

apiVersion: kyverno.io/v2beta1
kind: ClusterPolicy
metadata:
  name: verify-signed-images
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-signature
      match:
        any:
          - resources:
              kinds:
                - Pod
      verifyImages:
        - imageReferences:
            - "ghcr.io/myorg/*"
          attestors:
            - entries:
                - keyless:
                    subjectRegExp: "https://github.com/myorg/.*"
                    issuer: https://token.actions.githubusercontent.com

Každý Pod v klastri musí používať image, ktorý má valid Sigstore podpis s identitou z myorg GitHub Actions. Všetky ostatné images sú admission-rejected.

2. Sigstore Policy Controller

Natívny controller od Sigstore, jednoduchšia alternatíva:

apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
  name: myorg-keyless
spec:
  images:
    - glob: "ghcr.io/myorg/**"
  authorities:
    - keyless:
        identities:
          - issuer: https://token.actions.githubusercontent.com
            subjectRegExp: "https://github.com/myorg/.*"

3. OPA / Gatekeeper

Rovnaký princíp, cez OPA rules. Viac konfigurácie, väčšia flexibilita.


Cosign vs klasické GPG signing

Aspekt GPG signing Cosign keyless
Key management Dlhodobé kľúče, treba rotovať Žiadne — krátkodobé certs
CI integration Treba injektovať privátny kľúč Natívne cez OIDC
Identity Kľúč = identita (slabé) OIDC provider + Rekor log
Transparency Žiadna Verejný Rekor log
Revocation Komplikované Nepotrebné (krátke certs)
Verification gpg --verify cosign verify + identity check

Pre moderné CI/CD je Cosign dramaticky jednoduchší a bezpečnejší.


Produkčné tipy

  • Nie každý image treba podpisovať — začnite s production imagmi a postupne pridávajte.
  • Monitorujte Rekor log — nástroj rekor-cli search nájde všetky podpisy vytvorené vašou identitou. Užitočné na detekciu zneužitia.
  • Verify pri deploy, nie pri pull — registry vám tag prepíše, podpis to neochráni. Deploy gate je správne miesto.
  • Identity pinning — neustále používajte --certificate-identity a --certificate-oidc-issuer. Bez nich je cosign verify takmer useless.
  • Self-hosted Sigstore — veľké firmy (Google, GitHub, Chainguard) si prevádzkujú vlastné inštancie Fulcio + Rekor pre compliance.

Zhrnutie

Sigstore a cosign posunuli signing z "something only paranoid infra teams do" do "default step v každom release workflow". Inštalácia trvá minúty, integrácia s GitHub Actions je triviálna, policy enforcement cez Kyverno alebo Sigstore Policy Controller uzatvára krúh medzi "podpis vznikol" a "podpis sa overí pred deployom".

Ak dnes staviate image pipeline a chcete vedieť odpovedať na otázku "kto a čím vyrobil tento konkrétny container image?", Sigstore je jediná rozumná odpoveď.

Odkazy