DevOpsFacile
AccueilParcours de formationCertificationsModulesCheat SheetÀ Propos
DevOpsFacile

Une plateforme d'apprentissage complète pour maîtriser les pratiques DevOps modernes, du débutant à l'expert.

contact@devopsfacile.fr

Formation

  • Parcours de formation
  • Modules

Informations

  • À Propos
  • Conditions d'utilisation
  • Confidentialité
  • Mentions légales

© 2026 DevOps Facile. Tous droits réservés.

Fait avec pour la communauté DevOps

ModulesSécurité DevOps - Avancé02 - Générer un SBOM et signer ses images Docker avec cosign

Détails

  • 40 minutes
  • Avancé

Objectifs

  • Générer un SBOM (Software Bill of Materials) avec syft
  • Signer une image Docker avec cosign (keyless)
  • Vérifier la signature d'une image avant déploiement
  • Intégrer SBOM et signature dans un pipeline GitHub Actions
Module Sécurité DevOps - Avancé

Exercice 02 : Générer un SBOM et signer ses images Docker avec cosign

🎯 Objectifs

À la fin de cet exercice, vous serez capable de :

  • ✅ Générer un SBOM en format SPDX et CycloneDX avec syft
  • ✅ Signer une image Docker avec cosign en mode keyless (OIDC)
  • ✅ Attacher le SBOM comme attestation cosign à l'image
  • ✅ Vérifier la signature d'une image avant de la déployer
  • ✅ Intégrer signature et SBOM dans un workflow GitHub Actions

Durée estimée : 40 minutes

Difficulté : ⭐⭐⭐☆☆ (Avancé)

Prérequis : Docker, compte GitHub avec repository, cosign et syft installables


📖 Contexte

La supply chain attack SolarWinds (2020) a montré qu'un attaquant peut compromettre le processus de build pour injecter du code malveillant dans une image officielle. Pour s'en protéger, il faut pouvoir prouver que l'image que vous déployez est bien celle qui a été buildée par votre CI, et pas une image modifiée.

SBOM (Software Bill of Materials) : inventaire complet de tous les composants d'une image, comme la liste d'ingrédients d'un produit alimentaire.

cosign : outil de signature cryptographique d'images de conteneurs. La signature est stockée dans le registre à côté de l'image.


📋 Énoncé

Buildez une image Docker, générez son SBOM, signez-la avec cosign, et vérifiez la chaîne de confiance.


🧭 Déroulement de l'exercice

Tâche 1 : Installer syft et cosign

bash
# Installer syft (générateur de SBOM)
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

# Installer cosign
COSIGN_VERSION=$(curl -s https://api.github.com/repos/sigstore/cosign/releases/latest | grep tag_name | cut -d'"' -f4)
curl -sSL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-amd64" -o /tmp/cosign
chmod +x /tmp/cosign && sudo mv /tmp/cosign /usr/local/bin/cosign

# Vérifications
syft version
cosign version

Tâche 2 : Créer et builder une image Docker

bash
mkdir sbom-cosign-demo && cd sbom-cosign-demo

cat > Dockerfile << 'EOF'
FROM node:22-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
USER app

EXPOSE 3000
CMD ["node", "server.js"]
EOF

cat > package.json << 'EOF'
{
  "name": "sbom-demo",
  "version": "1.0.0",
  "dependencies": {
    "express": "^4.18.0",
    "helmet": "^7.1.0"
  }
}
EOF

echo "require('express')().get('/',(r,s)=>s.send('ok')).listen(3000)" > server.js
npm install

# Builder l'image
docker build -t sbom-demo:latest .
docker tag sbom-demo:latest sbom-demo:1.0.0

Tâche 3 : Générer le SBOM avec syft

bash
# Générer un SBOM en format SPDX JSON (standard de l'industrie)
syft sbom-demo:latest -o spdx-json=sbom.spdx.json

# Générer aussi en CycloneDX (format utilisé par Dependency-Track)
syft sbom-demo:latest -o cyclonedx-json=sbom.cyclonedx.json

# Lire le SBOM : combien de composants ?
cat sbom.spdx.json | python3 -c "
import json, sys
sbom = json.load(sys.stdin)
packages = sbom.get('packages', [])
print(f'Total packages: {len(packages)}')
# Afficher les 5 premiers
for p in packages[:5]:
    print(f'  - {p[\"name\"]} {p.get(\"versionInfo\", \"\")}')
"

Indice : Un SBOM complet liste TOUS les composants : packages npm, bibliothèques système Alpine, binaires. Pour node:22-alpine, le SBOM peut contenir 200-400 composants. C'est cette liste exhaustive qui permet à Trivy ou Dependency-Track de détecter des CVE dans votre image.

Vérification : sbom.spdx.json existe et contient plus de 50 packages.


Tâche 4 : Signer l'image avec cosign (keyless)

Le mode keyless utilise votre identité OIDC (GitHub Actions, Google, etc.) comme preuve d'identité. La signature est enregistrée dans Rekor (journal public d'audit).

bash
# Pousser l'image vers un registre (nécessaire pour la signature)
# Pour cet exercice, utilisons le registre GitHub
# Remplacez votre-username par votre GitHub username
docker tag sbom-demo:latest ghcr.io/votre-username/sbom-demo:latest
docker push ghcr.io/votre-username/sbom-demo:latest

# Signer l'image (keyless = utilise l'OIDC GitHub si dans Actions, sinon interactif)
cosign sign --yes ghcr.io/votre-username/sbom-demo:latest

# Attacher le SBOM comme attestation à l'image
cosign attest --yes \
  --type spdxjson \
  --predicate sbom.spdx.json \
  ghcr.io/votre-username/sbom-demo:latest

Indice : En mode keyless, cosign ouvre un navigateur pour l'authentification OIDC. Dans GitHub Actions, ce processus est automatique via ACTIONS_ID_TOKEN_REQUEST_URL. La signature est stockée dans Rekor (https://rekor.sigstore.dev) - un journal public immuable.


Tâche 5 : Vérifier la signature et le SBOM

bash
# Vérifier que l'image est bien signée
cosign verify \
  --certificate-identity-regexp "https://github.com/votre-username/" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/votre-username/sbom-demo:latest

# Vérifier et extraire l'attestation SBOM
cosign verify-attestation \
  --type spdxjson \
  --certificate-identity-regexp "https://github.com/votre-username/" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/votre-username/sbom-demo:latest | jq '.payload | @base64d | fromjson | .predicate.packages | length'

Vérification : La commande verify ne doit pas afficher d'erreur et doit retourner les informations de signature.


Tâche 6 : Intégrer dans GitHub Actions

bash
mkdir -p .github/workflows
cat > .github/workflows/build-sign.yml << 'EOF'
name: Build, SBOM et Signature

on:
  push:
    branches: [main]
    tags: ['v*']

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-sign:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write  # Requis pour cosign keyless

    steps:
      - uses: actions/checkout@v4

      - name: Installer cosign
        uses: sigstore/cosign-installer@v3

      - name: Installer syft
        uses: anchore/sbom-action/download-syft@v0

      - name: Login au registre GitHub
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build et push
        id: build
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

      - name: Générer le SBOM
        uses: anchore/sbom-action@v0
        with:
          image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
          format: spdx-json
          output-file: sbom.spdx.json

      - name: Signer l'image (keyless)
        run: |
          cosign sign --yes \
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}

      - name: Attacher le SBOM comme attestation
        run: |
          cosign attest --yes \
            --type spdxjson \
            --predicate sbom.spdx.json \
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
EOF

✅ Vérification du résultat

  • syft génère un SBOM avec 50+ packages listés
  • sbom.spdx.json et sbom.cyclonedx.json sont créés
  • L'image est poussée sur le registre
  • cosign sign complète sans erreur
  • cosign verify confirme la signature valide

💡 À retenir

La chaîne de confiance supply chain :

Code → Build CI → SBOM (quoi ?) → Signature cosign (qui ? quand ?)
                                          ↓
                               Rekor (journal public immuable)
                                          ↓
                          Déploiement → Vérification de signature

Si quelqu'un modifie l'image après sa signature, cosign verify échoue. Sans signature, vous déployez ce que vous pensez être votre image - pas ce qui a réellement été buildé.


✨ Solution Complète

bash
# Générer SBOM
syft mon-image:latest -o spdx-json=sbom.json

# Signer et attacher SBOM
cosign sign --yes mon-registre.io/mon-image:latest
cosign attest --yes --type spdxjson --predicate sbom.json mon-registre.io/mon-image:latest

# Vérifier avant déploiement
cosign verify --certificate-identity-regexp "github.com/mon-org" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  mon-registre.io/mon-image:latest
Retour au module

Sur cette page

  • 🎯 Objectifs
  • 📖 Contexte
  • 📋 Énoncé
  • 🧭 Déroulement de l'exercice
  • Tâche 1 : Installer syft et cosign
  • Tâche 2 : Créer et builder une image Docker
  • Tâche 3 : Générer le SBOM avec syft
  • Tâche 4 : Signer l'image avec cosign (keyless)
  • Tâche 5 : Vérifier la signature et le SBOM
  • Tâche 6 : Intégrer dans GitHub Actions
  • ✅ Vérification du résultat
  • 💡 À retenir
  • ✨ Solution Complète