Sécurité

Cosign (Sigstore)

Signature et vérification d'images OCI - projet Sigstore OpenSSF. Keyless via OIDC/Rekor, clés KMS ou keypair. Intégration Kyverno, Gatekeeper, Tekton Chains.

Cosign est l'outil de signature d'images OCI du projet Sigstore, initiative open source co-fondée par Google, Red Hat, Chainguard et Purdue University sous l'égide de l'OpenSSF (Open Source Security Foundation). Il permet de signer cryptographiquement des images de conteneurs et de vérifier ces signatures avant le déploiement, créant une chaîne de confiance de la build jusqu'au cluster. Cosign supporte plusieurs modes de signature : keyless (via OIDC et Rekor, sans gestion de clé privée), clé statique (keypair), et KMS (AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault).

Cosign est le composant de signature de Sigstore, aux côtés de Rekor (journal de transparence) et Fulcio (CA pour certificats ephémères OIDC).


Informations essentielles

Origine : Google / Red Hat / Chainguard / Purdue University → OpenSSF  ·  Licence : Apache 2.0  ·  Architectures : x86_64, ARM64

Liens : Site officiel  ·  Documentation  ·  GitHub  ·  Releases

Support : OpenSSF Graduated depuis mars 2024, releases régulières. Infrastructure publique Sigstore (Rekor, Fulcio) opérée par la Linux Foundation.

Stack par défaut

ComposantValeur
Mode keylessOIDC (GitHub Actions, GKE WI, etc.) + Rekor + Fulcio
Mode clé statiquekeypair .key / .pub, ou secret Kubernetes
Mode KMSAWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault
Stockage signaturesOCI registry (même repo que l'image, tag sha256-<digest>.sig)
AttestationsSBOM, SLSA Provenance, custom predicates

Concepts clés

ConceptDescription
Signature OCIStockée dans le même registry que l'image, pas de sidecar
KeylessOIDC - identité CI/CD (GitHub Actions, etc.) remplace la clé privée
RekorJournal de transparence immuable - enregistre toutes les signatures
FulcioCA éphémère - émet un certificat court (20 min) lié à l'identité OIDC
AttestationMétadonnées signées attachées à l'image (SBOM, provenance…)
BundleSignature + certificat + entrée Rekor (vérifiable hors ligne)

Prérequis

RessourceValeur
Registry OCICompatible OCI (Docker Hub, ghcr.io, ECR, GCR, ACR, Harbor…)
Clé ou OIDCKeypair, KMS, ou environnement OIDC (GitHub Actions, GKE, etc.)

Installation

# Linux amd64
curl -Lo cosign https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign && sudo mv cosign /usr/local/bin/

# macOS
brew install cosign

# Go install
go install github.com/sigstore/cosign/v2/cmd/cosign@latest

# Vérifier
cosign version

Vérification de l'installation

# 1. Version
cosign version

# 2. Vérifier une image publique déjà signée (Chainguard)
cosign verify \
  --certificate-identity-regexp ".*" \
  --certificate-oidc-issuer-regexp ".*" \
  cgr.dev/chainguard/static:latest
# Vérification OK avec les données Rekor

# 3. Tester la connectivité Rekor (mode keyless)
curl https://rekor.sigstore.dev/api/v1/log
# {"treeSize": ..., "rootHash": "..."}

# 4. Vérifier Fulcio (CA éphémère)
curl https://fulcio.sigstore.dev/api/v2/trustBundle
# Liste des certificats racines

Signer avec keypair (mode clé statique)

Générer une paire de clés

# Générer cosign.key (privée) + cosign.pub (publique)
cosign generate-key-pair

# Ou stocker directement dans un secret Kubernetes
cosign generate-key-pair k8s://my-namespace/cosign-keys

Signer une image

# Signer (la clé privée est demandée)
cosign sign --key cosign.key myregistry.io/myapp:v1.0

# Ou avec la clé dans un secret K8s
cosign sign --key k8s://my-namespace/cosign-keys myregistry.io/myapp:v1.0

Vérifier la signature

cosign verify \
  --key cosign.pub \
  myregistry.io/myapp:v1.0

# Sortie JSON avec les détails
cosign verify --key cosign.pub myregistry.io/myapp:v1.0 | jq .

Signer en mode keyless (GitHub Actions)

Le mode keyless est recommandé en CI/CD : l'identité GitHub Actions remplace la clé privée, aucune gestion de secret n'est nécessaire.

# .github/workflows/build.yml
- name: Login to registry
  uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}

- name: Build et push image
  run: |
    docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .
    docker push ghcr.io/${{ github.repository }}:${{ github.sha }}

- name: Signer l'image avec Cosign (keyless)
  uses: sigstore/cosign-installer@v3
- run: |
    cosign sign --yes \
      ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
  env:
    COSIGN_EXPERIMENTAL: "1"    # Keyless mode

Vérifier une signature keyless

cosign verify \
  --certificate-identity "https://github.com/my-org/my-repo/.github/workflows/build.yml@refs/heads/main" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/my-org/my-app:v1.0

Attacher des attestations

Attacher un SBOM

# Générer un SBOM avec Syft
syft myregistry.io/myapp:v1.0 -o spdx-json > sbom.spdx.json

# Attacher et signer le SBOM
cosign attest \
  --key cosign.key \
  --predicate sbom.spdx.json \
  --type spdx \
  myregistry.io/myapp:v1.0

# Vérifier et lire l'attestation SBOM
cosign verify-attestation \
  --key cosign.pub \
  --type spdx \
  myregistry.io/myapp:v1.0 | jq -r '.payload' | base64 -d | jq .

Enforcement dans Kubernetes

Via Kyverno (recommandé)

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: enforce
  rules:
  - name: check-image-signature
    match:
      any:
      - resources:
          kinds: [Pod]
          namespaces: [production]
    verifyImages:
    - imageReferences:
      - "myregistry.io/myapp:*"
      attestors:
      - entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              <contenu de cosign.pub>
              -----END PUBLIC KEY-----

Via OPA Gatekeeper + Cosign

# Installer le policy controller Sigstore
kubectl apply -f https://github.com/sigstore/policy-controller/releases/latest/download/release.yaml
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
  name: require-signed-images
spec:
  images:
  - glob: "myregistry.io/myapp:*"
  authorities:
  - keyless:
      url: https://fulcio.sigstore.dev
      identities:
      - issuer: https://token.actions.githubusercontent.com
        subject: "https://github.com/my-org/my-repo/.github/workflows/build.yml@refs/heads/main"

Mise à jour

curl -Lo cosign https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign && sudo mv cosign /usr/local/bin/
cosign version

Troubleshooting

# Vérifier qu'une image a une signature
cosign tree myregistry.io/myapp:v1.0
# Affiche les signatures et attestations attachées

# Debug de la vérification
cosign verify --key cosign.pub myregistry.io/myapp:v1.0 --verbose 2>&1

# Vérifier sans Rekor (offline)
cosign verify --key cosign.pub --offline myregistry.io/myapp:v1.0

Signature non trouvée

# Vérifier que la signature est bien dans le registry
cosign tree myregistry.io/myapp:v1.0
# Doit afficher "Signatures for an image tag"

# Vérifier les droits sur le registry (push des signatures)
# La signature est pushée dans myregistry.io/myapp:sha256-<digest>.sig

Commandes utiles

cosign generate-key-pair                      # Générer une paire de clés
cosign sign --key cosign.key <image>          # Signer une image
cosign verify --key cosign.pub <image>        # Vérifier la signature
cosign sign --yes <image>                     # Signer en mode keyless
cosign tree <image>                           # Voir signatures + attestations
cosign attest --key cosign.key --predicate <file> --type spdx <image>
cosign verify-attestation --key cosign.pub --type spdx <image>
cosign download signature <image>             # Télécharger la signature brute

Ressources

Newsletter · 2 000+ abonnés

Reste au courant de ce qui bouge en prod

RudeOps veille devops hebdo, droit au but.

Gratuit · Sans spam · Désinscription en un clic