L'attaque sur SolarWinds en 2020, sur Codecov en 2021, sur xz-utils en 2024 ont remis la chaîne d'approvisionnement logicielle au centre des préoccupations sécurité. Quand on tire une image conteneur depuis un registre, qui garantit qu'elle vient bien de l'éditeur attendu, et n'a pas été modifiée entre-temps ?
Sigstore répond à cette question. Projet open source porté par la Linux Foundation depuis 2021, gradué CNCF en 2025, il fournit un écosystème complet pour signer et vérifier les artefacts logiciels. Cosign est l'outil de signature pour les images conteneurs et autres artefacts OCI. Rekor est le journal de transparence public et immutable. Fulcio est l'autorité de certification temporaire qui évite la gestion de clés long terme.
Pour une équipe DevSecOps qui pousse 50 images par jour, Sigstore transforme la signature de "projet de niche cryptographique" en pratique opérationnelle quotidienne.
Plan de l'article
- Le problème supply chain conteneur
- Architecture Sigstore : Cosign, Fulcio, Rekor
- Signature keyless via OIDC
- Cosign en pratique : signer et vérifier
- Attestations SLSA et SBOM signés
- Vérification au déploiement Kubernetes
- Intégration CI/CD GitHub Actions et GitLab
- Gouvernance et limites
Le problème supply chain conteneur
Le pipeline classique : un dev pousse du code, la CI build une image, push vers un registre privé, K8s pull l'image et la déploie. À chaque étape, des risques :
- Compromission du runner CI : injection de code malicieux dans le build.
- Compromission du registre : remplacement de l'image par une variante.
- Compromission du proxy de pull dans le cluster : attaque MITM sur le pull.
- Cache local altéré : tampering sur le node Kubernetes.
Sans signature cryptographique, on ne peut pas distinguer une image légitime d'une image substituée. Le tag :latest ou :1.42 ne garantit rien. Le digest SHA256 garantit l'intégrité du contenu, pas l'origine.
Sigstore ajoute la couche origine. Une image signée avec Cosign porte une signature vérifiable. Le cluster vérifie au pull. Si la signature manque ou ne correspond pas, refus de déploiement.
C'est l'équivalent moderne de Notary v1, en plus simple à opérer.
Architecture Sigstore : Cosign, Fulcio, Rekor
Trois composants principaux, accessibles publiquement en infrastructure managée par la fondation Sigstore.
Fulcio : autorité de certification éphémère. Émet un certificat X.509 avec une durée de vie de 10 minutes, lié à une identité OIDC (compte GitHub, GitLab, Google, Microsoft, ou OIDC custom). Pas de clé privée à protéger sur la durée. La signature est faite avec ce certificat court terme.
Rekor : journal de transparence append-only, basé sur Trillian (Google). Chaque signature est inscrite dans Rekor, horodatée, immutable. Permet la détection a posteriori d'une signature frauduleuse (audit log distribué).
Cosign : outil CLI qui orchestre tout : signature, vérification, gestion d'attestations OCI, gestion de policies. Compatible registres OCI standards (Docker Hub, Harbor, GHCR, GitLab CR, AWS ECR, GCP Artifact Registry).
Ensemble, ces trois composants permettent une signature dite "keyless" : pas de clé long terme à protéger, identité prouvée par OIDC, traçabilité publique via Rekor.
Signature keyless via OIDC
Le flux nominal d'une signature Cosign keyless :
- Le user (ou un runner CI) lance
cosign sign image:tag. - Cosign ouvre un flow OIDC vers le provider configuré (GitHub Actions, Google, etc.).
- Le provider OIDC retourne un token signé.
- Cosign envoie ce token à Fulcio, qui émet un certificat X.509 court terme contenant l'identité OIDC.
- Cosign signe l'image avec la clé privée associée à ce certificat.
- La signature et le certificat sont publiés sur Rekor (public log).
- La signature est attachée à l'image dans le registre OCI (sous forme d'objet OCI artifact).
Pour un registre privé, la signature reste dans le registre privé. Seul Rekor garde la trace publique (sans révéler le digest sensible si on le souhaite). On peut aussi opérer un Rekor privé pour les organisations qui n'acceptent pas le journal public.
Côté ops, l'avantage est immense : pas de clé privée à stocker, à rotater, à protéger dans un HSM. L'identité GitHub Actions du workflow est l'identité signataire. L'intégration s'aligne avec les pipelines GitHub Actions runners ou GitLab CI on K8s.
Cosign en pratique : signer et vérifier
Install :
go install github.com/sigstore/cosign/v2/cmd/cosign@latest
# ou via brew, apk, dnf, paquets distro
Signature keyless interactive :
cosign sign registry.exemple.fr/billing-api:1.42
# Browser ouvre un flow OIDC, signature publiée sur Rekor
Signature non interactive en CI (token OIDC fourni par GitHub Actions) :
- uses: sigstore/cosign-installer@v3
- name: Sign container image
env:
COSIGN_EXPERIMENTAL: '1'
run: |
cosign sign --yes \
registry.exemple.fr/billing-api@${{ steps.build.outputs.digest }}
Vérification :
cosign verify registry.exemple.fr/billing-api:1.42 \
--certificate-identity-regexp '^https://github\.com/exemple/billing-api/.+$' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
La vérification valide que la signature existe, qu'elle est bien dans Rekor, et que l'identité signataire correspond au pattern attendu. Si un attaquant signe avec un compte GitHub différent, la vérification échoue.
Pour les anciens patterns avec clé statique (toujours supportés), Cosign gère aussi cosign generate-key-pair et signature classique. À éviter sur du neuf.
Attestations SLSA et SBOM signés
Au-delà de la signature de l'image elle-même, Cosign permet de signer des attestations : déclarations vérifiables sur l'image. Format standard : in-toto attestations.
Attestations courantes :
- SLSA provenance : qui a buildé l'image, quel commit Git, quel runner, quel pipeline. Standard SLSA défini par OpenSSF.
- SBOM (Software Bill of Materials) : liste des composants logiciels et leurs versions. Format CycloneDX ou SPDX.
- Vulnerability scan results : output Trivy ou Grype attaché comme attestation.
- Test results : preuve que l'image est passée par sa suite de tests.
Exemple : générer un SBOM avec Syft, l'attacher signé avec Cosign :
syft registry.exemple.fr/billing-api:1.42 -o cyclonedx-json > sbom.json
cosign attest --predicate sbom.json --type cyclonedx \
registry.exemple.fr/billing-api:1.42
Au pull, le cluster vérifie : signature image présente, SBOM signé attaché, scan vulnérabilités passé. Si un des contrôles manque, refus.
Pour la chaîne complète, articuler avec Trivy en scan registre et un Harbor registre qui sait stocker et exposer ces attestations.
Vérification au déploiement Kubernetes
Sur un cluster K8s, la vérification se fait via un admission controller. Plusieurs implémentations :
Sigstore Policy Controller : projet officiel Sigstore. Définit des ClusterImagePolicy CRD qui décrivent les politiques de vérification par image, par namespace, par registre.
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: require-signed-images
spec:
images:
- glob: 'registry.exemple.fr/**'
authorities:
- keyless:
url: https://fulcio.sigstore.dev
identities:
- issuer: https://token.actions.githubusercontent.com
subjectRegExp: '^https://github\.com/exemple/.+$'
Kyverno : moteur de policies plus large que la signature, supporte la vérification Cosign en natif depuis 1.7.
OPA Gatekeeper : via une rego policy qui appelle Cosign verify, ou via la nouvelle intégration native.
L'admission controller intercepte chaque déploiement, vérifie les images, autorise ou refuse. Sans signature valide, le pod ne démarre pas.
À aligner avec k8s OPA Gatekeeper si on a déjà cette stack.
Intégration CI/CD GitHub Actions et GitLab
Le pattern GitOps complet sur GitHub Actions :
jobs:
build-sign-publish:
runs-on: ubuntu-latest
permissions:
id-token: write # OIDC pour Fulcio
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: registry.exemple.fr
username: ${{ secrets.REG_USER }}
password: ${{ secrets.REG_PASS }}
- id: build
uses: docker/build-push-action@v5
with:
push: true
tags: registry.exemple.fr/billing-api:${{ github.sha }}
- uses: sigstore/cosign-installer@v3
- run: cosign sign --yes registry.exemple.fr/billing-api@${{ steps.build.outputs.digest }}
- run: cosign attest --predicate sbom.json --type cyclonedx \
registry.exemple.fr/billing-api@${{ steps.build.outputs.digest }}
GitLab CI : équivalent avec id_tokens pour l'OIDC GitLab vers Fulcio (supporté depuis 16.x). Voir aussi Drone CI pour les contextes alternatifs.
Gouvernance et limites
Quelques points qui demandent une décision avant le rollout.
Rekor public ou privé. Le Rekor public expose le digest et l'identité signataire. Pour les organisations sensibles à la fuite d'information sur la cadence de release, opérer un Rekor privé est une option (composante self-host disponible).
Identités OIDC autorisées. Définir précisément quelles identités peuvent signer pour un projet donné. Une faute commune : laisser n'importe quel compte GitHub Actions de l'organisation signer n'importe quelle image. La policy subjectRegExp doit matcher le repo précis.
Rotation et révocation. Sigstore est append-only. Une signature inscrite dans Rekor reste inscrite. La révocation se fait par publication d'une politique explicite côté admission controller, pas par suppression de signature. Documenter ce flow.
Compatibilité legacy. Les images signées Notary v1 ou Docker Content Trust ne sont pas compatibles Cosign. Migrer ou cohabiter selon le périmètre.
Déploiements offline / edge. Si les noeuds K8s n'ont pas d'accès internet, la vérification Rekor en ligne ne marche pas. Solution : vérification offline avec bundle de signature embarqué dans l'image. Supporté depuis Cosign 2.x.
Performance. La vérification ajoute quelques 100ms au pull. Négligeable à l'échelle d'un cluster K8s, mais à mesurer.
Sur les pipelines DevSecOps qu'on opère pour nos clients, Sigstore est désormais la couche signature par défaut, intégrée au pipeline build et au admission controller cluster. Le déploiement initial est mécanique. Le travail réel est dans la définition des policies (qui peut signer quoi, quelles attestations sont obligatoires) et dans la gouvernance (revue trimestrielle des identités autorisées). Si vous démarrez un projet de signature d'images et que vous voulez éviter de redécouvrir les écueils que tous les premiers adopteurs ont rencontrés, on peut auditer votre cible et mettre en oeuvre la stack complète en deux à trois sprints.
Sources
- Sigstore documentation officielle : architecture, concepts, guides.
- Cosign GitHub : code, releases, examples.
- Sigstore CNCF graduated project : positionnement et adopters.
- SLSA framework : niveaux de provenance et attestations standardisées.
- Rekor transparency log : journal de transparence Sigstore.
- in-toto attestations : standard d'attestations vérifiables sur le pipeline.


