Aller au contenu principal

Cosign pour signer vos conteneurs OCI

· 7 minutes de lecture
Stéphane ROBERT
Consultant DevOps

Dans le billet précédent, j'avais introduit la notion de sécurisation de la chaine d'approvisionnement logiciel et surtout pourquoi il est important de la mettre en place. Ce billet parle d'une première solution permettant de signer des conteneurs OCI avec Cosign. L'objectif est d'intégrer ces outils dans une CI Gitlab.

Introduction

Soutenu par le l'OpenSSF (Open Source Security Foundation), le projet Sigstore fonctionne comme un service de bien public à but non lucratif.

L'objectif de Sigstore est de fournir aux développeurs les moyens de valider que les logiciels qu’ils utilisent sont exactement ceux attendus. Cette validation se fait via l'utilisation de signatures numériques codées et des technologies de journal de transparence.

Sigstore fournit donc une suite d'outils dont :

  • Cosign pour la signature d’artefacts logiciels,
  • l’autorité de certification Fulcio,
  • le journal de confiance (ou transparence) Rekor,
  • Gitsign pour la signature des Git commits.

Ces outils peuvent être utilisés indépendamment ! Dans ce billet, nous utiliserons seulement Cosign. Dans un prochain billet, nous verrons comment héberger un service de signature.

Installation de Cosign

Comme d'habitude, nous allons utiliser asdf pour installer Cosign.

asdf plugin add cosign
asdf install cosign latest
asdf global cosign latest

Dans le cas de l'utilisation de cet outil dans une CI je vous conseille d'utiliser l'image fournie par Chainguard.

docker run --rm cgr.dev/chainguard/cosign version

Signatures de nos artefacts

Maintenant que nous avons installé Cosign, je vais vous montrer comment l'utiliser conjointement avec trivy pour stocker et signer la SBOM, le scan de vulnérabilité et toutes autres informations dans la registry OCI.

Création des clés

Comme dit plus ce n'est pas la meilleure des pratiques, mais tant que nous n'aurons pas installé Fulcio nous l'utiliserons.

cosign generate-key-pair
Enter password for private key:
Enter password for private key again:
Private key written to cosign.key
Public key written to cosign.pub

Je n'ai pas mis de paraphrase, ce n'est pas bien ! Mais c'est pour simplifier la démo.

Création de l'image

Je vais construire une image utilisant une image wolfi nginx dans lequel je copie un simple fichier index.html. Je vais utiliser la container registry de Gitlab qui est compatible OCI.

J'ai créé un projet sur gitlab et je clone le projet :

git clone git@gitlab.com:dockerfiles6/images/demo-cosign.git
cd demo-cosign
git switch --create main

Le fichier index.html :

<h1>Test Cosign</h1>

Le Dockerfile :

FROM cgr.dev/chainguard/nginx as deploy

# Copy what we've installed/built from production
COPY index.html /usr/share/nginx/html/

On construit, puis on pousse l'image dans la registry Gitlab. On récupère le SHA pour le stocker dans une variable $IMAGE (nécessaire aux commandes cosign):

docker build -t registry.gitlab.com/dockerfiles6/images/demo-cosign:latest .
docker push registry.gitlab.com/dockerfiles6/images/demo-cosign:latest .

docker login registry.gitlab.com -u xxxxxx -p xxxxxx
Login Succeeded

export IMAGE=`docker inspect --format='{{index .RepoDigests 0}}' registry.gitlab.com/dockerfiles6/images/demo-cosign:latest`

Signature de l'image

Maintenant que notre image est stockée dans la registry, nous allons la signer en ne stockant rien dans rekor.

cosign sign --key cosign.key --tlog-upload=false $IMAGE

Enter password for private key:
Pushing signature to: registry.gitlab.com/dockerfiles6/images/demo-cosign

Vous avez remarqué la signature est poussée directement dans la registry. Une petite vérification sur le site gitlab.

Et oui, nous avons bien stocké la signature.

Récupération des informations sur la signature

La commande triangulate permet d'obtenir l'adresse de l'image contentant la signature :

cosign triangulate registry.gitlab.com/dockerfiles6/images/demo-cosign@sha256:708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42
registry.gitlab.com/dockerfiles6/images/demo-cosign:sha256-708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42.sig

Pour en afficher le contenu je vous conseille d'utiliser crane (installé avec asdf) :

crane manifest registry.gitlab.com/dockerfiles6/images/demo-cosign:sha256-708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42.sig |jq -r .

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 248,
    "digest": "sha256:c7b780b59727e119501961e1b36bb8c4f8886055a9cbfccb2f02eb43dac7e48d"
  },
  "layers": [
    {
      "mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
      "size": 267,
      "digest": "sha256:70b7b4faa03fa820f8411fe34bd3da5421b97dc3ef0aa469f70f5a769716dfb9",
      "annotations": {
        "dev.cosignproject.cosign/signature": "MEUCIFMBHH8o0EWNXEqLey4CeuJFQaUozrul6OE2zNjmTT3UAiEA9yBL38wkB5VHWeBeYxz4//0kNLUZay3vEG3PIZzuPeg=",
        "dev.sigstore.cosign/bundle": "{\"SignedEntryTimestamp\":\"MEYCIQDhKL3G5/B2J9kEEOM3SNB0/hPAxaU+v16wj2k3et8arwIhAO47k68xkb/AE7E1ARISv7jbeYw771weQlyJDk5KlpUl\",\"Payload\":{\"body\":\"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI3MGI3YjRmYWEwM2ZhODIwZjg0MTFmZTM0YmQzZGE1NDIxYjk3ZGMzZWYwYWE0NjlmNzBmNWE3Njk3MTZkZmI5In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJRk1CSEg4bzBFV05YRXFMZXk0Q2V1SkZRYVVvenJ1bDZPRTJ6TmptVFQzVUFpRUE5eUJMMzh3a0I1VkhXZUJlWXh6NC8vMGtOTFVaYXkzdkVHM1BJWnp1UGVnPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGVlV0SWRXNXNTR015YTFOeFIyOVpNalJMZG1kWGVFbENNVUZYY1FwV2JFUk1kMnRQV2pZeGEyY3laVW92ZEU1cWRGZFZiVkJzTlc1TlJsRlZaeTlxWkdOdGNDODNTbHB2Y1VGMWNVMVJlVGt3T0dNeU56bFJQVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=\",\"integratedTime\":1692622355,\"logIndex\":32118650,\"logID\":\"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d\"}}"
      }
    }
  ]
}

Vérification de la signature de l'image

Nous allons demander si l'image stockée dans la registry est bien celle qui a été signée.

cosign verify --key cosign.pub --insecure-ignore-tlog=true $IMAGE
WARNING: Skipping tlog verification is an insecure practice that lacks of transparency and auditability verification for the signature.

Verification for registry.gitlab.com/dockerfiles6/images/demo-cosign@sha256:708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key

[{"critical":{"identity":{"docker-reference":"registry.gitlab.com/dockerfiles6/images/demo-cosign"},"image":{"docker-manifest-digest":"sha256:708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42"},"type":"cosign container image signature"},"optional":{"Bundle":{"SignedEntryTimestamp":"MEYCIQDhKL3G5/B2J9kEEOM3SNB0/hPAxaU+v16wj2k3et8arwIhAO47k68xkb/AE7E1ARISv7jbeYw771weQlyJDk5KlpUl","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI3MGI3YjRmYWEwM2ZhODIwZjg0MTFmZTM0YmQzZGE1NDIxYjk3ZGMzZWYwYWE0NjlmNzBmNWE3Njk3MTZkZmI5In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJRk1CSEg4bzBFV05YRXFMZXk0Q2V1SkZRYVVvenJ1bDZPRTJ6TmptVFQzVUFpRUE5eUJMMzh3a0I1VkhXZUJlWXh6NC8vMGtOTFVaYXkzdkVHM1BJWnp1UGVnPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGVlV0SWRXNXNTR015YTFOeFIyOVpNalJMZG1kWGVFbENNVUZYY1FwV2JFUk1kMnRQV2pZeGEyY3laVW92ZEU1cWRGZFZiVkJzTlc1TlJsRlZaeTlxWkdOdGNDODNTbHB2Y1VGMWNVMVJlVGt3T0dNeU56bFJQVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=","integratedTime":1692622355,"logIndex":32118650,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}}}}]

Cela fonctionne ! En testant avec une autre clé publique :

cd /tmp
cosign generate-key-pair

Enter password for private key:
Enter password for private key again:
Private key written to cosign.key
Public key written to cosign.pub

cosign verify --key cosign.pub --insecure-ignore-tlog=true $IMAGE
WARNING: Skipping tlog verification is an insecure practice that lacks of transparency and auditability verification for the signature.
Error: no matching signatures: invalid signature when validating ASN.1 encoded signature
main.go:69: error during command execution: no matching signatures: invalid signature when validating ASN.1 encoded signature

Attachement de la SBOM

Nous allons générer la nomenclature de l'image pour la stocker avec trivy :

trivy i --format cosign-vuln $IMAGE > image.sbom

2023-08-21T15:10:19.697+0200    INFO    Need to update DB
2023-08-21T15:10:19.697+0200    INFO    DB Repository: ghcr.io/aquasecurity/trivy-db
2023-08-21T15:10:19.697+0200    INFO    Downloading DB...
39.00 MiB / 39.00 MiB [-----------------------------------------------------------------------------------------------------------------------------------------------------------------] 100.00% 13.24 MiB p/s 3.1s
2023-08-21T15:10:23.811+0200    INFO    Vulnerability scanning is enabled
2023-08-21T15:10:23.811+0200    INFO    Secret scanning is enabled
2023-08-21T15:10:23.811+0200    INFO    If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2023-08-21T15:10:23.811+0200    INFO    Please see also https://aquasecurity.github.io/trivy/v0.43/docs/scanner/secret/#recommendation for faster secret detection
2023-08-21T15:10:24.036+0200    INFO    Detected OS: wolfi
2023-08-21T15:10:24.036+0200    INFO    Detecting Wolfi vulnerabilities...
2023-08-21T15:10:24.037+0200    INFO    Number of language-specific files: 0

Reste plus qu'à la joindre à notre image dans la registry avec cosign :

cosign attach sbom --sbom image.sbom $IMAGE
Enter password for private key:
Using payload from: image.sbom

Un petit tout sur le site de Gitlab.

On retrouve bien l'attestation.

Vérification de l'attestation

On va utiliser la commande verify-attestion :

cosign verify-attestation --key cosign.pub --insecure-ignore-tlog=true $IMAGE

WARNING: Skipping tlog verification is an insecure practice that lacks of transparency and auditability verification for the attestation.

Verification for registry.gitlab.com/dockerfiles6/images/demo-cosign@sha256:708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
{"payloadType":"application/vnd.in-toto+json","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL2Nvc2lnbi5zaWdzdG9yZS5kZXYvYXR0ZXN0YXRpb24vdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoicmVnaXN0cnkuZ2l0bGFiLmNvbS9kb2NrZXJmaWxlczYvaW1hZ2VzL2RlbW8tY29zaWduIiwiZGlnZXN0Ijp7InNoYTI1NiI6IjcwOGU0ZTdhMjljMzE2ZmM1MTY1MDQzN2IzNjRiOTMyYjMwZjUwMGM5MDE0ZDU4NjA3M2VhMjZmODE5YjRlNDIifX1dLCJwcmVkaWNhdGUiOnsiRGF0YSI6IntcbiAgXCJpbnZvY2F0aW9uXCI6IHtcbiAgICBcInBhcmFtZXRlcnNcIjogbnVsbCxcbiAgICBcInVyaVwiOiBcIlwiLFxuICAgIFwiZXZlbnRfaWRcIjogXCJcIixcbiAgICBcImJ1aWxkZXIuaWRcIjogXCJcIlxuICB9LFxuICBcInNjYW5uZXJcIjoge1xuICAgIFwidXJpXCI6IFwicGtnOmdpdGh1Yi9hcXVhc2VjdXJpdHkvdHJpdnlAMC40My4xXCIsXG4gICAgXCJ2ZXJzaW9uXCI6IFwiMC40My4xXCIsXG4gICAgXCJkYlwiOiB7XG4gICAgICBcInVyaVwiOiBcIlwiLFxuICAgICAgXCJ2ZXJzaW9uXCI6IFwiXCJcbiAgICB9LFxuICAgIFwicmVzdWx0XCI6IHtcbiAgICAgIFwiU2NoZW1hVmVyc2lvblwiOiAyLFxuICAgICAgXCJBcnRpZmFjdE5hbWVcIjogXCJyZWdpc3RyeS5naXRsYWIuY29tL2RvY2tlcmZpbGVzNi9pbWFnZXMvZGVtby1jb3NpZ25Ac2hhMjU2OjcwOGU0ZTdhMjljMzE2ZmM1MTY1MDQzN2IzNjRiOTMyYjMwZjUwMGM5MDE0ZDU4NjA3M2VhMjZmODE5YjRlNDJcIixcbiAgICAgIFwiQXJ0aWZhY3RUeXBlXCI6IFwiY29udGFpbmVyX2ltYWdlXCIsXG4gICAgICBcIk1ldGFkYXRhXCI6IHtcbiAgICAgICAgXCJPU1wiOiB7XG4gICAgICAgICAgXCJGYW1pbHlcIjogXCJ3b2xmaVwiLFxuICAgICAgICAgIFwiTmFtZVwiOiBcIjIwMjMwMjAxXCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJJbWFnZUlEXCI6IFwic2hhMjU2OjdiMWY2MjllN2E2YzM0OGE5Njc2Y2Q3ZWJlYmI4MDU2NzRkYjMyYjgwNTQ5NGZjMDM3ZWUzZWM3ZWY2OWEwNWJcIixcbiAgICAgICAgXCJEaWZmSURzXCI6IFtcbiAgICAgICAgICBcInNoYTI1Njo0YmQ3NGM0NmJlYmFhOGJkZWEyZmY0NDQ3Yjc0YmJkODI5NDQ3MTFhZWRiOGZiZGE4Yjc0YzE3NzIxN2RiODcwXCIsXG4gICAgICAgICAgXCJzaGEyNTY6YzBjMjdmNWFkOTQzMjRiNzc4NWYxMjAzMzQ2NDQ5MDBlMDc2ZmE4NjEwNTExYzBjMzk3ZGMyNGNiMjU2YjIwYVwiXG4gICAgICAgIF0sXG4gICAgICAgIFwiUmVwb1RhZ3NcIjogW1xuICAgICAgICAgIFwicmVnaXN0cnkuZ2l0bGFiLmNvbS9kb2NrZXJmaWxlczYvaW1hZ2VzL2RlbW8tY29zaWduOmxhdGVzdFwiXG4gICAgICAgIF0sXG4gICAgICAgIFwiUmVwb0RpZ2VzdHNcIjogW1xuICAgICAgICAgIFwicmVnaXN0cnkuZ2l0bGFiLmNvbS9kb2NrZXJmaWxlczYvaW1hZ2VzL2RlbW8tY29zaWduQHNoYTI1Njo3MDhlNGU3YTI5YzMxNmZjNTE2NTA0MzdiMzY0YjkzMmIzMGY1MDBjOTAxNGQ1ODYwNzNlYTI2ZjgxOWI0ZTQyXCJcbiAgICAgICAgXSxcbiAgICAgICAgXCJJbWFnZUNvbmZpZ1wiOiB7XG4gICAgICAgICAgXCJhcmNoaXRlY3R1cmVcIjogXCJhbWQ2NFwiLFxuICAgICAgICAgIFwiYXV0aG9yXCI6IFwiZ2l0aHViLmNvbS9jaGFpbmd1YXJkLWRldi9hcGtvXCIsXG4gICAgICAgICAgXCJjcmVhdGVkXCI6IFwiMjAyMy0wOC0yMVQxNDozNjo0OS42NTE1MTkxNiswMjowMFwiLFxuICAgICAgICAgIFwiaGlzdG9yeVwiOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIFwiY3JlYXRlZFwiOiBcIjIwMjMtMDgtMDNUMDY6MjM6MjlaXCIsXG4gICAgICAgICAgICAgIFwiY3JlYXRlZF9ieVwiOiBcImFwa29cIixcbiAgICAgICAgICAgICAgXCJjb21tZW50XCI6IFwiVGhpcyBpcyBhbiBhcGtvIHNpbmdsZS1sYXllciBpbWFnZVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBcImNyZWF0ZWRcIjogXCIyMDIzLTA4LTIxVDEyOjM2OjQ5WlwiLFxuICAgICAgICAgICAgICBcImNyZWF0ZWRfYnlcIjogXCJDT1BZIGluZGV4Lmh0bWwgL3Vzci9zaGFyZS9uZ2lueC9odG1sLyAjIGJ1aWxka2l0XCIsXG4gICAgICAgICAgICAgIFwiY29tbWVudFwiOiBcImJ1aWxka2l0LmRvY2tlcmZpbGUudjBcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIF0sXG4gICAgICAgICAgXCJvc1wiOiBcImxpbnV4XCIsXG4gICAgICAgICAgXCJyb290ZnNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwibGF5ZXJzXCIsXG4gICAgICAgICAgICBcImRpZmZfaWRzXCI6IFtcbiAgICAgICAgICAgICAgXCJzaGEyNTY6NGJkNzRjNDZiZWJhYThiZGVhMmZmNDQ0N2I3NGJiZDgyOTQ0NzExYWVkYjhmYmRhOGI3NGMxNzcyMTdkYjg3MFwiLFxuICAgICAgICAgICAgICBcInNoYTI1NjpjMGMyN2Y1YWQ5NDMyNGI3Nzg1ZjEyMDMzNDY0NDkwMGUwNzZmYTg2MTA1MTFjMGMzOTdkYzI0Y2IyNTZiMjBhXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY29uZmlnXCI6IHtcbiAgICAgICAgICAgIFwiQ21kXCI6IFtcbiAgICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgICBcIi9ldGMvbmdpbngvbmdpbnguY29uZlwiLFxuICAgICAgICAgICAgICBcIi1lXCIsXG4gICAgICAgICAgICAgIFwiL2Rldi9zdGRlcnJcIixcbiAgICAgICAgICAgICAgXCItZ1wiLFxuICAgICAgICAgICAgICBcImRhZW1vbiBvZmY7XCJcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBcIkVudHJ5cG9pbnRcIjogW1xuICAgICAgICAgICAgICBcIi91c3Ivc2Jpbi9uZ2lueFwiXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgXCJFbnZcIjogW1xuICAgICAgICAgICAgICBcIlBBVEg9L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluXCIsXG4gICAgICAgICAgICAgIFwiU1NMX0NFUlRfRklMRT0vZXRjL3NzbC9jZXJ0cy9jYS1jZXJ0aWZpY2F0ZXMuY3J0XCJcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBcIlVzZXJcIjogXCI2NTUzMlwiLFxuICAgICAgICAgICAgXCJTdG9wU2lnbmFsXCI6IFwiU0lHUVVJVFwiXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgXCJSZXN1bHRzXCI6IFtcbiAgICAgICAge1xuICAgICAgICAgIFwiVGFyZ2V0XCI6IFwicmVnaXN0cnkuZ2l0bGFiLmNvbS9kb2NrZXJmaWxlczYvaW1hZ2VzL2RlbW8tY29zaWduQHNoYTI1Njo3MDhlNGU3YTI5YzMxNmZjNTE2NTA0MzdiMzY0YjkzMmIzMGY1MDBjOTAxNGQ1ODYwNzNlYTI2ZjgxOWI0ZTQyICh3b2xmaSAyMDIzMDIwMSlcIixcbiAgICAgICAgICBcIkNsYXNzXCI6IFwib3MtcGtnc1wiLFxuICAgICAgICAgIFwiVHlwZVwiOiBcIndvbGZpXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH1cbiAgfSxcbiAgXCJtZXRhZGF0YVwiOiB7XG4gICAgXCJzY2FuU3RhcnRlZE9uXCI6IFwiMjAyMy0wOC0yMVQxNToyMDowNi45MzE4MDI3NjErMDI6MDBcIixcbiAgICBcInNjYW5GaW5pc2hlZE9uXCI6IFwiMjAyMy0wOC0yMVQxNToyMDowNi45MzE4MDI3NjErMDI6MDBcIlxuICB9XG59IiwiVGltZXN0YW1wIjoiMjAyMy0wOC0yMVQxMzoyMDo1OVoifX0=","signatures":[{"keyid":"","sig":"MEUCIChqDJdq7epCXd7kpeFwefRJkxZXF3tbc5aLxWUl286mAiEAzAh871hfGDNuaEQAMI5rydgLP0lss50dhmAcbHld4J8="}]}

Pour visualiser le contenu de la payload un petit coup de jq :

cosign verify-attestation --key cosign.pub --insecure-ignore-tlog=true $IMAGE | jq -r .payload | base64 -d | jq .

WARNING: Skipping tlog verification is an insecure practice that lacks of transparency and auditability verification for the attestation.

Verification for registry.gitlab.com/dockerfiles6/images/demo-cosign@sha256:708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
{
  "_type": "https://in-toto.io/Statement/v0.1",
  "predicateType": "https://cosign.sigstore.dev/attestation/v1",
  "subject": [
    {
      "name": "registry.gitlab.com/dockerfiles6/images/demo-cosign",
      "digest": {
        "sha256": "708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42"
      }
    }
  ],
  "predicate": {
    "Data": "{\n  \"invocation\": {\n    \"parameters\": null,\n    \"uri\": \"\",\n    \"event_id\": \"\",\n    \"builder.id\": \"\"\n  },\n  \"scanner\": {\n    \"uri\": \"pkg:github/aquasecurity/trivy@0.43.1\",\n    \"version\": \"0.43.1\",\n    \"db\": {\n      \"uri\": \"\",\n      \"version\": \"\"\n    },\n    \"result\": {\n      \"SchemaVersion\": 2,\n      \"ArtifactName\": \"registry.gitlab.com/dockerfiles6/images/demo-cosign@sha256:708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42\",\n      \"ArtifactType\": \"container_image\",\n      \"Metadata\": {\n        \"OS\": {\n          \"Family\": \"wolfi\",\n          \"Name\": \"20230201\"\n        },\n        \"ImageID\": \"sha256:7b1f629e7a6c348a9676cd7ebebb805674db32b805494fc037ee3ec7ef69a05b\",\n        \"DiffIDs\": [\n          \"sha256:4bd74c46bebaa8bdea2ff4447b74bbd82944711aedb8fbda8b74c177217db870\",\n          \"sha256:c0c27f5ad94324b7785f120334644900e076fa8610511c0c397dc24cb256b20a\"\n        ],\n        \"RepoTags\": [\n          \"registry.gitlab.com/dockerfiles6/images/demo-cosign:latest\"\n        ],\n        \"RepoDigests\": [\n          \"registry.gitlab.com/dockerfiles6/images/demo-cosign@sha256:708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42\"\n        ],\n        \"ImageConfig\": {\n          \"architecture\": \"amd64\",\n          \"author\": \"github.com/chainguard-dev/apko\",\n          \"created\": \"2023-08-21T14:36:49.65151916+02:00\",\n          \"history\": [\n            {\n              \"created\": \"2023-08-03T06:23:29Z\",\n              \"created_by\": \"apko\",\n              \"comment\": \"This is an apko single-layer image\"\n            },\n            {\n              \"created\": \"2023-08-21T12:36:49Z\",\n              \"created_by\": \"COPY index.html /usr/share/nginx/html/ # buildkit\",\n              \"comment\": \"buildkit.dockerfile.v0\"\n            }\n          ],\n          \"os\": \"linux\",\n          \"rootfs\": {\n            \"type\": \"layers\",\n            \"diff_ids\": [\n              \"sha256:4bd74c46bebaa8bdea2ff4447b74bbd82944711aedb8fbda8b74c177217db870\",\n              \"sha256:c0c27f5ad94324b7785f120334644900e076fa8610511c0c397dc24cb256b20a\"\n            ]\n          },\n          \"config\": {\n            \"Cmd\": [\n              \"-c\",\n              \"/etc/nginx/nginx.conf\",\n              \"-e\",\n              \"/dev/stderr\",\n              \"-g\",\n              \"daemon off;\"\n            ],\n            \"Entrypoint\": [\n              \"/usr/sbin/nginx\"\n            ],\n            \"Env\": [\n              \"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\n              \"SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt\"\n            ],\n            \"User\": \"65532\",\n            \"StopSignal\": \"SIGQUIT\"\n          }\n        }\n      },\n      \"Results\": [\n        {\n          \"Target\": \"registry.gitlab.com/dockerfiles6/images/demo-cosign@sha256:708e4e7a29c316fc51650437b364b932b30f500c9014d586073ea26f819b4e42 (wolfi 20230201)\",\n          \"Class\": \"os-pkgs\",\n          \"Type\": \"wolfi\"\n        }\n      ]\n    }\n  },\n  \"metadata\": {\n    \"scanStartedOn\": \"2023-08-21T15:20:06.931802761+02:00\",\n    \"scanFinishedOn\": \"2023-08-21T15:20:06.931802761+02:00\"\n  }\n}",
    "Timestamp": "2023-08-21T13:20:59Z"
  }
}

Plus loin

Avant tout, je tiens à remercier leila qui m'a fourni pas mal d'informations pour élaborer ce billet. Comme dit plus haut cette solution est incomplète sans les autres outils. Nous verrons donc dans un prochain billet comment installer et utiliser rekor, puis fulcio.

Par la suite, nous verrons aussi comment contrôler les images avec kyverno avant qu'elles soient déployées dans un cluster kubernetes.