Aller au contenu

Sécuriser la Supply Chain avec Cosign

Mise à jour :

La sécurité des images de conteneurs est un enjeu majeur. Comment être certain qu’une image provient bien de sa source officielle et qu’elle n’a pas été altérée ? C’est là qu’intervient Cosign, un outil développé par Sigstore pour signer et vérifier des images de manière simple et sécurisée.

Avec Cosign, plus besoin de stocker des clés privées sur votre machine, et les signatures peuvent être directement enregistrées dans un registre OCI. Cet outil s’intègre facilement dans une chaîne CI/CD et renforce la confiance dans le déploiement des applications.

Origine et historique

L’adoption massive des conteneurs a apporté de nombreux avantages, mais aussi des défis en matière de sécurité. Comment garantir qu’une image téléchargée sur un registry n’a pas été modifiée ou compromise ? C’est pour répondre à ce problème que Cosign a été créé.

Au fil des années, plusieurs attaques ont mis en lumière la vulnérabilité des chaînes d’approvisionnement logicielles. Les images conteneurisées ne font pas exception. Des images malveillantes peuvent être publiées sous des noms similaires à des versions officielles, ou bien des images peuvent être altérées avant d’être utilisées en production.

En 2021, Cosign a vu le jour sous l’égide de Sigstore, un projet open source soutenu par Google, Red Hat et la Linux Foundation. L’objectif de Sigstore est de faciliter la signature et la vérification de logiciels, sans imposer de complexité supplémentaire aux développeurs.

Depuis son lancement, Cosign a été rapidement adopté par les entreprises et les projets open source soucieux de renforcer leur chaîne de confiance. Il est désormais intégré à de nombreuses pipelines CI/CD, compatible avec les registries OCI, et utilisé par des plateformes comme Kubernetes pour vérifier l’authenticité des images avant leur déploiement.

Fonctionnement

Cosign simplifie la signature et la vérification des images de conteneurs sans complexité inutile. Contrairement aux méthodes traditionnelles qui nécessitent des certificats lourds à gérer, Cosign adopte une approche plus fluide et mieux intégrée aux workflows DevSecOps. Voici ses principales fonctionnalités.

L’une des innovations de Cosign est de permettre la signature sans stocker de clé privée sur l’ordinateur. Il prend en charge l’authentification via des fournisseurs OIDC ou un KMS comme Google Cloud KMS, AWS KMS ou HashiCorp Vault, garantissant ainsi que les clés sont générées et stockées de manière sécurisée.

Les signatures ne sont pas stockées dans un fichier séparé, mais directement dans le registry OCI à côté de l’image signée. Cela permet :

  • D’éviter les pertes ou incohérences entre l’image et sa signature.
  • De faciliter la vérification automatique par des outils tiers.
  • D’assurer une intégration native avec les CI/CD pipelines.

Une fois une image signée, Cosign permet de vérifier en une commande si elle est authentique. Il peut aussi s’intégrer avec Kubernetes pour imposer des politiques d’admission qui bloquent le déploiement d’images non signées ou provenant de sources inconnues.

En plus de la signature, Cosign permet d’ajouter des attestations qui décrivent le processus de build, garantissant qu’une image provient bien d’une build validé. Cela est essentiel pour répondre aux exigences de Supply Chain Security et aux frameworks comme SLSA.

L’outil est conçu pour fonctionner avec des systèmes d’intégration et de déploiement continue comme GitHub Actions, Gitlab CI et Tekton. Il permet d’automatiser la signature et la vérification des images avant leur déploiement en production.

Grâce à ces fonctionnalités, Cosign devient un élément clé de la sécurisation des images de conteneurs et s’impose comme un standard dans la gestion de la chaîne de confiance logicielle. Dans le prochain chapitre, nous explorerons les concepts fondamentaux de la signature et de la vérification avec Cosign.

Installation et configuration de Cosign

Avant de commencer à signer et vérifier des images, il faut installer et configurer Cosign correctement. Voici les étapes selon votre système d’exploitation.

Si vous utilisez Homebrew :

Terminal window
brew install cosign

On peut aussi télécharger le binaire depuis GitHub pour toutes les trois plateformes (Linux, MacOS, Windows) :

Terminal window
wget https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o cosign # Linux
Invoke-WebRequest -Uri "https://github.com/sigstore/cosign/releases/latest/download/cosign-windows-amd64.exe" -OutFile "cosign.exe" #

Pour Linux, rendez le binaire exécutable et installez-le dans le répertoire /usr/local/bin :

Terminal window
chmod +x cosign
sudo install cosign /usr/local/bin/cosign

Une fois installé, vérifiez que Cosign fonctionne correctement :

Terminal window
cosign version
______ ______ _______. __ _______ .__ __.
/ | / __ \ / || | / _____|| \ | |
| ,----'| | | | | (----`| | | | __ | \| |
| | | | | | \ \ | | | | |_ | | . ` |
| `----.| `--' | .----) | | | | |__| | | |\ |
\______| \______/ |_______/ |__| \______| |__| \__|
cosign: A tool for Container Signing, Verification and Storage in an OCI registry.
GitVersion: v2.4.1
GitCommit: 9a4cfe1aae777984c07ce373d97a65428bbff734
GitTreeState: clean
BuildDate: 2024-10-03T17:01:50Z
GoVersion: go1.22.7
Compiler: gc
Platform: linux/amd64

Vous devriez voir la version installée s’afficher comme ci-dessus.

Générer une paire de clés pour Cosign

Générer une paire de clés locales

Si vous ne l’avez pas encore fait, commencez par générer une paire de clés :

Terminal window
cosign generate-key-pair

Entrez une paraphrase, cela crée deux fichiers :

  • cosign.key : la clé privée utilisée pour signer les images.
  • cosign.pub : la clé publique qui permettra de vérifier les signatures.

Configurer Cosign avec une clé avec un KMS

Il est possible de configurer Cosign pour utiliser un Key Management Service (KMS) externe, offrant ainsi une sécurité renforcée et un meilleur contrôle des clés.

Lorsqu’un KMS est utilisé, Cosign n’a plus besoin de stocker des clés privées localement. À la place, il se connecte à un fournisseur de gestion de clés, qui sécurise les signatures et évite les risques de vol ou de fuite de clés.

Cosign utilise une URI spécifique pour identifier chaque fournisseur de KMS :

  • AWS KMSawskms://
  • Google Cloud KMSgcpkms://
  • Azure Key Vaultazurekms://
  • HashiCorp Vaulthashivault://
  • Kubernetes Secretsk8s://

Chaque KMS a sa propre syntaxe d’URI, que nous détaillerons plus loin.

Pour créer une clé de signature dans un KMS, utilisez la commande suivante :

Terminal window
cosign generate-key-pair --kms <provider>://<clé>

Par exemple, pour générer une clé sur AWS KMS :

Terminal window
cosign generate-key-pair --kms awskms://arn:aws:kms:us-west-2:123456789012:key/abcd-1234-efgh-5678

Pour Google Cloud KMS :

Terminal window
cosign generate-key-pair --kms gcpkms://projects/mon-projet/locations/global/keyRings/monKeyRing/cryptoKeys/maClé

Et pour Azure Key Vault :

Terminal window
cosign generate-key-pair --kms azurekms://mon-vault/ma-clé

Une fois la clé générée, Cosign utilisera automatiquement le KMS pour signer et vérifier les images.

Signer une image avec Cosign

Maintenant que Cosign est installé et configuré, nous allons voir comment signer une image de conteneur. La signature garantit que l’image provient bien d’une source vérifiée et qu’elle n’a pas été modifiée.

Signer une image avec une clé locale

Pour signer une image, utilisez la commande suivante :

Terminal window
cosign sign --key cosign.key mon-registry/mon-image:latest

Cosign vous demandera la passphrase de votre clé. Une fois l’image signée, la signature sera stockée directement dans le registre OCI.

Signer une image avec un KMS

Si vous avez configuré Cosign avec un KMS, vous pouvez signer une image en appelant directement le KMS :

Avec AWS KMS :

Terminal window
cosign sign --key awskms://arn:aws:kms:us-west-2:123456789012:key/abcd-1234-efgh-5678 mon-registry/mon-image:latest

Avec Google Cloud KMS :

Terminal window
cosign sign --key gcpkms://projects/mon-projet/locations/global/keyRings/monKeyRing/cryptoKeys/maClé mon-registry/mon-image:latest

Avec Azure Key Vault :

Terminal window
cosign sign --key azurekms://mon-vault/ma-clé mon-registry/mon-image:latest

Et pour HashiCorp Vault :

Terminal window
cosign sign --key hashivault://mon-vault/ma-clé mon-registry/mon-image:latest

Vérifier une image signée

Une fois une image signée avec Cosign, il est essentiel de pouvoir vérifier son authenticité avant de l’utiliser ou de la déployer. La vérification permet de s’assurer que l’image provient bien de son auteur d’origine et n’a pas été altérée.

Vérifier une image avec une clé publique locale

Si une image a été signée avec une clé privée, elle peut être vérifiée avec la clé publique correspondante. Voici la commande pour vérifier une image :

Terminal window
cosign verify --key cosign.pub mon-registry/mon-image:latest

Si la signature est valide, Cosign affichera un message confirmant que l’image est authentique.

Vérification avec un KMS

Si l’image a été signée avec un KMS, la vérification se fait en appelant le fournisseur de clés :

Pour AWS KMS :

Terminal window
cosign verify --key awskms://arn:aws:kms:us-west-2:123456789012:key/abcd-1234-efgh-5678 mon-registry/mon-image:latest

Pour Google Cloud KMS :

Terminal window
cosign verify --key gcpkms://projects/mon-projet/locations/global/keyRings/monKeyRing/cryptoKeys/maClé mon-registry/mon-image:latest

Ou avec HashiCorp Vault :

Terminal window
cosign verify --key hashivault://mon-vault/ma-clé mon-registry/mon-image:latest

Cosign récupérera la signature enregistrée dans le registre et la comparera avec la clé stockée dans le KMS.

Intégration à des pipelines CI/CD

L’automatisation de la signature et de la vérification des images dans un pipeline CI/CD permet de garantir qu’aucune image non signée ou compromise n’est déployée en production. Cosign s’intègre facilement avec des outils comme GitHub Actions, GitLab CI et Jenkins.

Automatiser la signature avec GitHub Actions

Si vous utilisez GitHub Actions, vous pouvez ajouter une étape pour signer automatiquement les images générées. Voici un exemple de workflow GitHub Actions :

name: Build and Sign Container
on:
push:
branches:
- main
jobs:
build-and-sign:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.5.0
- name: Login to GitHub Container Registry
uses: docker/login-action@v2.1.0
with:
registry: quay.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Publish Dockerfile
uses: docker/build-push-action@v4
id: build-and-push
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: quay.io/${{ github.repository }}:latest
- name: Install Cosign
uses: sigstore/cosign-installer@v3.1.1
- name: Sign image with a key
run: |
cosign sign --yes --key env://COSIGN_PRIVATE_KEY quay.io/${{ github.repository }}:latest
env:
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}

Vérification automatique dans GitLab CI/CD

Dans un pipeline GitLab CI/CD, vous pouvez par exemple ajouter une étape pour vérifier les images avant déploiement :

verify_image:
image: alpine:3.20
stage: verify
before_script:
- apk add --update cosign docker
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- cosign verify "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" --certificate-identity "https://gitlab.com/my-group/my-project//path/to/.gitlab-ci.yml@refs/heads/main" --certificate-oidc-issuer "https://gitlab.com"

Conclusion

Nous avons vu comment Cosign permet de signer, vérifier et sécuriser les images de conteneurs à l’aide de clés et de services KMS. Que ce soit pour un usage individuel ou une intégration en CI/CD, Cosign offre une solution efficace et simple à mettre en place pour renforcer la chaîne de de livraison logicielle.

Cependant, ce guide n’est qu’une introduction à l’écosystème Sigstore. Cosign n’est qu’un des outils de cet environnement plus vaste, qui inclut également Rekor (journalisation des signatures), Fulcio (certificat d’identité OIDC).

De plus, nous n’avons pas encore abordé la vérification des images avant leur déploiement dans un cluster Kubernetes. Comment empêcher l’exécution d’images non signées dans un cluster ? Comment intégrer Cosign avec des Admission Controllers comme Kyverno ou OPA Gatekeeper ? Ces sujets feront l’objet d’autres guides pour aller encore plus loin dans la sécurisation des environnements conteneurisés.

Si vous souhaitez approfondir l’utilisation de Sigstore et Cosign, n’hésitez pas à explorer la documentation officielle et à expérimenter l’outil dans vos propres pipelines. La sécurité des conteneurs n’est plus une option, c’est une nécessité.