Cette page explique comment créer une attestation dans l'autorisation binaire à partir de la ligne de commande.
Les instructions de cette page décrivent les étapes qu'un signataire doit effectuer pour autoriser le déploiement d'une image de conteneur. En situation réelle, vous intégrez ces étapes dans un script ou une automatisation pouvant être déclenché par un processus machine ou un utilisateur humain, plutôt que de les saisir manuellement en ligne de commande.
Présentation
Une attestation est un document signé numériquement, généré par un signataire, qui certifie qu'un processus requis dans votre pipeline est terminé et que l'image de conteneur obtenue est autorisée pour le déploiement dans GKE. L'attestation elle-même contient le chemin d'accès complet à la version de l'image de conteneur stockée dans votre registre d'images de conteneurs, ainsi qu'une signature créée en signant le condensé globalement unique qui identifie une compilation d'image de conteneur spécifique.
Vous pouvez créer une attestation à l'aide d'une signature PKIX (recommandée) ou PGP. Ce guide utilise le format d'infrastructure à clé publique X.509 (PKIX) pour les clés cryptographiques et utilise l'algorithme de signature numérique à courbe elliptique (ECDSA) recommandé pour signer et créer l'attestation. Vous pouvez également utiliser des clés RSA ou PGP pour la signature. Consultez la page Objectifs et algorithmes des clés pour plus d'informations sur les algorithmes de signature.
Définir le projet par défaut
Si vous n'avez pas encore défini votre projet Google Cloud par défaut, exécutez la commande suivante :
PROJECT_ID=PROJECT_ID gcloud config set project ${PROJECT_ID}
Où PROJECT_ID correspond au nom de votre projet.
Configurer l'environnement
Configurez des variables d'environnement pour stocker vos ID de projet :
ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID ATTESTATION_PROJECT_ID=ATTESTATION_PROJECT_ID
Où :
- ATTESTOR_PROJECT_ID correspond au nom du projet dans lequel vous stockez vos certificateurs ;
- ATTESTATION_PROJECT_ID correspond au nom du projet dans lequel vous stockez vos attestations.
Si votre projet pour les certificateurs est le même que votre projet pour les attestations, utilisez le même ID de projet pour les deux variables.
Configurez des variables d'environnement pour stocker le nom du certificateur qui valide l'attestation et le chemin d'accès du registre à l'image que vous souhaitez déployer :
ATTESTOR_NAME=ATTESTOR_NAME IMAGE_PATH=IMAGE_PATH IMAGE_DIGEST=IMAGE_DIGEST PUBLIC_KEY_ID=PUBLIC_KEY_ID PRIVATE_KEY_FILE=PRIVATE_KEY_FILE IMAGE_TO_ATTEST="${IMAGE_PATH}@${IMAGE_DIGEST}"
Où :
- ATTESTOR_NAME correspond au nom du certificateur (par exemple,
build-secure
ouprod-qa
) ; - IMAGE_PATH correspond au chemin d'accès dans Container Registry vers l'image que vous souhaitez déployer (par exemple,
gcr.io/example-project/quickstart-image
) ; - PUBLIC_KEY_ID correspond à l'ID associé à la clé publique de la paire de clés générée. La clé publique est stockée dans le certificateur ;
- PRIVATE_KEY_FILE correspond au fichier contenant la clé privée de la paire de clés que vous avez générée. La charge utile de l'attestation est signée avec cette clé ;
- IMAGE_DIGEST correspond au condensé SHA-256 du fichier manifeste de l'image (par exemple,
sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea882eb722c3be4
). Pour plus d'informations sur l'obtention du condensé de l'image, consultez la section Répertorier les versions d'une image dans Container Registry.
- ATTESTOR_NAME correspond au nom du certificateur (par exemple,
Chaque image de conteneur stockée dans Container Registry ou un autre registre est accessible via un chemin d'accès unique. En outre, un condensé SHA-256 identifie de manière unique la version de l'image. Les attestations référencent le chemin d'accès complet de l'image et son condensé, ce qui vous permet d'autoriser des versions spécifiques d'une image.
Voici un exemple de chemin de registre complet :
gcr.io/example-project/quickstart-image@sha256:bedb3feb23e81d162e33976fd7b245adff00379f4755c0213e84405e5b1e0988
Créer une attestation avec une signature PKIX à l'aide d'une clé stockée localement
Pour les attestations signées avec une clé publique PKIX, vous devez procéder comme suit :
- Créer une charge utile d'attestation à envoyer à l'autorisation binaire, qui référence le chemin d'accès au registre.
- Signer la charge utile et générer un fichier de signature PKIX.
- Obtenir l'ID de clé publique.
- Créer l'attestation avec le fichier de signature et l'ID de clé publique.
Créer une charge utile d'attestation
La charge utile d'un certificat est un fichier au format JSON qui référence l'emplacement de l'image de conteneur.
Pour créer le fichier de charge utile :
gcloud
Saisissez ce qui suit :
gcloud container binauthz create-signature-payload \ --artifact-url="${IMAGE_TO_ATTEST}" > /tmp/generated_payload.json
Le fichier de charge utile ressemble à ceci :
{ "critical": { "identity": { "docker-reference": "gcr.io/google-samples/hello-app" }, "image": { "docker-manifest-digest": "sha256:bedb3feb23e81d162e33976fd7b245 adff00379f4755c0213e84405e5b1e0988" }, "type": "Google cloud binauthz container signature" } }
REST
Créez un fichier de charge utile nommé /tmp/generated_payload.json
à l'aide des variables d'environnement que vous avez définies ci-dessus :
cat > /tmp/generated_payload.json << EOM { "critical": { "identity": { "docker-reference": "${IMAGE_PATH}" }, "image": { "${IMAGE_DIGEST}" }, "type": "Google cloud binauthz container signature" } } EOM
Signer le fichier de charge utile et générer un fichier de signature
Après avoir créé le fichier de charge utile, vous devez le signer à l'aide de la clé cryptographique privée de la paire de clés générée précédemment. Rappelez-vous que la clé publique correspondante a été stockée dans le certificateur associé. La clé publique de ce certificateur est utilisée pour vérifier cette signature au moment du déploiement.
Pour savoir comment créer un certificateur, consultez la page Créer des certificateurs à l'aide de la CLI ou Créer des certificateurs à l'aide de la console.
Pour obtenir un exemple de bout en bout incluant toutes ces étapes, consultez la page Premiers pas avec la CLI ou Premiers pas avec la console.
Pour signer le fichier de charge utile :
Signez le fichier de charge utile à l'aide de votre clé privée PKIX locale et générez un fichier de signature :
openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
Le fichier de signature est une version signée numériquement du fichier JSON de charge utile que vous avez créé ci-dessus.
Obtenir l'ID de clé publique
Vous devez envoyer un ID de clé publique à l'autorisation binaire avec le fichier de signature lorsque vous créez une attestation.
Pour obtenir l'ID de clé publique :
Enregistrez l'ID de clé publique.
Pour afficher ultérieurement l'ID de clé publique de votre certificateur, utilisez la commande
gcloud container binauthz attestors describe ${ATTESTOR_NAME}
:PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \ --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
Créer l'attestation
gcloud
Pour créer l'attestation, saisissez la commande suivante :
gcloud container binauthz attestations create \ --project="${ATTESTATION_PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \ --signature-file=/tmp/ec_signature \ --public-key-id="${PUBLIC_KEY_ID}"
Vous pouvez également créer et valider la vérification de l'attestation par le certificateur fourni :
gcloud alpha container binauthz attestations create \ --project="${ATTESTATION_PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \ --signature-file=/tmp/ec_signature \ --public-key-id="${PUBLIC_KEY_ID}" \ --validate
Remarque : Le format de la chaîne de l'ID de clé est libre.
REST
Pour créer l'attestation, procédez comme suit :
Récupérez le certificateur associé à l'attestation et extrayez l'ID de la clé publique stockée :
curl \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \ "https://binaryauthorization.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/attestors/"
L'autorisation binaire renvoie un objet JSON semblable à celui-ci :
{ "name": "projects/example-project/attestors/test-attestor", "userOwnedGrafeasNote": { "noteReference": "projects/example-project/notes/test-attestor", "publicKeys": [ { "id": "ni:///sha-256;EwVxs8fNUAHq9FI2AMfh8WNIXVBuuTMeGtPH72U-I70", "pkixPublicKey": { "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXnpuYEfvLl1kj4fjxViFRwY1a+zC\n5qzlf9LJIK+rnjq42tiKGyyXMbnZKJiYPPdMDGyltnkrABnztg2jJ48aYQ==\n-----END PUBLIC KEY-----\n", "signatureAlgorithm": "ECDSA_P256_SHA256" } } ], "delegationServiceAccountEmail": "service-363451293945@gcp-sa-binaryauthorization.iam.gserviceaccount.com" }, "updateTime": "2019-06-26T16:58:33.977438Z" }
Dans un éditeur de texte, créez un fichier JSON dans
/tmp/attestation.json
qui décrit l'attestation :cat > /tmp/attestation.json << EOM { "resourceUri": "${IMAGE_TO_ATTEST}", "note_name": "${NOTE_URI}", "attestation": { "serialized_payload": "$(base64 --wrap=0 /tmp/generated_payload.json)", "signatures": [ { "public_key_id": "KEY_ID", "signature": "$(base64 --wrap=0 /tmp/ec_signature)" } ] } } EOM
Où KEY_ID correspond à l'ID de clé publique renvoyé à l'étape précédente.
Créez l'attestation :
curl -X POST \ -H "Content-Type: application/json" \ -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ --data-binary @/tmp/attestation.json \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/"
Créer une attestation avec une signature PKIX basée sur Cloud Key Management Service
Pour créer une attestation avec une signature PKIX basée sur Cloud Key Management Service, procédez comme suit :
Configurez des variables d'environnement pour stocker des informations sur les projets où sont stockés vos attestations, vos certificateurs et vos clés Cloud Key Management Service, ainsi que des informations sur votre paire de clés PKIX :
KMS_KEY_PROJECT_ID=KMS_KEY_PROJECT_ID KMS_KEY_LOCATION=KMS_KEY_LOCATION KMS_KEYRING_NAME=KMS_KEYRING_NAME KMS_KEY_NAME=KMS_KEY_NAME KMS_KEY_VERSION=KMS_KEY_VERSION
Où :
- KMS_KEY_PROJECT_ID correspond à l'ID du projet dans lequel vos clés Cloud Key Management Service sont stockées ;
- KMS_KEY_LOCATION correspond à l'emplacement de la clé (
global
est la valeur par défaut) ; - KMS_KEYRING_NAME correspond au nom du trousseau de clés ;
- KMS_KEY_NAME correspond au nom de la clé ;
- KMS_KEY_VERSION correspond à la version de clé.
Signez et créez l'attestation :
gcloud
Saisissez ce qui suit dans la ligne de commande :
gcloud beta container binauthz attestations sign-and-create \ --project="${ATTESTATION_PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="${ATTESTOR_NAME}" \ --attestor-project="${ATTESTOR_PROJECT_ID}" \ --keyversion-project="${KMS_KEY_PROJECT_ID}" \ --keyversion-location="${KMS_KEY_LOCATION}" \ --keyversion-keyring="${KMS_KEYRING_NAME}" \ --keyversion-key="${KMS_KEY_NAME}" \ --keyversion="${KMS_KEY_VERSION}"
REST
Créez un fichier de charge utile nommé
/tmp/generated_payload.json
à l'aide des variables d'environnement que vous avez définies ci-dessus :cat > /tmp/generated_payload.json << EOM { "critical": { "identity": { "docker-reference": "${IMAGE_PATH}" }, "image": { "${IMAGE_DIGEST}" }, "type": "Google cloud binauthz container signature" } } EOM
Signez le fichier de charge utile :
gcloud --project="${KMS_KEY_PROJECT_ID}" \ alpha kms asymmetric-sign \ --location="${KMS_KEY_LOCATION}" \ --keyring="${KMS_KEYRING_NAME}" \ --key="${KMS_KEY_NAME}" \ --version="${KMS_KEY_VERSION}" \ --digest-algorithm="DIGEST_ALGORITHM" \ --input-file=/tmp/generated_payload.json \ --signature-file=/tmp/generated_payload.json.sig
Où DIGEST_ALGORITHM est l'un des éléments suivants :
sha256
,sha384
ousha512
. Il s'agit de l'algorithme de condensé de la version de clé que vous utilisez pour la signature.Cette commande génère un fichier nommé
/tmp/generated_payload.json.sig
contenant la signature numérique.Récupérez le certificateur au nom duquel vous signez l'attestation et extrayez l'ID de la clé publique stockée :
curl \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \ "https://binaryauthorization.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/attestors/"
L'autorisation binaire renvoie un objet JSON semblable à celui-ci :
{ "name": "projects/example-project/attestors/test-attestor", "userOwnedGrafeasNote": { "noteReference": "projects/example-project/notes/test-attestor", "publicKeys": [ { "id": "ni:///sha-256;EwVxs8fNUAHq9FI2AMfh8WNIXVBuuTMeGtPH72U-I70", "pkixPublicKey": { "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXnpuYEfvLl1kj4fjxViFRwY1a+zC\n5qzlf9LJIK+rnjq42tiKGyyXMbnZKJiYPPdMDGyltnkrABnztg2jJ48aYQ==\n-----END PUBLIC KEY-----\n", "signatureAlgorithm": "ECDSA_P256_SHA256" } } ], "delegationServiceAccountEmail": "service-363451293945@gcp-sa-binaryauthorization.iam.gserviceaccount.com" }, "updateTime": "2019-06-26T16:58:33.977438Z" }
Dans un éditeur de texte, créez un fichier JSON dans
/tmp/attestation.json
qui décrit l'attestation :cat > /tmp/attestation.json << EOM { "resourceUri": "${IMAGE_TO_ATTEST}", "note_name": "${NOTE_URI}", "attestation": { "serialized_payload": "$(base64 --wrap=0 /tmp/generated_payload.json)", "signatures": [ { "public_key_id": "KEY_ID", "signature": "$(base64 --wrap=0 /tmp/generated_payload.json.sig)" } ] } } EOM
Où KEY_ID correspond à l'ID de clé publique renvoyé à l'étape précédente.
Créez l'attestation :
curl -X POST \ -H "Content-Type: application/json" \ -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ --data-binary @/tmp/attestation.json \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/"
Vérifier que l'attestation a bien été créée
Pour vérifier que l'attestation a été créée, procédez comme suit :
gcloud
Saisissez ce qui suit dans la ligne de commande :
gcloud container binauthz attestations list \ --project="${ATTESTATION_PROJECT_ID}" \ --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}"
REST
Récupérez une liste d'attestations :
curl -X GET \ -H "Content-Type: application/json" \ -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences?filter=kind%3D%22ATTESTATION%22"
S'il existe de nombreuses attestations, une valeur "nextPageToken" peut être renvoyée dans la réponse. Dans ce cas, la requête doit être répétée, mais le paramètre de requête pageToken doit être défini sur cette valeur nextPageToken pour récupérer d'autres attestations. Lorsque nextPageToken est vide, cela signifie qu'il n'y a plus de résultats.
curl -X GET \ -H "Content-Type: application/json" \ -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/?filter=kind%3D%22ATTESTATION%22&pageToken=${NEXT_PAGE_TOKEN}"
Étape suivante
- Déployez une image de conteneur sur un cluster où l'autorisation binaire est activée.