End-to-End Supply Chain Security
Software-Integrität ist kein «Nice-to-have» mehr, sondern wird durch Standards wie PCI-DSS v4.0 und ISO 27001 zunehmend zur Pflicht. Doch während Cloud-Giganten Signatur-Lösungen von Haus aus mitliefern, stehen Teams mit Inhouse-Infrastrukturen oft vor einer Hürde: Wie sichert man die eigene Build-Pipeline lückenlos ab? Wir bei Puzzle haben den Praxistest gemacht und zeigen, wie wir mit Sigstore und GitLab CI Container-Images «keyless» signieren – vom ersten Build in der Fabrik bis zur sicheren Ausführung in OpenShift.
Das Sigstore-Projekt
Das Sigstore-Projekt wurde ins Leben gerufen, um Software-Entwickler:innen eine einfache Möglichkeit zu bieten, ihre Artefakte mit ihrer Identität zu signieren. So können Konsument:innen später prüfen, ob die Software wirklich von der erwarteten Quelle stammt. Das Konzept beruht vereinfacht darauf, dass sich Entwickler:innen über ihren Identity Provider authentifizieren, um anschliessend ein kurzlebiges Zertifikat zum Signieren zu erhalten.
Die Analogie: Der Bote und das Paket
Um das Ganze verständlicher zu machen, nutzen wir die Analogie eines Boten und eines Pakets.
Unsere GitLab-Fabrik hat ein neues Paket hergestellt, das nun vom Boten in den Hafen gebracht werden soll. Damit der Bote das überwachte Firmengelände verlassen kann, benötigt er einen Passierschein. Diesen beantragt er bei der Behörde. Dazu weist sich der Bote mit seinem Firmenausweis aus und deklariert den Inhalt des Pakets. Die Behörde versichert sich zuerst bei der Firma, ob der Bote wirklich dort arbeitet. Auch der Bote kann sich rückversichern und prüfen, ob die Behörde wirklich legitim ist. Dazu kann er die Regierung anrufen, welche ihm die Autorität der Behörde bestätigt.
Sobald die Identität geklärt ist, stellt die Behörde einen einmaligen Passierschein aus. Dieser ist nur für zehn Minuten gültig und enthält neben der Identität des Boten auch die Deklaration des Pakets. Er ist nicht auf andere Personen oder Pakete übertragbar.
Beim Verlassen des Geländes scannt der Bote den Schein. Die Daten (inklusive Zeitstempel) werden automatisch an das zentrale Versandsystem gesendet. Danach bringt der Bote das Paket in den sicheren Hafen. Der Passierschein wird in einem öffentlichen Register gespeichert. Jede Person kann dort einsehen, zu welcher Zeit welcher Bote mit welchem Paket das Gelände verlassen hat.
Anschliessend wird das Paket an andere Fabriken verteilt. Im Video oben sehen wir die Lieferung an eine Container-Plattform. Sobald das Paket entladen wird, prüft es der Sicherheitsdienst der Plattform. Er scannt den Barcode, um die Herkunft zu klären. Da der Sicherheitsdienst einem Etikett nicht blind vertraut, ruft er beim zentralen Versandsystem an und lässt sich bestätigen, dass die Angaben korrekt sind. Erst dann darf das Paket auf die Plattform. Auch hier kann sich der Sicherheitsdienst rückversichern und zuerst die Regierung anrufen, um sicherzustellen, dass das zentrale Versandsystem vertrauenswürdig ist, und er nicht hinters Licht geführt wird.
Vorteile von Sigstore
Der Sigstore-Ansatz bietet deutliche Vorteile gegenüber dem klassischen Signieren mit statischen Private Keys:
| Traditionell | Sigstore |
|---|---|
| Ein privater Schlüssel ist meist über Monate oder Jahre gültig und muss extrem sicher aufbewahrt werden. Ein Verlust ist fatal. | Sigstore generiert nur temporäre Schlüssel, die nach 10 Minuten unbrauchbar werden. |
| Schlüsselrotation ist komplex. | Keine manuelle Rotation erforderlich. Jeder Vorgang nutzt einen Einmalschlüssel. |
| Der Widerruf ist kompliziert (CRLs nötig). | Kein Widerruf nötig, da die Schlüssel sofort ablaufen. |
| Vertrauen basiert rein auf dem Schlüssel. | Zusätzliche Sicherheit durch Identitätsnachweis und öffentliches Log. |
Signierung in GitLab CI

Der Aufbau unseres „Signing Stacks“ besteht im Wesentlichen aus folgenden Teilen:
- Sigstore-Komponenten:
- Fulcio: Die „Behörde“ für die Passierscheine.
- Cosign: Das Werkzeug des Boten (Client CLI).
- Rekor: Die zentrale Sammelstelle (Log) aller Passierscheine.
- TUF: Die Regierung
- GitLab CI (Self-hosted):
- Agiert als OIDC-Provider (das HR-Büro der GitLab-Fabrik).
- Die Pipeline führt den Job aus und agiert als der Bote.
- Das OIDC-Token ist der Firmen- und Personalausweis des Boten.
Fulcio – Die Behörde für Passierscheine
Fulcio ist ein Root-CA-Service zur Identitätsprüfung. Er stellt den Passierschein in Form eines X.509-Zertifikats aus. Während das Sigstore-Projekt eine öffentliche Instanz für GitHub oder GitLab.com betreibt, nutzen wir bei Puzzle einen eigenen Stack, um unseren internen Identity Provider anzubinden.
Cosign – Das Werkzeug
Cosign ist das Tool, mit dem der Bote das Paket versiegelt (signiert) oder der Empfänger das Siegel prüft (verifiziert).
Rekor – Das Versandregister (Transparency Log)
Rekor speichert die Metadaten fälschungssicher in einem Ledger – ähnlich einer Blockchain. Jeder „Ausgang“ aus der Fabrik bleibt somit rückwirkend nachvollziehbar.
Umsetzung in GitLab
Die Integration in die Pipelines ist denkbar einfach. Hier ein Beispiel-Job:
sign-image:
stage: sign
id_tokens:
SIGSTORE_ID_TOKEN:
aud: sigstore
script:
- cosign sign registry.foo.ch/sigstore/signed:latest --yes --fulcio-url=https://fulcio.foo.ch --oidc-issuer $CI_SERVER_URL --identity-token $SIGSTORE_ID_TOKEN
Die Magie liegt im Abschnitt id_tokens. GitLab generiert hier ein signiertes JSON Web Token (JWT). Fulcio validiert dieses Token gegenüber unserer GitLab-Instanz – genau wie die Behörde, die in der Fabrik nachfragt, ob der Bote rechtmässig dort arbeitet.
Verifizierung in OpenShift
Supply-Chain-Security endet nicht nach der Build-Pipeline. Es muss sichergestellt werden, dass der Inhalt des Pakets auf dem Weg zum Betrieb integer bleibt und nicht manipuliert wurde.
Der digitale Sicherheitsdienst
In OpenShift nutzen wir einen Policy-Controller, der als Türsteher fungiert. Er prüft bei jedem Deployment, ob das Image eine gültige Signatur besitzt. Für unseren PoC haben wir den von Red Hat unterstützten Policy-Operator gewählt.
Zuerst definieren wir eine TrustRoot (unsere vertrauenswürdige Instanz):
apiVersion: policy.sigstore.dev/v1alpha1
kind: TrustRoot
metadata:
name: trust-root
spec:
remote:
mirror: https://tuf.foo.ch
root: <redacted>
Anschliessend erzwingen wir die Prüfung mit einer ClusterImagePolicy. Hier wird festgelegt, dass nur Pakete mit korrektem Passierschein der Behörde (Fulcio) und Eintrag im Register (Rekor) akzeptiert werden:
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: image-policy-keyless-with-trustroot-remote
spec:
authorities:
- ctlog:
trustRootRef: trust-root
url: http://rekor.foo.ch
keyless:
identities:
- issuerRegExp: .*kubernetes.default.*
subjectRegExp: .*kubernetes.io/namespaces/default/serviceaccounts/default
trustRootRef: trust-root
url: http://fulcio.foo.ch
name: attestation
images:
- glob: harbor.foo.ch/pitc-cicd-private/cosign-*
mode: enforce
Anschliessend muss auf Namespace-Ebene der Policy-Controller aktiviert werden. Dies geschieht über folgendes Namespace-Label: policy.rhtas.com/include: “true”.
Versuchen wir nun, ein unsigniertes Paket zu liefern, verweigert der Sicherheitsdienst den Zutritt mit einer Fehlermeldung:
Error from server (BadRequest): admission webhook "policy.rhtas.com" denied the request: validation failed: failed policy: image-policy-keyless-with-trustroot-remote: signature keyless validation failed (...) no signatures found
Fazit
Auch wenn die Signierung nur ein Teil der Supply-Chain-Security ist, ist sie ein entscheidender Schritt in die richtige Richtung. Die Konzepte sind vorhanden. Nun braucht es den Willen der Industrie, diese auch umzusetzen. Sei es durch Eigeninitiative oder regulatorischen Druck. Je mehr Unternehmen ihre Artefakte signieren, desto schwieriger wird es für Angreifer, Schadsoftware einzuschleusen. Aber auch die Konsument:innen der Software sind in der Pflicht, dass diese Konsequent signierte Artefakte von ihren Herstellern verlangen.
Haben wir dein Interesse geweckt? Möchtest du auch von signierten Images profitieren? Nimm Kontakt mit uns auf. Wir helfen dir gerne dabei, deinen eigenen Sigstore-Stack aufzubauen!
