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
| Composant | Valeur |
|---|---|
| Mode keyless | OIDC (GitHub Actions, GKE WI, etc.) + Rekor + Fulcio |
| Mode clé statique | keypair .key / .pub, ou secret Kubernetes |
| Mode KMS | AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault |
| Stockage signatures | OCI registry (même repo que l'image, tag sha256-<digest>.sig) |
| Attestations | SBOM, SLSA Provenance, custom predicates |
Concepts clés
| Concept | Description |
|---|---|
| Signature OCI | Stockée dans le même registry que l'image, pas de sidecar |
| Keyless | OIDC - identité CI/CD (GitHub Actions, etc.) remplace la clé privée |
| Rekor | Journal de transparence immuable - enregistre toutes les signatures |
| Fulcio | CA éphémère - émet un certificat court (20 min) lié à l'identité OIDC |
| Attestation | Métadonnées signées attachées à l'image (SBOM, provenance…) |
| Bundle | Signature + certificat + entrée Rekor (vérifiable hors ligne) |
Prérequis
| Ressource | Valeur |
|---|---|
| Registry OCI | Compatible OCI (Docker Hub, ghcr.io, ECR, GCR, ACR, Harbor…) |
| Clé ou OIDC | Keypair, 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
- Documentation Sigstore/Cosign : https://docs.sigstore.dev/cosign/overview/
- GitHub Cosign : https://github.com/sigstore/cosign
- Releases : https://github.com/sigstore/cosign/releases
- Rekor (transparency log) : https://rekor.sigstore.dev
- Policy Controller Sigstore : https://docs.sigstore.dev/policy-controller/overview/
- Intégration Kyverno + Cosign : https://kyverno.io/docs/writing-policies/verify-images/