Aller au contenu principal
pipelinebrut.fr — CI/CD · automatisation · terrain
Sécurité

Sigstore en CI/CD : signer vos artefacts sans complexité

Comment intégrer Sigstore dans un pipeline CI/CD pour signer et vérifier images, binaires et paquets sans gérer de clés statiques.

Par Julien Mercier 8 min de lecture
Sigstore en CI/CD : signer vos artefacts sans complexité

Pourquoi l’intégrité des artefacts devient un problème opérationnel

Un pipeline CI/CD ne livre pas seulement du code : il produit des images conteneur, des archives, des binaires, des paquets et parfois des fichiers de configuration générés. Une fois publiés dans un registre ou un dépôt de paquets, ces artefacts peuvent être consommés par plusieurs environnements, équipes ou clients internes. La question n’est donc plus uniquement « le build a-t-il réussi ? », mais aussi : qui a produit cet artefact, depuis quel workflow, et peut-on vérifier qu’il n’a pas été remplacé ?

Dans une chaîne de livraison classique, l’image Docker est poussée vers un registre après les tests. Le déploiement récupère ensuite un tag tel que latest, main ou v1.4.2. Or un tag est une référence mutable dans de nombreux registres : il peut être déplacé vers une autre image. Même lorsqu’une équipe applique de bonnes conventions de versionnage, il reste utile de vérifier cryptographiquement l’origine de l’image consommée.

Le risque opérationnel n’implique pas nécessairement une attaque sophistiquée. Il peut aussi s’agir :

  • d’un jeton de registre exposé dans un poste de travail ou dans une variable CI ;
  • d’un compte de service trop permissif pouvant pousser des images de production ;
  • d’un mauvais projet ou d’un mauvais registre ciblé par un script de publication ;
  • d’un artefact reconstruit hors du pipeline officiel ;
  • d’un déploiement qui référence un tag au lieu d’un digest immuable.

Les contrôles traditionnels répondent partiellement au sujet. Le contrôle d’accès au registre limite qui peut pousser ou tirer une image. Le scan de vulnérabilités renseigne sur son contenu. Un SBOM intégré à la CI/CD décrit les composants connus. Mais aucun de ces mécanismes ne prouve, à lui seul, que l’artefact a été produit par le pipeline attendu.

C’est le rôle d’une signature. Elle relie un artefact précis, identifié idéalement par son digest, à une identité de signature. Dans un environnement DevOps, l’enjeu est de mettre ce contrôle en place sans créer une nouvelle infrastructure de gestion de clés, de certificats et de procédures manuelles. C’est précisément le compromis que cherche à apporter Sigstore.

Sigstore, OIDC et signatures éphémères : le fonctionnement utile

Sigstore est un ensemble de projets open source destiné à signer et vérifier des artefacts logiciels. Son outil le plus courant pour les images OCI est Cosign. Il permet notamment de signer des images de conteneur, des blobs et des attestations.

Le modèle qui intéresse particulièrement les pipelines modernes est la signature dite keyless, c’est-à-dire sans clé privée statique conservée durablement dans le système CI. Au lieu de déposer une clé de signature dans un coffre de secrets et de la monter dans chaque job, le pipeline utilise un jeton OIDC émis par sa plateforme.

Dans le flux général, voici ce qui se passe :

  • le job CI obtient un jeton OIDC avec des informations sur son identité ;
  • Cosign présente ce jeton à Fulcio, l’autorité de certification utilisée dans l’écosystème Sigstore ;
  • Fulcio émet un certificat à durée de vie courte lié à cette identité ;
  • Cosign signe le digest de l’artefact avec une clé éphémère ;
  • la signature et les informations associées sont enregistrées de façon vérifiable, notamment via le journal de transparence Rekor ;
  • un environnement de déploiement vérifie ensuite la signature, l’identité attendue et l’émetteur OIDC accepté.

Le point important n’est pas de mémoriser tous les composants internes. Sur le terrain, il faut retenir que la confiance ne repose plus sur une clé privée longue durée partagée entre des jobs. Elle repose sur l’identité OIDC du workflow qui signe, plus sur les règles de vérification appliquées au moment de consommer l’artefact.

GitHub Actions fournit par exemple des jetons OIDC que les workflows peuvent demander explicitement. GitLab CI/CD propose également une mécanique d’ID tokens pour les intégrations OIDC. D’autres plateformes peuvent fournir des jetons compatibles, mais leur configuration et les revendications incluses diffèrent. Avant de généraliser une configuration, vérifiez donc la documentation de votre forge et les informations réellement présentes dans le jeton.

Cette approche rejoint le mouvement plus large de réduction des secrets statiques dans les pipelines. L’article consacré à OIDC en CI/CD détaille pourquoi une identité temporaire est généralement préférable à un secret réutilisable pour accéder à des services externes.

Ce que Cosign signe réellement : image, digest et attestations

Une signature n’est utile que si elle porte sur la bonne référence. Pour une image de conteneur, la référence la plus robuste est le digest, par exemple une valeur commençant par sha256:. Le digest identifie le contenu exact de l’image. À l’inverse, un tag comme stable ou production exprime une intention de version, mais il peut pointer vers un contenu différent au fil du temps.

Dans un pipeline, une séquence pragmatique consiste à construire l’image, à la pousser dans le registre, à récupérer son digest, puis à signer ce digest. Avec Docker Buildx, la sortie du build peut fournir un digest lorsqu’une image est poussée. Avec d’autres outils, comme Buildah, Kaniko ou les mécanismes de build intégrés à certains runners, la manière de récupérer cette référence varie. Le principe ne change pas : signer l’artefact effectivement publié, pas seulement le tag utilisé dans le script.

Cosign peut aussi produire une attestation. Une attestation est une déclaration signée, attachée à un artefact. Elle peut embarquer, par exemple :

  • un SBOM au format SPDX ou CycloneDX ;
  • des informations de provenance de build ;
  • un résultat de contrôle structuré ;
  • une déclaration au format in-toto.

Il faut toutefois éviter de confondre signature et preuve universelle de sécurité. Une image signée prouve qu’elle a été signée par l’identité autorisée selon la politique appliquée. Elle ne prouve pas automatiquement qu’elle ne contient aucune vulnérabilité, que son code est sans défaut ou que tous ses composants sont acceptables. Une attestation SBOM peut enrichir une décision de déploiement, mais sa valeur dépend aussi de la façon dont le SBOM est produit et contrôlé.

La bonne progression est souvent la suivante : commencer par signer les images de production, vérifier leur identité au déploiement, puis ajouter des attestations quand elles répondent à une décision concrète. L’objectif n’est pas de multiplier les métadonnées parce qu’un outil le permet, mais de rendre la livraison vérifiable.

Intégrer Cosign dans un pipeline CI/CD sans bloquer les équipes

L’intégration initiale peut rester courte. Pour une image publiée dans un registre OCI, Cosign fournit une commande de signature telle que :

cosign sign --yes registry.example.com/equipe/api@sha256:...

Dans un job utilisant une identité OIDC compatible, Cosign peut effectuer une signature keyless. En pratique, la configuration du fournisseur CI reste indispensable : sur GitHub Actions, le workflow doit notamment autoriser l’écriture d’un jeton OIDC via la permission id-token: write. La documentation de la forge doit être votre source de vérité pour ce point, car les noms de variables, permissions et revendications changent selon la plateforme.

Un pipeline de publication raisonnable sépare les responsabilités :

  • un job construit et teste le code ;
  • un job publie l’artefact dans le registre autorisé ;
  • un job signe le digest publié ;
  • le déploiement ne consomme que cette référence immuable ;
  • un contrôle de vérification est exécuté avant ou pendant l’admission du déploiement.

Cette séparation rend les échecs plus faciles à diagnostiquer. Si la publication échoue, le problème est côté registre. Si la signature échoue, il faut regarder l’identité OIDC, le réseau, la configuration Sigstore ou la référence d’image. Si la vérification échoue au déploiement, le problème porte probablement sur la politique attendue ou sur l’artefact déployé.

Pour vérifier une signature keyless, on ne se contente pas d’indiquer l’image. Il faut aussi restreindre l’identité de certificat attendue et l’émetteur OIDC. Une commande de vérification Cosign peut notamment utiliser les paramètres --certificate-identity et --certificate-oidc-issuer. Le principe est essentiel : une vérification qui accepterait n’importe quelle identité valide ne répondrait pas au besoin métier.

Par exemple, une politique peut accepter uniquement les signatures issues du workflow de publication du dépôt de l’application, sur sa branche de livraison. Les valeurs exactes à autoriser doivent être dérivées des revendications et certificats réellement émis dans votre environnement, et non copiées à l’aveugle depuis un exemple trouvé en ligne.

Avant d’imposer ce mécanisme à toute l’organisation, commencez avec un seul service non critique. Faites signer les images, archivez les références exactes utilisées par le déploiement et exécutez la vérification en mode informatif. Cette phase permet d’identifier les cas normaux qui auraient été bloqués : images de base internes, jobs de correctif, déploiements manuels exceptionnels ou environnements de recette.

Vérifier au bon endroit : CI, CD et admission Kubernetes

Signer dans la CI est nécessaire, mais insuffisant. Si personne ne vérifie la signature, elle reste une information disponible sans effet sur la chaîne de livraison. La vérification doit intervenir là où l’artefact est réellement accepté.

Dans un déploiement scripté, une étape cosign verify peut précéder la commande de déploiement. Cette approche est simple et fonctionne aussi hors Kubernetes. Elle suppose néanmoins que tous les chemins de déploiement passent bien par ce pipeline. Un accès direct au cluster, à un outil GitOps ou à une API de déploiement peut contourner ce contrôle.

Dans Kubernetes, il est possible d’appliquer une vérification à l’admission. Des projets tels que Kyverno proposent des politiques de vérification d’images. Sigstore maintient également policy-controller, destiné à appliquer des politiques de signature dans Kubernetes. Ces solutions interviennent avant que le workload ne soit admis dans le cluster.

Une politique d’admission doit être précise sans devenir impraticable. Elle peut, par exemple :

  • imposer des images référencées par digest dans les namespaces de production ;
  • exiger une signature pour les images provenant du registre de l’entreprise ;
  • autoriser une identité de workflow dédiée à la publication de production ;
  • prévoir explicitement les images tierces nécessaires, avec un traitement séparé.

Le passage brutal à un refus global est rarement une bonne première étape. Une politique qui bloque les composants système, les images de maintenance ou les outils de diagnostic sans solution de remplacement sera rapidement contournée. Commencez par l’audit ou un périmètre limité, observez les rejets, puis activez le blocage sur les workloads dont l’équipe maîtrise la publication.

Ce raisonnement est proche de celui des golden paths DevOps : offrir un chemin sécurisé et simple par défaut est plus durable que demander à chaque équipe de reconstruire sa propre politique de signature.

Les fausses bonnes idées à éviter avec Sigstore

Sigstore réduit une partie de la complexité PKI, mais il ne dispense pas de concevoir la chaîne de confiance. Plusieurs erreurs reviennent fréquemment.

Signer un tag mutable et déployer un autre contenu

Si le pipeline signe api:main mais que le déploiement résout ce tag plus tard, le contenu peut avoir changé entre les deux opérations. La correction est simple : publier, récupérer le digest, signer le digest et déployer ce même digest.

Vérifier une signature sans vérifier l’identité

Accepter « toute image avec une signature valide » est trop large dans la plupart des organisations. La vérification doit restreindre l’identité de signature et l’émetteur OIDC. Sans cette contrainte, une signature valide peut provenir d’un workflow, d’un dépôt ou d’un contexte qui n’est pas autorisé à livrer votre application.

Conserver une clé Cosign dans les secrets CI par défaut

Cosign prend aussi en charge des signatures basées sur clé. Elles peuvent être adaptées à certains contextes, notamment lorsqu’un système ne fournit pas d’OIDC exploitable ou lorsqu’une exigence particulière l’impose. Mais stocker une clé privée durable dans les secrets CI comme choix automatique recrée les problèmes connus : rotation, droits de lecture, export accidentel et utilisation hors du contexte prévu.

Quand la signature keyless est compatible avec le pipeline et la politique de sécurité, elle évite précisément cette gestion de clé statique. Ce n’est pas une raison pour négliger les droits OIDC : un workflow capable d’obtenir l’identité de publication doit rester protégé par les règles de revue, les protections de branche et les permissions minimales.

Traiter la signature comme un substitut au contrôle d’accès

Une image signée ne rend pas inutile la gestion des permissions du registre. Limitez toujours les droits de push, séparez les registres ou espaces de noms selon les environnements si cela correspond à votre organisation, et évitez que les jobs de test puissent publier dans le périmètre de production.

La signature complète les contrôles existants. Elle aide à répondre à une question différente : « cet artefact précis provient-il de la chaîne que nous avons autorisée ? »

Une stratégie de déploiement progressive et exploitable

Pour éviter de transformer Sigstore en chantier transverse, adoptez une trajectoire limitée et mesurable. Commencez par recenser les artefacts qui ont réellement besoin d’une preuve d’origine : images de production, binaires distribués à des clients, paquets internes consommés par plusieurs équipes. Les scripts jetables et les artefacts de test n’ont pas forcément besoin du même niveau de contrôle.

Ensuite, documentez le contrat de livraison de chaque application :

  • quel registre est autorisé ;
  • quelle identité CI est autorisée à signer ;
  • quels environnements exigent une vérification ;
  • quelles exceptions existent et qui les valide ;
  • comment retrouver le digest déployé lors d’un incident.

Cette documentation doit être proche du code et du pipeline. Elle peut vivre dans le dépôt de l’application ou dans le dépôt GitOps qui pilote les déploiements. Elle sera plus utile qu’une politique centrale non comprise par les équipes.

Enfin, traitez la signature comme un élément observable du pipeline. Un job doit afficher clairement le digest signé. Le déploiement doit conserver la référence exacte consommée. En cas d’échec de vérification, le message doit indiquer l’identité ou la contrainte qui ne correspond pas, sans exposer de jeton. Cette exigence rejoint les principes d’un suivi bout en bout des flux de déploiement : un contrôle de sécurité utile est aussi un contrôle diagnosticable.

Conclusion : sécuriser la livraison sans ajouter une PKI à administrer

Sigstore et Cosign apportent une réponse pragmatique à un problème concret de CI/CD : vérifier l’origine des artefacts livrés sans distribuer une clé privée de signature permanente dans les jobs. Avec OIDC, une signature keyless associe la publication à l’identité du workflow, tandis que la vérification permet de refuser les artefacts qui ne correspondent pas à la politique attendue.

La mise en œuvre la plus saine reste progressive : signer d’abord les images de production par digest, vérifier l’identité du pipeline, observer les écarts, puis appliquer le contrôle dans le déploiement ou à l’admission Kubernetes. Commencez sur un service maîtrisé, mesurez les cas réels, et faites de la signature un garde-fou simple plutôt qu’une couche de conformité impossible à opérer.