Créer des attestations

Cette page décrit la procédure à suivre pour créer une attestation d'autorisation binaire.

Une seule attestation permet d'autoriser des images identiques stockées dans plusieurs emplacements ou différents registres, tels qu'Artifact Registry, Container Registry ou un registre de conteneurs externe.

Au moment du déploiement, l'autorisation binaire utilise des certificateurs pour valider les attestations.

Pour obtenir un tutoriel de bout en bout décrivant l'application basée sur l'attestation à l'aide de l'autorisation binaire et de Google Kubernetes Engine (GKE), consultez la page Premiers pas avec l'outil de ligne de commande ou Premiers pas avec Google Cloud Console.

Pour obtenir des instructions de bout en bout pour toutes les autres plates-formes, consultez la page Configurer les plates-formes et sélectionnez votre plate-forme.

Avant de commencer

La page Présentation des attestations décrit la procédure à suivre avant de créer une attestation.

Configurer l'environnement

  1. Spécifiez les ID de votre projet :

    ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID
    ATTESTATION_PROJECT_ID=ATTESTATION_PROJECT_ID
    

    Remplacez les éléments suivants :

    • ATTESTOR_PROJECT_ID : nom du projet dans lequel vous stockez vos certificateurs.
    • ATTESTATION_PROJECT_ID : nom du projet dans lequel vous stockez vos attestations.

    Si vous souhaitez que votre attestation soit créée dans le même projet que vos certificateurs, utilisez le même ID de projet pour les deux variables. Pour obtenir un tutoriel de bout en bout illustrant la séparation des tâches avec différents projets, consultez la page Configuration multiprojets.

  2. Spécifiez le nom du certificateur et les informations relatives à l'image :

    ATTESTOR_NAME=ATTESTOR_NAME
    IMAGE_PATH=IMAGE_PATH
    IMAGE_DIGEST=IMAGE_DIGEST
    IMAGE_TO_ATTEST="${IMAGE_PATH}@${IMAGE_DIGEST}"
    

    Remplacez les éléments suivants :

    • ATTESTOR_NAME : nom du certificateur, par exemple, build-secure ou prod-qa.
    • IMAGE_PATH : URI représentant un chemin d'accès à l'image. Bien que l'URI doive comprendre un nom de domaine et d'image, il n'a pas besoin de faire référence à une image réelle. Les images ne sont pas accessibles lors de la création de l'attestation. Voici des exemples de chemins d'accès normalisés :

      • us-docker.pkg.dev/google-samples/containers/gke/hello-app
      • gcr.io/example-project/quickstart-image
      • example.com/hello-app.
    • IMAGE_DIGEST : condensé du fichier manifeste de l'image. Par exemple, sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567 correspond au condensé de l'image associé au chemin d'accès de l'image us-docker.pkg.dev/google-samples/containers/gke/hello-app. Pour savoir comment obtenir le condensé d'une image dans Artifact Registry, consultez la section Gérer les images. Pour obtenir une image dans Container Registry, consultez la section Répertorier les versions d'une image

Attribuer des rôles Identity and Access Management

Pour créer des attestations, vous devez attribuer les rôles Identity and Access Management (IAM) suivants à l'identité qui crée le certificateur, comme suit :

  • roles/containeranalysis.notes.attacher sur la ressource de note associée au certificateur.
  • roles/containeranalysis.occurrences.editor sur la ressource du projet d'attestation.

Vous créez une attestation basée sur un certificateur. Le certificateur est associé à une note Container Analysis. La création d'une attestation à son tour crée une occurrence Container Analysis et l'associe à la note.

En savoir plus sur l'octroi de l'accès.

Pour savoir comment créer une attestation dans un pipeline Cloud Build, consultez la page Créer des attestations à l'aide de Kritis Signer.

Créez un certificat

Créer une attestation à l'aide d'une clé stockée localement

Pour créer des attestations signées avec une clé locale, procédez comme suit :

  1. Créez un fichier de charge utile de signature :

    gcloud

    Pour créer le fichier de charge utile de signature, saisissez la commande suivante :

    gcloud container binauthz create-signature-payload \
        --artifact-url="${IMAGE_TO_ATTEST}" > /tmp/generated_payload.json
    

    Le fichier de charge utile au format JSON ressemble à ce qui suit :

    {
      "critical": {
        "identity": {
          "docker-reference": "us-docker.pkg.dev/google-samples/containers/gke/hello-app"
        },
        "image": {
          "docker-manifest-digest": "sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567"
        },
        "type": "Google cloud binauthz container signature"
      }
    }
    

    API REST

    Créez un fichier de charge utile nommé /tmp/generated_payload.json à l'aide des variables d'environnement que vous avez définies précédemment dans ce document :

    cat > /tmp/generated_payload.json << EOM
    {
      "critical": {
        "identity": {
          "docker-reference": "${IMAGE_PATH}"
        },
        "image": {
          "docker-manifest-digest": "${IMAGE_DIGEST}"
        },
        "type": "Google cloud binauthz container signature"
      }
    }
    EOM
    
  2. Signez le fichier de charge utile à l'aide de votre clé privée pour générer un fichier de signature.

    Ce guide utilise l'algorithme ECDSA (Elliptic Curve Digital Signing Algorithm) recommandé pour la signature. Vous pouvez également utiliser l'algorithme RSA. Pour plus d'informations sur les algorithmes de signature, consultez la page Objectifs et algorithmes des clés. Ce guide utilise également le format de signature Infrastructure à clé publique (X.509) (PKIX). Vous pouvez également utiliser PGP.

    PRIVATE_KEY_FILE=PRIVATE_KEY_FILE
    openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
    

    Remplacez PRIVATE_KEY_FILE par le chemin d'accès à la clé privée que vous avez générée lors de la création du certificateur.

  3. Obtenir l'ID de clé publique

    Vous pouvez récupérer l'ID de clé publique à partir du certificateur en saisissant la commande suivante :

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
    
  4. Créez l'attestation :

    gcloud

    Pour créer et valider 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}" \
        --validate
    

    L'option validate vérifie que l'attestation peut être validée par le certificateur que vous avez configuré dans votre stratégie.

    Remarque : Le format de la chaîne de l'ID de clé est libre.

    API REST

    Pour créer l'attestation, procédez comme suit :

    1. 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"
      }
      

      La clé publique se trouve dans le champ id.

    2. Créez un fichier JSON décrivant l'attestation dans /tmp/attestation.json :

      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": "${PUBLIC_KEY_ID}",
               "signature": "$(base64 --wrap=0 /tmp/ec_signature)"
              }
           ]
        }
       }
      EOM
      
    3. 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 à l'aide de Cloud KMS

Pour créer une attestation à l'aide de Cloud Key Management Service, procédez comme suit :

  1. Créez des variables d'environnement :

    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
    

    Remplacez les éléments suivants :

    • KMS_KEY_PROJECT_ID : ID du projet dans lequel vos clés Cloud Key Management Service sont stockées.
    • KMS_KEY_LOCATION : emplacement de la clé (global est la valeur par défaut)
    • KMS_KEYRING_NAME : nom du trousseau de clés
    • KMS_KEY_NAME : nom de la clé
    • KMS_KEY_VERSION : version de la clé
  2. Signez et créez l'attestation :

    gcloud

    Saisissez la commande suivante :

    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}"
    

    API REST

    1. 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": {
            "docker-manifest-digest": "${IMAGE_DIGEST}"
          },
          "type": "Google cloud binauthz container signature"
        }
      }
      EOM
      
    2. Signez le fichier de charge utile :

      curl \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer $(gcloud auth print-access-token)" \
        --header "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \
        --data '{"digest":  {"DIGEST_ALGORITHM": "'$(openssl dgst -sha256 -binary /tmp/generated_payload.json | openssl base64)'" }}' \
      https://cloudkms.googleapis.com/v1/projects/${KMS_KEY_PROJECT_ID}/locations/${KMS_KEY_LOCATION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME}/cryptoKeyVersions/${KMS_KEY_VERSION}:asymmetricSign?alt=json
      

      Remplacez DIGEST_ALGORITHM par l'algorithme pour condenser les entrées. Les exemples de ce guide utilisent un condensé sha256. Vous pouvez utiliser sha256, sha384 ou sha512.

      Dans cet exemple, le résultat ressemble à ceci :

      {
        "signature": "<var>SIGNATURE</var>": "996305066",
        "name": "projects/<var>KMS_KEY_PROJECT_ID</var>/locations/<var>KMS_KEY_LOCATION</var>/keyRings/<var>KMS_KEYRING_NAME</var>/cryptoKeys/<var>KMS_KEY_NAME</var>/cryptoKeyVersions/<var>KMS_KEY_VERSION</var>"
      }
      

      Dans ce résultat, SIGNATURE est la signature encodée en base64 du fichier de charge utile.

    3. Stockez la signature dans une variable d'environnement :

      PAYLOAD_SIGNATURE=PAYLOAD_SIGNATURE
      
    4. Récupérez le certificateur au nom duquel vous signez l'attestation et extrayez l'ID de la clé publique stockée et l'ID de la note :

      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"
      }
      

      Vous pouvez trouver l'ID de clé publique dans le champ id et l'ID de note dans le champ noteReference.

    5. Stockez l'ID de clé publique dans une variable d'environnement :

      PUBLIC_KEY_ID="PUBLIC_KEY_ID"
      NOTE_URI="NOTE_URI"
      

      Remplacez les éléments suivants :

      • PUBLIC_KEY_ID : ID de clé publique du certificateur.
      • NOTE_URI : URI de la note Container Analysis associée au certificateur.
    6. Créez un fichier JSON décrivant l'attestation dans /tmp/attestation.json :

      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": "${PUBLIC_KEY_ID}",
                   "signature": "${PAYLOAD_SIGNATURE}"
               }
           ]
        }
      }
      EOM
      
    7. 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/"
      

Vous avez créé l'attestation.

Vérifier que le certificat a été créé

Pour vérifier que l'attestation a été créée, vous pouvez répertorier les attestations associées à l'image.

gcloud

Pour récupérer la liste des attestations, saisissez la commande suivante :

gcloud container binauthz attestations list\
    --project="${ATTESTATION_PROJECT_ID}"\
    --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}"\
    --artifact-url="${IMAGE_TO_ATTEST}"

API REST

Pour demander une liste d'attestations, saisissez la commande suivante :

curl -X GET \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: ${ATTESTOR_PROJECT_ID}" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}/occurrences?filter=resourceUrl%3D%22https%3A%2F%2F$(jq -rn --arg x ${IMAGE_TO_ATTEST} '$x|@uri')%22

S'il existe de nombreuses attestations, la réponse peut contenir une valeur nextPageToken. Dans ce cas, vous pouvez récupérer la page de résultats suivante en répétant la requête, en ajoutant un paramètre de requête pageToken comme suit :

NEXT_PAGE_TOKEN=NEXT_PAGE_TOKEN
curl -X GET \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: ${ATTESTOR_PROJECT_ID}" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}/occurrences?filter=resourceUrl%3D%22https%3A%2F%2F$(jq -rn --arg x ${IMAGE_TO_ATTEST} '$x|@uri')%22&pageToken=${NEXT_PAGE_TOKEN}

Remplacez NEXT_PAGE_TOKEN par la valeur nextPageToken dans la réponse de la requête précédente.

Lorsque nextPageToken est vide, cela signifie qu'il n'y a plus de résultats.

Supprimer l'attestation

Avant de supprimer l'attestation, vous devez effectuer les opérations suivantes :

  1. Découvrez les conséquences de sa suppression. La suppression d'une attestation bloque à terme le déploiement des images de conteneurs associées à l'attestation.

  2. Arrêtez tous les conteneurs en cours d'exécution associés aux attestations que vous souhaitez supprimer.

  3. Supprimez toutes les copies des attestations, où qu'elles se trouvent, par exemple les attestations des dépôts Artifact Registry et Container Analysis.

  4. Assurez-vous que le déploiement des images concernées est bloqué en essayant de les redéployer.

Pour supprimer une attestation, exécutez les commandes suivantes :

  1. Répertoriez les attestations :

    gcloud container binauthz attestations list \
      --attestor-project=${ATTESTOR_PROJECT_ID} \
      --attestor=${ATTESTOR_NAME}
    

    L'attestation contient un ID d'occurrence. La sortie ressemble à ceci :

    projects/ATTESTOR_PROJECT_ID/occurrences/OCCURRENCE_ID
    
  2. Enregistrez l'ID de l'occurrence.

    Enregistrez l'ID de l'occurrence de l'attestation que vous souhaitez supprimer.

    OCCURRENCE_ID=OCCURRENCE_ID
    
  3. Supprimez l'attestation :

    curl -H "Authorization: Bearer $(gcloud auth print-access-token)" -X DELETE \
      https://containeranalysis.googleapis.com/v1beta1/projects/${ATTESTATION_PROJECT_ID}/occurrences/${OCCURRENCE_ID}
    

    Vérifiez que les attestations ont été supprimées en répertoriant à nouveau les attestations.

Étape suivante