DevOps - Héberger son sigstore privé pour signer ses artefacts
Publié le : 22 août 2023 | Mis à jour le : 31 août 2023Table des matières
Hier, je vous ai présenté comment utiliser cosign
pour signer et vérifier
vos images Docker. Par contre, j’avais désactivé le stockage des preuves de
signature dans le serveur de transparence rekor
publique. Aujourd’hui, je vous
propose de voir comment avoir un serveur Rekor
self-hosted. Attention au
moment de l’écriture de ce billet cette fonctionnalité est au status
Experimental
.
Installation de kind
Pour tester rekor
, j’ai choisi de le faire sur une instance de cluster kubernetes
créé avec kind
. Pour installer kind
, rien de plus facile avec asdf
.
asdf plugin add kind 13:49:33
asdf install kind latest
asdf global kind latest
Configuration kind pour ajouter un serveur d’ingress
Pour exposer mon service, je vais utiliser le controleur d’ingress nginx qui
peut être déployé dans kind
. Pour l’installer sur notre cluster kind
, il faut
créer un fichier de configuration kind.config
:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
On peut créer le cluster :
kind create cluster --config kind.config
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
Au bout de quelques instants, vous devriez avoir un pod
ingress-nginx-controller-xxxxxxxxx-xxxx
dans le namespace
ingress-nginx
.
> kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-5mbz8 0/1 Completed 0 5h5m
ingress-nginx-admission-patch-gsj58 0/1 Completed 1 5h5m
ingress-nginx-controller-6b7f45576b-qxfxc 1/1 Running 0 5h5m
Déploiement de la suite sigstore
Bon reste à déployer toute la suite Sigstore. Et bonne nouvelle, on a un chart
Helm
à notre disposition.
helm repo add sigstore https://sigstore.github.io/helm-charts
helm repo update
Avant de l’utiliser, nous allons créer le fichier de values.
helm show values sigstore/scaffold > values.yaml
Editer le fichier et activer les composants : fulcio, ctlog, tuf et
CopySecretjob : enabled: true
.
Un exemple de fichier de values:
---
# Fulcio
fulcio:
enabled: true
namespace:
name: fulcio-system
create: true
forceNamespace: fulcio-system
createcerts:
fullnameOverride: fulcio-createcerts
ctlog:
enabled: false
createctconfig:
logPrefix: sigstorescaffolding
server:
fullnameOverride: fulcio-server
ingress:
http:
annotations:
cert-manager.io/cluster-issuer: "vault-issuer"
className: nginx
hosts:
- host: fulcio.robert.local
path: /
tls:
- secretName: fulcio-tls
hosts:
- fulcio.robert.local
config:
contents:
OIDCIssuers:
https://oauth2.sigstore.dev/auth:
IssuerURL: https://oauth2.sigstore.dev/auth
ClientID: sigstore
Type: email
IssuerClaim: $.federated_claims.connector_id
# CTLog
ctlog:
enabled: true
namespace:
name: ctlog-system
create: true
forceNamespace: ctlog-system
fullnameOverride: ctlog
createcerts:
fullnameOverride: ctlog-createcerts
createtree:
fullnameOverride: ctlog-createtree
displayName: ctlog-tree
# Rekor
rekor:
enabled: true
namespace:
name: rekor-system
create: true
forceNamespace: rekor-system
fullnameOverride: rekor
server:
fullnameOverride: rekor-server
ingress:
className: nginx
annotations:
cert-manager.io/cluster-issuer: "vault-issuer"
hosts:
- host: rekor.robert.local
path: /
tls:
- secretName: rekor-tls
hosts:
- rekor.robert.local
redis:
fullnameOverride: rekor-redis
trillian:
enabled: false
# Trillian
trillian:
enabled: true
namespace:
name: trillian-system
create: true
forceNamespace: trillian-system
fullnameOverride: trillian
logServer:
name: trillian-logserver
fullnameOverride: trillian-logserver
portHTTP: 8090
portRPC: 8091
logSigner:
name: trillian-logsigner
fullnameOverride: trillian-logsigner
mysql:
fullnameOverride: trillian-mysql
tuf:
enabled: true
namespace:
name: tuf-system
create: true
forceNamespace: tuf-system
fullnameOverride: tuf
ingress:
className: nginx
annotations:
cert-manager.io/cluster-issuer: "vault-issuer"
http:
hosts:
- host: tuf.robert.local
path: /
tls:
- secretName: tuf-tls
hosts:
- tuf.robert.local
secrets:
rekor:
name: rekor-public-key
path: rekor-pubkey
fulcio:
name: fulcio-server-secret
path: fulcio-cert
ctlog:
name: ctlog-public-key
path: ctlog-pubkey
copySecretJob:
enabled: true
name: copy-secrets-job
registry: docker.io
repository: alpine/k8s
version: sha256:fb0d2db81fb0f98abb1adf5246d6f0f4d19f34031afe4759cb7ad8e2eb8d2c01
imagePullPolicy: IfNotPresent
serviceaccount: tuf-secret-copy-job
backoffLimit: 6
tsa:
enabled: false
namespace:
name: tsa-system
create: true
forceNamespace: tsa-system
server:
fullnameOverride: tsa-server
Nous allons générer les certificats de rekor, fulcio et tuf avec mkcert:
for service_name in rekor fulcio tuf; do
mkcert ${service_name}.robert.local localhost 127.0.0.1 ::1
done
On déploie la stack :
helm upgrade -i scaffold sigstore/scaffold -n sigstore --create-namespace --values scaffold.values.yaml
Release "scaffold" does not exist. Installing it now.
NAME: scaffold
LAST DEPLOYED: Thu Aug 31 08:38:28 2023
NAMESPACE: sigstore
STATUS: deployed
REVISION: 1
TEST SUITE: None
Au bout de quelques minutes, vous trouverez en fait plusieurs composants :
- Le serveur
rekor
. - Un serveur
redis
. - Un serveur de bdd
mysql
. - Un serveur de log
trillian
, produit sigstore également. - Un serveur
ctflog
- Un serveur
fulcio
- Et quelques jobs dont certains en erreur mais c’est normal !
Attendez que tout soit démarré !
kubectcl get pod -A --watch
NAMESPACE NAME READY STATUS RESTARTS AGE
ctlog-system ctlog-56fbc5595f-8trzt 1/1 Running 0 4m45s
ctlog-system ctlog-createtree-7vdgs 0/1 Completed 0 4m45s
ctlog-system scaffold-ctlog-createctconfig-chhmb 0/1 Completed 0 4m45s
fulcio-system fulcio-createcerts-mrpkd 0/1 Completed 0 4m45s
fulcio-system fulcio-server-7cd549dc9b-2hw4f 1/1 Running 0 4m45s
ingress-nginx ingress-nginx-admission-create-n64qz 0/1 Completed 0 9m56s
ingress-nginx ingress-nginx-admission-patch-k8tcv 0/1 Completed 0 9m56s
ingress-nginx ingress-nginx-controller-6b7f45576b-pbxzb 1/1 Running 0 9m56s
kube-system coredns-5d78c9869d-659ns 1/1 Running 0 11m
kube-system coredns-5d78c9869d-pgh42 1/1 Running 0 11m
kube-system etcd-kind-control-plane 1/1 Running 0 12m
kube-system kindnet-v4x9k 1/1 Running 0 11m
kube-system kube-apiserver-kind-control-plane 1/1 Running 0 12m
kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 12m
kube-system kube-proxy-875cf 1/1 Running 0 11m
kube-system kube-scheduler-kind-control-plane 1/1 Running 0 12m
local-path-storage local-path-provisioner-6bc4bddd6b-4tvd7 1/1 Running 0 11m
rekor-system rekor-redis-5d665cddb8-mrsh9 1/1 Running 0 4m45s
rekor-system rekor-server-75c967c64-p4jc2 1/1 Running 0 4m45s
rekor-system scaffold-rekor-createtree-vt8wb 0/1 Completed 0 4m45s
trillian-system scaffold-trillian-createdb-22t9s 0/1 Error 0 4m45s
trillian-system scaffold-trillian-createdb-9jwgm 0/1 Completed 0 3m55s
trillian-system trillian-logserver-68bf4cbbc8-jd52q 1/1 Running 0 4m45s
trillian-system trillian-logsigner-754cd6894-bk6hr 1/1 Running 0 4m45s
trillian-system trillian-mysql-64dbf8864-cngn2 1/1 Running 0 4m45s
tuf-system copy-secrets-job-fzv89 0/3 Completed 0 4m45s
tuf-system scaffold-tuf-tuf-7fd95b87cd-gzrwv 1/1 Running 0 4m45s
On crée les secrets stockant les certificats :
for service_name in rekor fulcio tuf; do
kubectl create secret -n ${service_name}-system tls ${service_name}-tls --key=${service_name}.robert.local+3-key.pem --cert=${service_name}.robert.local+3.pem
done
secret/rekor-tls created
secret/fulcio-tls created
secret/tuf-tls created
On récupère l’adresse du container :
docker container inspect kind-control-plane \
--format '{{ .NetworkSettings.Networks.kind.IPAddress }}'
172.19.0.2
On édite le fichier /etc/hosts
:
vi /etc/hosts
Ajoutez cette ligne :
172.19.0.2 rekor.robert.local
172.19.0.2 fulcio.robert.local
172.19.0.2 tuf.robert.local
On teste que le serveur rekor
est accessible et que le certificat est accepté:
curl https://rekor.robert.local
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta property="og:title" content="sigstore" />
<meta property="og:description" content="A non-profit, public good software signing & transparency service" />
<meta property="og:type" content="website" />
<meta property="og:url" content="/" />
<meta name="description" content="A non-profit, public good software signing & transparency service" />
<meta charset="utf-8">
<title>sigstore</title>
<link href="https://fonts.googleapis.com/css?family=Catamaran:400,600" rel="stylesheet">
</head>
<body>
<h1>
Rekor Server
</h1>
<h2>
A non-profit, public good software signing & transparency service.
<p>To learn more visit <a href="https://sigstore.dev">Sigstore project page</a></p>
</h2>
<p>Currently storing <span id="count">some</span> items.</p>
<footer>
<p>Copyright © sigstore a Series of LF Projects, LLC For web site terms of use, trademark policy and general project
policies please see <a href="https://lfprojects.org">https://lfprojects.org</a>.</p>
</footer>
<script type="text/javascript">
const url = '/api/v1/log/';
function update() {
fetch(url, {headers: {'Accept': 'application/json'}}).then((resp) => {
resp.json().then((j) => {
let count = j.treeSize;
document.getElementById('count').innerText = count;
}).catch(console.error);
}).catch(console.error);
}
update(); // Update immediately on page load.
setInterval(update, 10000); // Update the counter every 10 seconds.
</script>
</body>
</html>
Il faut maintenant initialisé le serveur tuf :
kubectl -n tuf-system get secrets tuf-root -ojsonpath='{.data.root}' | base64 -d > root.json
Vous devriez obtenir le fichier root.json avec ce contenu :
cat root.json
{
"signed": {
"_type": "root",
"spec_version": "1.0",
"version": 1,
"expires": "2024-03-02T06:42:45Z",
"keys": {
"1ddd1e0f11401c5b981bd67edaf3c2779a963cc9739cfb7136a4be48b0ae7a6e": {
"keytype": "ed25519",
"scheme": "ed25519",
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keyval": {
"public": "507e72d4024fa5f12289bbe9ddb24259939eeece2f43100be3deaab8e7fed859"
}
},
"1f28940a9d054ddcd3d34603b6b0db2bad0b5c79ce822bb206682fa5f3595f01": {
"keytype": "ed25519",
"scheme": "ed25519",
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keyval": {
"public": "4a50d6d166fdc9648e7ffc3db6eae7f09fadc6d47c2012a3382d159daab42870"
}
},
"777ba66bf28f946c2182ec68260230b1aded26ff5b80888a6777354f674a92fb": {
"keytype": "ed25519",
"scheme": "ed25519",
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keyval": {
"public": "5b1940fe025d8e4cf4ea4b04b8e3260b20b6e460eef3e31e98ff9d5021dfdefe"
}
},
"acbf0880ad51c944a937b1a5b869bbe423279fa803d04fcc13d7ecb49e50b456": {
"keytype": "ed25519",
"scheme": "ed25519",
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keyval": {
"public": "6cdfd0edf6f1e99db99a3a3bad5f66f2bf7228c4108d6c1774986235daf1d152"
}
}
},
"roles": {
"root": {
"keyids": [
"777ba66bf28f946c2182ec68260230b1aded26ff5b80888a6777354f674a92fb"
],
"threshold": 1
},
"snapshot": {
"keyids": [
"1ddd1e0f11401c5b981bd67edaf3c2779a963cc9739cfb7136a4be48b0ae7a6e"
],
"threshold": 1
},
"targets": {
"keyids": [
"1f28940a9d054ddcd3d34603b6b0db2bad0b5c79ce822bb206682fa5f3595f01"
],
"threshold": 1
},
"timestamp": {
"keyids": [
"acbf0880ad51c944a937b1a5b869bbe423279fa803d04fcc13d7ecb49e50b456"
],
"threshold": 1
}
},
"consistent_snapshot": false
},
"signatures": [
{
"keyid": "777ba66bf28f946c2182ec68260230b1aded26ff5b80888a6777354f674a92fb",
"sig": "188589b269dd79f899718aac806375a0a437c23e7691434fd28b83ca719ee2b309f70f82e7a497245f19dfeacc265ab53e74aa68a8de9d151c38268fb2864c04"
}
]
}
Initialisons le serveur tuf :
cosign -d initialize --root root.json --mirror https://tuf.robert.local
Root status:
{
"local": "/home/bob/.sigstore/root",
"remote": "https://tuf.robert.local",
"metadata": {
"root.json": {
"version": 1,
"len": 2178,
"expiration": "02 Mar 24 06:42 UTC",
"error": ""
},
"snapshot.json": {
"version": 1,
"len": 618,
"expiration": "02 Mar 24 06:42 UTC",
"error": ""
},
"targets.json": {
"version": 1,
"len": 1028,
"expiration": "02 Mar 24 06:42 UTC",
"error": ""
},
"timestamp.json": {
"version": 1,
"len": 619,
"expiration": "02 Mar 24 06:42 UTC",
"error": ""
}
},
"targets": [
"ctfe.pub",
"fulcio_v1.crt.pem",
"rekor.pub"
]
}
Cool ! Passons à la signature :)
Installation de la CLI Rekor
Avant de signer notre image de conteneur, installons la cli Rekor
:
wget https://github.com/sigstore/rekor/releases/download/v1.2.2/rekor-cli-linux-amd64 -O rekor-cli
chmod +x rekor-cli
sudo install rekor-cli /usr/local/bin
On teste l’accès à notre serveur local :
rekor-cli loginfo --rekor_server https://rekor.robert.local
No previous log state stored, unable to prove consistency
Unable to store previous state: do not persist state for empty logs
Unable to store previous state: do not persist state for empty logs
Verification Successful!
Active Tree Size: 0
Total Tree Size: 0
Root Hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Timestamp: 2023-08-31T06:54:22Z
TreeID: 2639852854654503233
Super !
Signature de l’image avec Cosign avec notre serveur Rekor
On reprend les commandes du billet d’hier pour signer notre image sauf qu’on
indique l’adresse du serveur rekor
:
docker pull registry.gitlab.com/dockerfiles6/images/demo-cosign:latest
export IMAGE=`docker inspect --format='{{index .RepoDigests 0}}' registry.gitlab.com/dockerfiles6/images/demo-cosign:latest`
export REKOR_URL=https://rekor.robert.local
export FULCIO_URL=https://fulcio.robert.local
Generating ephemeral keys...
Retrieving signed certificate...
The sigstore service, hosted by sigstore a Series of LF Projects, LLC, is provided pursuant to the Hosted Project Tools Terms of Use, available at https://lfprojects.org/policies/hosted-project-tools-terms-of-use/.
Note that if your submission includes personal data associated with this signed artifact, it will be part of an immutable record.
This may include the email address associated with the account with which you authenticate your contractual Agreement.
This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later, and is subject to the Immutable Record notice at https://lfprojects.org/policies/hosted-project-tools-immutable-records/.
By typing 'y', you attest that (1) you are not submitting the personal data of any other person; and (2) you understand and agree to the statement and the Agreement terms at the URLs listed above.
Are you sure you would like to continue? [y/N] y
Your browser will now be opened to:
https://oauth2.sigstore.dev/auth/auth?access_type=online&client_id=sigstore&code_challenge=C_QL_huOKcxcHhVSnehyy5RhfHmA3TznIZqAdNAPCvg&code_challenge_method=S256&nonce=2UjtssQFjscrEvjyvBxOETXwuF1&redirect_uri=http%3A%2F%2Flocalhost%3A33809%2Fauth%2Fcallback&response_type=code&scope=openid+email&state=2Ujtslba54Tl5MLEmqLSBMBWVpX
Successfully verified SCT...
tlog entry created with index: 0
Pushing signature to: registry.gitlab.com/dockerfiles6/images/demo-cosign
Normalement une fenêtre s’ouvre avec une demande d’authentification. Pour le
moment, on utilise la configuration d’OIDC de sigstore mais on peut imaginer
utiliser celui de --
(self-hosté) par exemple. Ça fera l’objet d’un projet
billet.
Vérification de la signature
Et là cela fonctionne-t-il ? :
cosign verify --rekor-url=$REKOR_URL --certificate-identity-regexp=.+ --certificate-oidc-issuer-regexp=.+ $IMAGE | jq -r .
**Warning** Missing fallback target fulcio.crt.pem, skipping
**Warning** Missing fallback target fulcio_intermediate_v1.crt.pem, skipping
Verification for registry.gitlab.com/dockerfiles6/images/demo-cosign@sha256:c3b002f3a90054d0f0db12f43f608291610dd61af7f5b06f2a05fdeac1096b40 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The code-signing certificate was verified using trusted certificate authority certificates
[
{
"critical": {
"identity": {
"docker-reference": "registry.gitlab.com/dockerfiles6/images/demo-cosign"
},
"image": {
"docker-manifest-digest": "sha256:c3b002f3a90054d0f0db12f43f608291610dd61af7f5b06f2a05fdeac1096b40"
},
"type": "cosign container image signature"
},
"optional": {
"1.3.6.1.4.1.57264.1.1": "https://github.com/login/oauth",
"Bundle": {
"SignedEntryTimestamp": "MEQCIFA1nuEu4X0/HaGUs/Pi2wURTRTNa/2aLYV+9rSUBny2AiAdsANTHFDFedNu5JMkIM3ItLrqJLIZ9V1PboGZeLuQXA==",
"Payload": {
"body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI2MjVhNmIyOTcxOWI1YzRhOWMyZDNlZTIzZGU0YmY4OGExNGM3NDE0NjRlN2YwNDdmOTE2NjAyMTg1ZTdmNGE1In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJSGV2aTc3Y3gzcnIrYWNoU053WEpYWHdNL0JFcGVudVM2RThuQzA3M0hQZUFpRUFnYUlOS1FMb3RmSkp5eWtyOHN1WkFlZjhXOU85a3c0OXZTRUppT2JZYU5ZPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVVjNla05EUVhGMVowRjNTVUpCWjBsVlRrcG1lamhyVTNOVmNraEVVVVU0SzFGUldFb3phbVp1Tm5jMGQwUlJXVXBMYjFwSmFIWmpUa0ZSUlV3S1FsRkJkMlpxUlUxTlFXOUhRVEZWUlVKb1RVUldWazVDVFZKTmQwVlJXVVJXVVZGSlJYZHdSRmxYZUhCYWJUbDVZbTFzYUUxU1dYZEdRVmxFVmxGUlNBcEZkekZVV1ZjMFoxSnVTbWhpYlU1d1l6Sk9kazFTV1hkR1FWbEVWbEZSU2tWM01ERk9SR2RuVkZkR2VXRXlWakJKUms0d1RWRTBkMFJCV1VSV1VWRlNDa1YzVlRGT2Vra3pUa1JGV2sxQ1kwZEJNVlZGUTJoTlVWUkhiSFZrV0dkblVtMDVNV0p0VW1oa1IyeDJZbXBCWlVaM01IbE5la0UwVFhwRmQwNXFWVE1LVFZSQ1lVWjNNSGxOZWtFMFRYcEZkMDU2UVROTlZFSmhUVUZCZDFkVVFWUkNaMk54YUd0cVQxQlJTVUpDWjJkeGFHdHFUMUJSVFVKQ2QwNURRVUZUWlFvM2FFcERUelJqUTJaclJXNWhXVkZTU210TFowWlBUR0ZqVGxaNVRXSlFTVzgyZEhORlRIVnBNalE1UTFsVWNIaDNiemh0WkcxdVVuQkpOVlZ4WldGa0NuazJlVWcwV1VSeVRrTjNRV0pNY1hZemVtSllielJKUW1kRVEwTkJXSGQzUkdkWlJGWlNNRkJCVVVndlFrRlJSRUZuWlVGTlFrMUhRVEZWWkVwUlVVMEtUVUZ2UjBORGMwZEJVVlZHUW5kTlJFMUNNRWRCTVZWa1JHZFJWMEpDVW5GdFRUSnNaMWx3Y0RoNlIwUm9XRkJxVVZvcmJXTjFUM0JuZWtGbVFtZE9WZ3BJVTAxRlIwUkJWMmRDVTFablFYZFhhMU0zUmxob01sUmhkV2xOV0d0S1kxaENMMGMzUkVGeFFtZE9Wa2hTUlVKQlpqaEZTVVJCWldkU2VIbGlNa3BzQ21OdVVYVmpNMUpzWTBkb2FHSnRWWFZOYW1oQldqSXhhR0ZYZDNWWk1qbDBUVU4zUjBOcGMwZEJVVkZDWnpjNGQwRlJSVVZJYldnd1pFaENlazlwT0hZS1dqSnNNR0ZJVm1sTWJVNTJZbE01YzJJeVpIQmlhVGwyV1ZoV01HRkVRWFZDWjI5eVFtZEZSVUZaVHk5TlFVVkpRa05CVFVodGFEQmtTRUo2VDJrNGRncGFNbXd3WVVoV2FVeHRUblppVXpsellqSmtjR0pwT1haWldGWXdZVVJEUW1sbldVdExkMWxDUWtGSVYyVlJTVVZCWjFJNFFraHZRV1ZCUWpKQlNWbEJDbk5DWm1rMVUyMDFlbWg0U2xGM1RIRkpla2RZWmxkaVpsQmlaa2x4VGtkR2FHTlVSblVyWld0QlFVRkNhV3R3YUhKeVFVRkJRVkZFUVVWamQxSlJTV2dLUVVrek1ISkllRGhVTVhaVmVVaGxRM2Q1V0M4MWJsQjZNbFU0YTBWcE9WRkNaV1l6WTNKWEszTnhNbkZCYVVKWmFrVjZUMk5YTVRjck9WRlRNVU5KVEFwb2MwTkljblJoYlZoV05tNXRNbGhYZFdOU2VuRlVaRzk0ZWtGT1FtZHJjV2hyYVVjNWR6QkNRVkZ6UmtGQlQwTkJaMFZCY0ROS2VGcFNXbTFoWTBaRENuUmtiV2RaWm5SQlFXTkJabXRSVVVsT2NERlJLM3BWYWxVMWVtMWllbmhtVFRVd2NGaEJWWFpTVlVRNFptSlBkRGxOZWxJeGFrcHVTblp1Y0RsVmNXZ0tlbFptWnpSMGRIQkhXVXNyWjB4MmVHZzNXbU5IYVcwNVFYUmtORXBpYTJNMVkyOTFMMWg0UkdkM1NXTjVTbWxhWkc1bGQzbFBNR0YxVm1WMWNGTmxNQXBLYkZsUmJWSkNRMkpFZUVNeVRHWkJLM1k1WW1sR1dsQklUSFJRUm1abWQzVTVhMVF6UVRZM09VTnFaRkpsVURscWNIWndPRFIyYkVWeVVVYzFaRlp0Q25JdllWUkxNMHBJYURKaGEyVXJlazVTTnprNFQyUlFhVkZSUjNsQlMycFJiV3hMTVhkWlNGUkpZbTFCVEhGRlFpOTJjbUlyYm0xSVQzZDJhSE4xTkZnS2JXWkZhMlpOT0daNVJGWk9SMW96T0U5M1EwMTNaRlIwV201Q05GWjNOMHQxV21wNk5YSmxORTEzY1ZsVU5XODVTMng1YjAxUlNub3JkV1V2YVRKbVVBcEhRWGRNYUNzcmRHRnNRa0owWkVaMmVITnphRlJFZEdwdFlsWm1TQ3N6UVVSbWMycE9iMmcwVEhSdWN6WjBiMVV6VlZOTFFqTnFOV0oxVjFGeWIzQjNDa0ZYTW1SRlUxRjRkV1ExYjJSMGFFOWxPVUZPZW5wNGNGVk1jeXRsYTFkdGVraEdNak52TmtoV2VYTmtPRUo1TnpsRk9XSTVabTF2T0ZoR1ZXNTVOWG9LTURaT1MwZ3dhakoyYlVOa2MxcElkblZ1Vm14VlVYWXhSbUpvZGxadVJrMTRNV0o2ZGxwbmNtUnhUV3BxU1RoQ1ExSmpTMDFITTJabE5FVnlkRlJLVmdvMU5GaENlVE5JVlZBdmEwOVJUbTV4T1V4TGFtSTRWVzVCWWtKeFJXZzFUSEp1WVdjMU1YSnRWREZUUVRCaVptMHdaVlkwYkZOeGExVk5Oek5VWVVOU0NucGtaVTEwT1ZCd1JtUkNaWE5aTkhOdmNXWktZVU5KT1RWR1VXTkplRk5pTXpKWWFrWnliMjA1V0M5WU1FSXJNR0o1YmpBeWMwbHZlSHBCWTJsRUszWUtiMFF3Vm5JeVZFbzVRMDVzTmxkV2VqUnlaRkV4Ykd0ck1sVXZlbk51ZHowS0xTMHRMUzFGVGtRZ1EwVlNWRWxHU1VOQlZFVXRMUzB0TFFvPSJ9fX19",
"integratedTime": 1693465031,
"logIndex": 0,
"logID": "a558e7d223efd979dace1b9323ce425f376f9e9c971900e2e1a0a6fdb6af312e"
}
},
"Issuer": "https://github.com/login/oauth",
"Subject": "robert.stephane.28@gmail.com"
}
}
]
Yes !!!!
rekor-cli get --log-index 0 --rekor_server https://rekor.robert.local --format json | jq -r .
{
"Attestation": "",
"AttestationType": "",
"Body": {
"HashedRekordObj": {
"data": {
"hash": {
"algorithm": "sha256",
"value": "625a6b29719b5c4a9c2d3ee23de4bf88a14c741464e7f047f916602185e7f4a5"
}
},
"signature": {
"content": "MEUCIHevi77cx3rr+achSNwXJXXwM/BEpenuS6E8nC073HPeAiEAgaINKQLotfJJyykr8suZAef8W9O9kw49vSEJiObYaNY=",
"publicKey": {
"content": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUV3ekNDQXF1Z0F3SUJBZ0lVTkpmejhrU3NVckhEUUU4K1FRWEozamZuNnc0d0RRWUpLb1pJaHZjTkFRRUwKQlFBd2ZqRU1NQW9HQTFVRUJoTURWVk5CTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saE1SWXdGQVlEVlFRSApFdzFUWVc0Z1JuSmhibU5wYzJOdk1SWXdGQVlEVlFRSkV3MDFORGdnVFdGeWEyVjBJRk4wTVE0d0RBWURWUVFSCkV3VTFOekkzTkRFWk1CY0dBMVVFQ2hNUVRHbHVkWGdnUm05MWJtUmhkR2x2YmpBZUZ3MHlNekE0TXpFd05qVTMKTVRCYUZ3MHlNekE0TXpFd056QTNNVEJhTUFBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTZQo3aEpDTzRjQ2ZrRW5hWVFSSmtLZ0ZPTGFjTlZ5TWJQSW82dHNFTHVpMjQ5Q1lUcHh3bzhtZG1uUnBJNVVxZWFkCnk2eUg0WURyTkN3QWJMcXYzemJYbzRJQmdEQ0NBWHd3RGdZRFZSMFBBUUgvQkFRREFnZUFNQk1HQTFVZEpRUU0KTUFvR0NDc0dBUVVGQndNRE1CMEdBMVVkRGdRV0JCUnFtTTJsZ1lwcDh6R0RoWFBqUVorbWN1T3BnekFmQmdOVgpIU01FR0RBV2dCU1ZnQXdXa1M3RlhoMlRhdWlNWGtKY1hCL0c3REFxQmdOVkhSRUJBZjhFSURBZWdSeHliMkpsCmNuUXVjM1JsY0doaGJtVXVNamhBWjIxaGFXd3VZMjl0TUN3R0Npc0dBUVFCZzc4d0FRRUVIbWgwZEhCek9pOHYKWjJsMGFIVmlMbU52YlM5c2IyZHBiaTl2WVhWMGFEQXVCZ29yQmdFRUFZTy9NQUVJQkNBTUhtaDBkSEJ6T2k4dgpaMmwwYUhWaUxtTnZiUzlzYjJkcGJpOXZZWFYwYURDQmlnWUtLd1lCQkFIV2VRSUVBZ1I4QkhvQWVBQjJBSVlBCnNCZmk1U201emh4SlF3THFJekdYZldiZlBiZklxTkdGaGNURnUrZWtBQUFCaWtwaHJyQUFBQVFEQUVjd1JRSWgKQUkzMHJIeDhUMXZVeUhlQ3d5WC81blB6MlU4a0VpOVFCZWYzY3JXK3NxMnFBaUJZakV6T2NXMTcrOVFTMUNJTApoc0NIcnRhbVhWNm5tMlhXdWNSenFUZG94ekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBZ0VBcDNKeFpSWm1hY0ZDCnRkbWdZZnRBQWNBZmtRUUlOcDFRK3pValU1em1ienhmTTUwcFhBVXZSVUQ4ZmJPdDlNelIxakpuSnZucDlVcWgKelZmZzR0dHBHWUsrZ0x2eGg3WmNHaW05QXRkNEpia2M1Y291L1h4RGd3SWN5SmlaZG5ld3lPMGF1VmV1cFNlMApKbFlRbVJCQ2JEeEMyTGZBK3Y5YmlGWlBITHRQRmZmd3U5a1QzQTY3OUNqZFJlUDlqcHZwODR2bEVyUUc1ZFZtCnIvYVRLM0pIaDJha2Urek5SNzk4T2RQaVFRR3lBS2pRbWxLMXdZSFRJYm1BTHFFQi92cmIrbm1IT3d2aHN1NFgKbWZFa2ZNOGZ5RFZOR1ozOE93Q013ZFR0Wm5CNFZ3N0t1Wmp6NXJlNE13cVlUNW85S2x5b01RSnordWUvaTJmUApHQXdMaCsrdGFsQkJ0ZEZ2eHNzaFREdGptYlZmSCszQURmc2pOb2g0THRuczZ0b1UzVVNLQjNqNWJ1V1Fyb3B3CkFXMmRFU1F4dWQ1b2R0aE9lOUFOenp4cFVMcytla1dtekhGMjNvNkhWeXNkOEJ5NzlFOWI5Zm1vOFhGVW55NXoKMDZOS0gwajJ2bUNkc1pIdnVuVmxVUXYxRmJodlZuRk14MWJ6dlpncmRxTWpqSThCQ1JjS01HM2ZlNEVydFRKVgo1NFhCeTNIVVAva09RTm5xOUxLamI4VW5BYkJxRWg1THJuYWc1MXJtVDFTQTBiZm0wZVY0bFNxa1VNNzNUYUNSCnpkZU10OVBwRmRCZXNZNHNvcWZKYUNJOTVGUWNJeFNiMzJYakZyb205WC9YMEIrMGJ5bjAyc0lveHpBY2lEK3YKb0QwVnIyVEo5Q05sNldWejRyZFExbGtrMlUvenNudz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
}
}
}
},
"LogIndex": 0,
"IntegratedTime": 1693465031,
"UUID": "24a2a42f4cfb8941bfe184574ae20e7444b406693ec70484cd661f92fb079a9996c9a1af6ba384a4",
"LogID": "a558e7d223efd979dace1b9323ce425f376f9e9c971900e2e1a0a6fdb6af312e"
}
Excellent non ?
Conclusion
Bon maintenant que la signature fonctionne, il faut passer à l’attachement des attestations dont le certificat d’analyse de vulnérabilités et des attestions de validation d’étapes de build avec in-toto