Cosign és Sigstore konténerkép-aláírás 2026: keyless signing, SLSA és Kyverno

Így írj alá konténerképeket Cosign és Sigstore használatával keyless módban 2026-ban. Végigvezetlek a GitHub Actions integráción, a Kyverno admission policy-n, az SLSA provenance-en és az SBOM tanúsításon, éles CI példákkal.

Frissítve: 2026. augusztus 17.

A Cosign konténerkép-aláírás egy nyílt forráskódú megoldás: a Sigstore infrastruktúrát használva a Linux CI/CD-ben épített képeket kriptográfiailag aláírja, majd a signaturet közvetlenül az OCI regiszterbe pusholja. Így a Kubernetes admission controller (pl. Kyverno) telepítéskor egyszerűen megtagadhatja az aláíratlan vagy módosított képek futtatását. 2026-ban a keyless signing az OIDC identitásokkal (GitHub Actions, GitLab CI) az iparági alapértelmezés, az SLSA Level 3 provenance-szel kiegészítve pedig teljes ellátási lánc bizalmi láncot ad.

  • A Cosign 2.5+ a Sigstore Fulcio (rövid életű X.509 tanúsítványok) és a Rekor (tamper-proof transparency log) segítségével teljes keyless workflow-t kínál. Vagyis nincs többé titkosított magánkulcs a CI secret storage-ban.
  • Az ellátási lánc elleni támadások 2024 óta több mint 300%-kal nőttek; az xz-utils backdoor (CVE-2024-3094) megmutatta, hogy a build pipeline maga a támadási felület, nem csak az alkalmazáskód.
  • Az SLSA Level 3 gyártási környezetekben elvárt: pinned hash-ekkel dolgozó, elszigetelt, tamper-resistant build rendszerre és aláírt provenance attestation-ra épül.
  • A Syft által generált SBOM in-toto attestation formátumban Cosign-nal írható alá, és Trivy vagy Grype scannerekkel validálható a Kyverno verifyImages szabályában.
  • A Kyverno ClusterPolicy Enforce módban blokkolja az aláíratlan podokat. Audit módban érdemes kezdeni, majd fokozatosan élesíteni, így elkerülhető a production leállás.
  • Mindig a sha256 digestet írjuk alá, sose a mutálható taget. A tag újraírható, a digest nem.

Mi az a Sigstore és a Cosign?

A Sigstore a Linux Foundation és az OpenSSF által gondozott projekt, aminek célja a szoftver ellátási lánc kriptográfiai aláírását ingyenessé és üzemeltetés-mentesé tenni. Három komponensre épül: a Cosign a CLI eszköz, ami OCI-artifactokat ír alá és ellenőriz; a Fulcio egy nyilvános, ingyenes tanúsítvány-hatóság, amely rövid életű (10 perces) X.509 tanúsítványokat állít ki OIDC identitás alapján; a Rekor pedig egy nyilvános, tamper-proof transparency log, ami minden aláírási eseményt eltárol.

A Cosign nem külön aláírás-szervert használ (mint a régi Notary v1), hanem a signaturet közvetlenül az OCI regiszterbe (Harbor, GHCR, ECR, Quay, Artifact Registry) tolja fel .sig tag-gel, a kép digest-jéhez láncolva. Ez azt jelenti: ha van írási jogod a regiszterbe, tudsz aláírni, nincs szükség külön infrastruktúrára. A DevSecOps pipeline felől nézve ez lényegesen egyszerűbb, mint a GPG-alapú Docker Content Trust volt.

A Cosign 2.x támogatja a kulcsalapú aláírást, a keyless OIDC flow-t, a hardware token integrációt (YubiKey PIV) és a cloud KMS-eket is (AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault). A 2026-os alapértelmezett workflow a keyless a legtöbb managed CI-ben, mert ezzel eltűnik a titkos kulcs a secret storage-ból.

# Cosign 2.5+ telepítése Linux szerverre vagy CI runnerre
COSIGN_VERSION="v2.5.3"
curl -fsSLo /usr/local/bin/cosign \
  "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-amd64"
chmod +x /usr/local/bin/cosign
cosign version

Miért van szükség konténerkép-aláírásra 2026-ban?

Az elmúlt 24 hónapban az ellátási láncot érő támadások exponenciálisan nőttek. A 2024-es xz-utils backdoor (CVE-2024-3094) majdnem minden Linux disztribúció SSH daemonjait kompromittálta egy több éves social engineering kampány révén, és 2025-2026-ban további kompromittált npm, PyPI és Go modulokat találtak. Közülük több olyat, amit direkt CI runnereken való tokenlopásra írtak. A védekezés kulcsa egyszerű: ne bízz semmiben, amit nem tudsz kriptográfiailag visszavezetni egy ismert build eseményhez.

A konténerkép-aláírás három konkrét problémát old meg. Először: provenance, vagyis bizonyítékot ad arra, hogy a kép valóban a te CI/CD rendszeredből származik és nem egy támadó által publikált, azonos nevű képből. Másodszor: integrity. Ha valaki a regiszterben módosítja a képet aláírás után, a digest változik, a signature pedig érvénytelenné válik. Harmadszor: policy enforcement. A Kubernetes admission controller megtagadhatja az aláíratlan képek futtatását, így egyetlen kompromittált fejlesztői gép sem tudja telepíteni a saját képét production-ba.

Honnan tudom? Egy fintech ügyfélnél pontosan ezt a pipeline-t építettem fel tavaly: minden build hash-pinned base image-ből indul, Syft-tel SBOM készül, Trivy-vel futásidejű sebezhetőségvizsgálat zajlik, Cosign aláírja a képet és az attestation-t, majd a Kyverno elutasítja azt, ami nem felel meg. Volt egyetlen support ticket, ahol az „éles rendszer állt le” panasz utólag pont a fenti pipeline szükségességét igazolta vissza.

# CI-ready: minimalis policy audit modban - egy hetes megfigyelesre
cat <<'EOF' | kubectl apply -f -
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: audit-unsigned-images
spec:
  validationFailureAction: Audit
  rules:
    - name: warn-unsigned
      match:
        any:
          - resources: { kinds: [Pod] }
      verifyImages:
        - imageReferences: ["ghcr.io/myorg/*"]
          mutateDigest: true
          required: false
EOF

Hogyan írjunk alá konténerképet Cosign-nal?

Az első aláírás mindig kulcsalapú legyen, hogy megértsd, mi történik. Utána már nyugodtan válts keyless-re. A cosign generate-key-pair létrehoz egy privát/publikus kulcspárt, ahol a privát kulcsot egy jelszó védi (a jelszó megadható a COSIGN_PASSWORD környezeti változóban, hogy CI-ben ne interaktív módon kelljen futtatni). Ezután a cosign sign a kép digest-jét írja alá, nem a taget, és a signaturet image-digest.sig néven pusholja a regiszterbe.

Ez a részlet kritikus: mindig a digestet írd alá, ne a taget. A tag mutálható. A latest tag ma egy kép layer-halmazra mutathat, holnap egy másikra. A digest (sha256:...) a manifest kriptográfiai hash-e, definíció szerint immutabilis. Ha taget írsz alá, hamis biztonságérzetet adsz; ha digestet, tényleges garanciát kapsz.

Verifikációnál kétféle módon dolgozhatsz: fejlesztői gépen a cosign verify paranccsal (mielőtt lokálisan futtatnád a képet), vagy fürtszinten Kyverno-val (lásd lentebb). A verifikációnak mindig meg kell hogy adja a Rekor URL-t is, mert így ellenőrizzük, hogy a signature bekerült-e a nyilvános transparency logba.

# Kulcspar generalasa es elso alairas
export COSIGN_PASSWORD="$(openssl rand -base64 32)"
cosign generate-key-pair            # cosign.key + cosign.pub keletkezik

IMAGE="ghcr.io/myorg/api:v2.4.1"
docker push "${IMAGE}"

# A digest kinyerese (SOHA ne a taget irjuk ala)
DIGEST=$(cosign triangulate --type=digest "${IMAGE}")
cosign sign --key cosign.key --yes "${DIGEST}"

# Ellenorzes fejlesztoi gepen a publikus kulccsal
cosign verify --key cosign.pub "${DIGEST}" \
  --rekor-url https://rekor.sigstore.dev \
  --output json | jq '.[0].critical'

Keyless és kulcsalapú aláírás összehasonlítása

A választás nem stílus kérdése, konkrét trade-off-jai vannak. A keyless workflow (Fulcio + OIDC) törli a hosszú életű titkos kulcsot a fenyegetési modellből, ami messze a legnagyobb footgun a Docker Content Trust és PGP-alapú rendszerek esetén. Cserébe a signer identitása bekerül a publikus Rekor logba (általában e-mail vagy CI workflow URL formájában), tehát a keyless nem „anonim”, hanem nyilvánosan auditálható. Enterprise környezetben ez feature, nem bug.

A kulcsalapú workflow-t akkor válaszd, ha air-gapped rendszerben vagy, vagy ha nem szeretnéd, hogy fejlesztőid e-mail címei a nyilvános Rekor logba kerüljenek. Ilyenkor HSM vagy cloud KMS backing kötelező. Sose tárold a magánkulcsot fájlként a CI secret store-ban plaintextben. A GitHub secrets és a GitLab masked variables jó indulási pont, de igazi biztonságot csak a KMS ad.

SzempontKeyless (Fulcio + OIDC)Kulcsalapú (Cosign key / KMS)
KulcskezelésNincs hosszú életű kulcs, 10 perces ephemeral tanúsítványLong-lived magánkulcs, rotációt igényel
IdentitásOIDC (GitHub Actions, GitLab CI, Google, Buildkite)A kulcs birtokosa
AuditálhatóságRekor logban nyilvános aláíró identitásCsak a saját logolásod
Air-gap támogatásSigstore private mode szükséges (Rekor + Fulcio self-hosted)Out-of-the-box működik
CI beállítási komplexitásAlacsony (OIDC token automatikusan)Közepes (secret management, jelszó, KMS auth)
Ajánlott 2026-banManaged CI (GitHub/GitLab SaaS), Kubernetes productionAir-gapped, szabályozott iparágak (banki, védelmi)
# CI-ready: keyless signing GitHub Actions OIDC tokennel
# Nincs COSIGN_PASSWORD, nincs cosign.key secret - csak id-token permission
export COSIGN_EXPERIMENTAL=1
cosign sign --yes \
  ghcr.io/myorg/api@sha256:2f7c3b...   # digest, nem tag

Cosign integrálása GitHub Actions és GitLab CI-ba

A GitHub Actions esetén a keyless flow zökkenőmentes: a workflow-nak id-token: write jogosultságot kell adnunk, és a Cosign automatikusan lekéri az OIDC tokent az ACTIONS_ID_TOKEN_REQUEST_URL-ról. A signature akkor a workflow identity-t hordozza, például https://github.com/myorg/api/.github/workflows/release.yaml@refs/tags/v2.4.1. Ez az érték válik a Kyverno policy subject mezőjévé, tehát csak a te release workflow-d által aláírt képek fognak átjutni.

GitLab CI-ban a beállítás hasonló, csak itt a Cosign a CI_JOB_JWT_V2 tokent használja OIDC szubjektumként. GitLab 16.0+ óta ez az alapértelmezés, és az iss claim a GitLab instance URL-jét tartalmazza. A Kyverno keyless.issuer mezőjében ezt kell megadnunk, nem a GitHub-ét.

Praktikus tapasztalat: minden CI pipeline-ba tegyél egy signing job-ot, ami elkülönül a build jobtól, és csak akkor fut, ha a build sikeres és a Trivy scan tiszta. Így egyetlen scanner-hiba egy CVE-re nem fog aláíratni egy sebezhető képet. A signing job outputja lehet egy artifact, ami tartalmazza a digest-et és a Rekor UUID-t. Ez auditra remekül jön.

# CI-ready: GitHub Actions workflow keyless signing-gel
name: Build, Sign and Attest
on: { push: { tags: ["v*"] } }
permissions: { contents: read, packages: write, id-token: write }

jobs:
  build-sign:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
      - uses: sigstore/[email protected]
        with: { cosign-release: 'v2.5.3' }
      - 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: Sign the digest (keyless)
        env: { COSIGN_EXPERIMENTAL: "1" }
        run: |
          cosign sign --yes \
            ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}

Aláírás-érvényesítés Kyverno-val Kubernetesben

Az aláírás önmagában nem megoldás. Ellenőrzés nélkül csak egy metadata bejegyzés a regiszterben. A production védelmét a Kubernetes admission control adja: a Kyverno (vagy alternatívaként a Sigstore Policy Controller, illetve az OPA Gatekeeper) minden pod létrehozásnál lefuttatja a verifyImages szabályt, és ha a signature nem felel meg, elutasítja a podot. Kritikus, hogy először Audit módban vezessük be, majd 5-7 nap tiszta futás után váltsunk Enforce-ra. Különben egy Kyverno hiba miatt leáll a cluster deployment folyamata.

A keyless verifikáció policy-ben két adatot igényel: az issuer-t (általában a CI provider OIDC URL-je) és a subject pattern-t (a workflow útvonala). Ezen felül a rekor.url alapértelmezetten a nyilvános Sigstore Rekor, de private deployment esetén saját instance is megadható. Fontos: az imageReferences lista pontos legyen. Ha wildcard-dal engedélyezel bármit, a policy bypass-olható egy tetszőleges regiszter-URL-lel.

A Kyverno 1.13+ ImageValidatingPolicy CRD-t vezetett be, ami rugalmasabb a régi ClusterPolicy-nál, és jobban skálázódik. Több ezer pod/perc admission rate-en is stabil. Egy szuper hasznos beállítás a mutateDigest: true, ami automatikusan lecseréli a tag-alapú image referenciákat digest-alapúra a manifestben. Ez a futásidejű konténer-manipuláció ellen véd.

# CI-ready: Kyverno ClusterPolicy keyless GitHub Actions verifikaciohoz
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-github-signed-images
  annotations:
    policies.kyverno.io/severity: high
spec:
  validationFailureAction: Enforce   # start with Audit, then Enforce
  webhookTimeoutSeconds: 30
  rules:
    - name: verify-keyless-github
      match:
        any:
          - resources:
              kinds: [Pod]
              namespaces: [production, staging]
      verifyImages:
        - imageReferences:
            - "ghcr.io/myorg/*"
          mutateDigest: true
          required: true
          attestors:
            - count: 1
              entries:
                - keyless:
                    subject: "https://github.com/myorg/*/.github/workflows/*@refs/tags/*"
                    issuer: "https://token.actions.githubusercontent.com"
                    rekor:
                      url: https://rekor.sigstore.dev

SLSA provenance és SBOM tanúsítás Syft-tel

Az SLSA (Supply-chain Levels for Software Artifacts) egy Google által kezdeményezett és az OpenSSF által gondozott keretrendszer, amely azt írja le, hogyan épült a szoftver. Nem azt, hogy mit tartalmaz (az utóbbi az SBOM). Az SLSA négy szintet definiál: Level 1 dokumentált build; Level 2 aláírt provenance; Level 3 izolált, hardened build platform pinned dependencies-szel; Level 4 kétszemélyes review minden változáshoz. 2026-ban a production ajánlás minimum SLSA Level 3.

Az SBOM (Software Bill of Materials) az „összetevők listája”: minden csomag, könyvtár, verzió, licenc. A leggyakoribb 2026-os gyakorlat a Syft által generált SPDX 2.3 vagy CycloneDX 1.6 formátumú SBOM, amit in-toto attestation formátumba csomagolunk és Cosign-nal aláírunk. Ez a tanúsítvány a regiszterben tárolódik a képhez kötve, és a Trivy vagy Grype scannerekkel offline lekérdezhető. Nem kell újra downloadolni és scannelni a képet.

Egy pragmatikus vélemény (ezt egyébként a legutóbbi projekten a saját bőrömön tanultam meg): 2026-ban az SBOM önmagában már nem elég. Az élő SBOM (VEX, azaz Vulnerability Exploitability eXchange adatokkal enrichelve) sokkal értékesebb. Nemcsak azt mondja meg, mi van a képben, hanem azt is, hogy melyik komponens sebezhető és ténylegesen kihasználható-e a te futási környezetedben. Egy zajos Trivy findingot nyugodtan elutasíthatsz, ha VEX-tel dokumentálod, hogy a sebezhető kódútra nincs runtime elérés. Ne blokkoltasd magad éjfélkor egy CVE-vel, ami sose fog aktiválódni.

# CI-ready: SBOM generalas Syft-tel + in-toto attestation alairas Cosign-nal
IMAGE="ghcr.io/myorg/api@sha256:2f7c3b..."
SBOM_FORMAT="cyclonedx-json"

# 1) SBOM generalas
syft "${IMAGE}" -o "${SBOM_FORMAT}" > sbom.cdx.json

# 2) Predikatum in-toto attestation formatumba csomagolas es alairas
cosign attest --yes \
  --predicate sbom.cdx.json \
  --type cyclonedx \
  "${IMAGE}"

# 3) SLSA provenance ellenorzes keyless modban
cosign verify-attestation --type slsaprovenance \
  --certificate-identity-regexp "https://github.com/myorg/.*" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  "${IMAGE}" | jq '.payload | @base64d | fromjson | .predicate'

Gyakori Cosign hibák és megoldások

A Error: no matching signatures a leggyakoribb probléma. Három oka lehet. (1) A signature nincs push-olva a regiszterbe. Ellenőrizd cosign tree ${IMAGE}-gal, hogy látszik-e a .sig tag. (2) A verifikáció során más digestet használsz, mint amit aláírtál. Mindig a fully-qualified digestet add meg, ne a taget. (3) A Kyverno policy subject pattern-je nem stimmel a Rekor entry-vel. A cosign verify --output json parancs kilistázza a subject-et, hasonlítsd össze a policy pattern-nel. Én is percekig kerestem egyszer, hogy miért utasít el a policy egy szerintem tökéletesen aláírt képet, aztán kiderült, hogy a workflow útvonala pár karakterrel eltért.

Az x509: certificate signed by unknown authority vagy failed to verify certificate hibák self-hosted Fulcio esetén jelennek meg. Ellenőrizd a SIGSTORE_ROOT_FILE és SIGSTORE_CT_LOG_PUBLIC_KEY_FILE környezeti változókat. A private Sigstore deploymentnek saját root of trust bundle-je van (trust-bundle.json), amit minden CI runnernek és Kubernetes csomópontnak látnia kell.

A rate limit exceeded from Rekor hiba nagy volumenű CI-ban jön elő. A public Rekor 100 req/perc/IP limitet ad. Megoldás: self-hosted Rekor, vagy a --tlog-upload=false flag-gel átmeneti offline aláírás, majd batch upload. De ne felejtsd el, hogy tlog nélkül a keyless verifikáció szigorúbb módban visszautasítja a signaturet.

# CI-ready: gyors diagnosztika, ha egy alairas nem verifikalodik
IMAGE="ghcr.io/myorg/api@sha256:2f7c3b..."
cosign tree "${IMAGE}"                              # signatures, attestations
cosign verify --key cosign.pub "${IMAGE}" -o json \
  | jq '.[0] | {subject: .optional.Subject, issuer: .optional.Issuer, digest: .critical.image."docker-manifest-digest"}'
rekor-cli search --sha "$(echo ${IMAGE} | cut -d@ -f2)"

Gyakran ismételt kérdések

Ingyenes-e a Sigstore és a Cosign használata production környezetben?

Igen, teljesen ingyenes. A Cosign CLI Apache 2.0 licenc alatti, és a public Sigstore infrastruktúra (Fulcio, Rekor) is ingyenes non-commercial és commercial use-ra egyaránt. Nagy volumenű CI-ban self-hosted deployment ajánlott a rate limit elkerülésére, ehhez a sigstore/scaffolding Helm chart használható.

Hogyan írjuk alá a Cosign-nal a taggelt képeket, ha a tag változhat?

A gyakorlatban sose a taget írjuk alá, hanem a képhez tartozó sha256 digestet. A cosign triangulate --type=digest ${IMAGE}:${TAG} visszaadja a digestet, amit az aláírási parancsba adunk. A digest immutabilis, tehát ha a tag változik, az új képet külön kell aláírni.

A keyless signing feltárja-e a fejlesztők e-mail címét publikusan?

A public Sigstore Rekor logba bekerül az OIDC identity claim (e-mail cím vagy CI workflow URL). Enterprise környezetben ez GDPR-alapon aggodalmat kelthet, ezért CI-ban használjunk workflow identity-t (nem személyes accountot) és privát Sigstore instance-ot, ha az e-mail cím érzékeny.

Cosign-nal aláírt képeket lehet-e Docker Hub-ra pusholni?

Igen. A Cosign a signaturet OCI 1.1+ szabvány szerint tárolja, így minden modern regiszter (Docker Hub, GHCR, ECR, Quay, Artifact Registry, Harbor 2.7+) natívan támogatja. A Docker Hub kompatibilis az OCI 1.1-gyel 2024 óta.

Mi a különbség a Cosign signature és a Cosign attestation között?

A signature csak azt bizonyítja, hogy a kép egy adott identitás által lett aláírva. Az attestation ezen felül strukturált metaadatot is hordoz (in-toto formátumban), például SBOM-ot, SLSA provenance-t vagy vulnerability scan eredményt. Az attestation is aláírt, de több információt hordoz, mint egy tiszta signature.

Blokkolja-e a Kyverno a Wazuh vagy monitoring image-eket, ha nincsenek aláírva?

Csak akkor, ha a match szabály illeszkedik rájuk. Legjobb gyakorlat: a kube-system és a monitoring namespace-eket kivenni a match-ből (vagy egy külön allow policyt írni), amíg a harmadik féltől érkező képek aláírása is bevezetésre kerül. Így nem kockáztatod a cluster monitoring leállását.

Raj Patel
A Szerzőről Raj Patel

DevSecOps engineer who's gradually turning every CI pipeline he sees into a security-checking machine.