Nach SolarWinds, Codecov und log4shell wurde klar, dass die Prüfung des Artefakts am Ende der Pipeline kein ausreichender Schutz mehr ist. Ein SBOM zeigt, was im Image steckt. Eine Cosign-Signatur beweist, dass der Unterzeichner ein gültiges OIDC-Token hatte. Zwischen beiden liegt die Lücke, durch die Supply-Chain-Angriffe schlüpfen: ein vertauschter Builder, ein manipulierter Workflow, der falsche Commit. SLSA schließt diese Lücke durch Provenance — eine maschinell prüfbare Beschreibung, wie genau das Artefakt gebaut wurde.
Was jedes Level verspricht
SLSA v1.0 (gepflegt von der OpenSSF) definiert vier Stufen. L0 bedeutet keine Garantien — der Default. L1 verlangt einen dokumentierten Build-Prozess und generierte Provenance, auch ohne Signatur: genug, um ehrliche Fehler und schnelle Vertauschungen zu fangen. L2 hebt die Latte auf einen gehosteten, isolierten Builder mit signierter Provenance — Tampering zwischen Build und Publish wird ausgeschlossen. L3 ist ein gehärteter ephemerer Builder mit starker Provenance: das Bedrohungsmodell umfasst nun einen kompromittierten Builder und einen Insider mit CI-Zugriff.
L3 ist auf GitHub Actions nahezu out-of-the-box verfügbar — über slsa-framework/slsa-github-generator (reusable Workflow). GitLab bleibt bei partiellem L2. Ein selbst gehosteter Builder mit der Aufschrift «bei uns läuft L2» ohne tatsächliche Isolation ist die häufigste Lüge der Branche, und SLSA weigert sich, sie zu validieren.
Was in Provenance steht
Provenance ist ein in-toto Statement mit Predikat slsa.dev/provenance/v1. Drinnen: subject — das Image und sein Digest; buildDefinition.externalParameters — Repository, Ref, Workflow-Pfad; buildDefinition.resolvedDependencies — der Git-Commit; runDetails.builder.id — der Builder-Identifier; runDetails.metadata — Invocation-ID und Zeitstempel.
Diese Felder beantworten vier Fragen: was gebaut wurde, woher, womit und wann. Eine Signatur ohne Provenance bestätigt nur «jemand mit einem gültigen Token hat etwas signiert». Provenance ohne Signatur ist JSON ohne Beweis. Sie wirken nur zusammen.
Sigstore: Signieren ohne langlebige Schlüssel
Cosign im Keyless-Modus (GA seit 2.0+) löst das Key-Management-Problem. Identität kommt aus OIDC: GitHub Actions, Google, Ihr Keycloak in Air-Gapped-Umgebungen. Fulcio stellt ein Zertifikat aus, das 10 Minuten lebt, Cosign signiert damit das Artefakt, und der Eintrag landet in Rekor — einem öffentlichen Append-only-Transparency-Log.
Eine Syntax deckt jedes OCI-Artefakt ab:
cosign sign --yes ghcr.io/org/payments-api:v1.2.3
cosign attest --predicate provenance.json --type slsaprovenance ghcr.io/org/payments-api:v1.2.3
cosign attest --predicate sbom.cdx.json --type cyclonedx ghcr.io/org/payments-api:v1.2.3
Mit Helm 4 und OCI als primärem Distributionskanal gilt dasselbe cosign sign für Chart-Artefakte. Ein Transparency-Log, ein Verifikationsmodell, eine Admission-Regel.
Den Loop in der Admission schließen
Signieren ohne zu verifizieren ist Security Theater — in jedem SLSA-Dokument erwähnt und regelmäßig in der Produktion anzutreffen. Verifikation gehört in den Admission Controller; sonst rutscht jedes Image an der Tür vorbei in den Cluster.
Eine Kyverno ClusterPolicy mit verifyImages akzeptiert einen Keyless-Attestor: ein Regex auf das Subject (Workflow-Pfad), den OIDC-Issuer, die Rekor-URL. Ein Pod, dessen Image die Prüfung nicht besteht, wird nicht erstellt. Auf der CLI-Seite leistet dasselbe slsa-verifier:
slsa-verifier verify-image ghcr.io/org/payments-api:v1.2.3 \
--source-uri github.com/org/payments-api \
--source-tag v1.2.3 \
--builder-id 'https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_container_slsa3.yml@refs/tags/v2.0.0'
Lässt man --builder-id weg, bricht die Kette: die Signatur ist gültig, aber wer wo gebaut hat — unbekannt.
Anti-Patterns, die häufiger auftreten als sie sollten
Ein gemeinsamer Schlüssel für dev/staging/prod löscht die Blast-Radius-Isolation. Eine hartkodierte Signierer-E-Mail in der Policy skaliert nicht auf ein Team. latest in verifyImages.imageReferences zeigt auf ein mutables Ziel — die Signatur wird bedeutungslos. Provenance mit leeren internalParameters verliert den Invocation-Kontext. Deaktiviertes Rekor (--rekor-url="") entfernt die Detection: ein gestohlenes OIDC-Token rutscht unbemerkt durch.
Die K8s-native Alternative
Tekton Chains ist ein Observer für TaskRun: es generiert SLSA Provenance automatisch, signiert über Sigstore Keyless, pusht die Attestation neben das Image in OCI und den Eintrag nach Rekor. Ergebnis: SLSA L3, ohne Kubernetes zu verlassen. Der Preis ist Tekton selbst — eine Pipeline-Engine mit eigenem Set an CRDs (Tasks, Pipelines, Triggers) und nicht-trivialem Operations-Overhead. Passt zu Platform-Engineering-Teams, die sich bereits auf K8s-first CI festgelegt haben.
Drei Antworten auf drei Fragen
Ein SBOM beantwortet «was steckt im Artefakt». Provenance — «wie wurde es gebaut». Eine Cosign-Signatur — «wer steht dafür gerade». Ein Supply-Chain-Angriff schlägt eine dieser drei Antworten heraus; SLSA ist so entworfen, dass der Admission Controller alle drei stellen darf, bevor ein Pod erstellt wird.