Attestierungen erstellen

Auf dieser Seite wird erläutert, wie Sie mithilfe der Befehlszeile eine Attestierung in der Binärautorisierung erstellen.

Die Anleitungen auf dieser Seite erläutern die Schritte, die ein Signaturgeber ausführen muss, um ein Container-Image für das Deployment zu autorisieren. In einem realen Szenario werden diese Schritte in ein Skript oder in einen automatisierten Vorgang eingebunden, das bzw. der durch einen maschinellen Prozess oder durch einen Nutzer ausgelöst werden kann und nicht manuell über die Befehlszeile eingegeben werden muss.

Übersicht

Eine Attestierung ist ein digital signiertes Dokument, das von einem Signaturgeber erstellt wurde und mit dem bestätigt wird, dass ein erforderlicher Prozess in der Pipeline abgeschlossen wurde und dass das resultierende Container-Image für das Deployment in GKE autorisiert ist. Die Attestierung selbst enthält den vollständigen Pfad zur Version des Container-Images, der in Ihrer Container-Image-Registry gespeichert. Außerdem enthält sie eine Signatur, die durch Signieren des global eindeutigen Digests erstellt wird, mit dem sich ein bestimmter Container-Image-Build identifizieren lässt.

Sie können eine Attestierung mithilfe einer PKIX-Signatur (empfohlen) oder einer PGP-Signatur erstellen. In dieser Anleitung wird für kryptografische Schlüssel das Format Public-Key-Infrastruktur (X.509) (PKIX) verwendet. Zum Signieren und Erstellen der Attestierung wird der empfohlene Elliptic Curve Digital Signing Algorithm (ECDSA) genutzt. Sie können zum Signieren auch RSA- oder PGP-Schlüssel verwenden. Weitere Informationen zu Signieralgorithmen finden Sie unter Schlüsselzwecke und Algorithmen.

Standardprojekt festlegen

Falls Sie noch kein Standardprojekt für Google Cloud festgelegt haben, gehen Sie so vor:

PROJECT_ID=PROJECT_ID
gcloud config set project ${PROJECT_ID}

Dabei ist PROJECT_ID der Name Ihres Projekts.

Umgebung einrichten

  1. Richten Sie Umgebungsvariablen zum Speichern Ihrer Projekt-IDs ein:

    ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID
    ATTESTATION_PROJECT_ID=ATTESTATION_PROJECT_ID
    

    Dabei gilt:

    • ATTESTOR_PROJECT_ID ist der Name des Projekts, in dem Sie die Attestierer speichern.
    • ATTESTATION_PROJECT_ID ist der Name des Projekts, in dem Sie die Attestierungen speichern.

    Wenn Ihr Attestiererprojekt mit Ihrem Attestierungsprojekt identisch ist, verwenden Sie für beide Variablen dieselbe Projekt-ID.

  2. Richten Sie Umgebungsvariablen zum Speichern des Namens des Attestierers ein, mit dem die Attestierung und der Registry-Pfad zum bereitzustellenden Image geprüft werden:

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

    Dabei gilt:

    • ATTESTOR_NAME ist der Name des Attestierers (z. B. build-secure oder prod-qa).
    • IMAGE_PATH ist der Pfad in Container Registry zu dem Image, das Sie bereitstellen möchten (z. B. gcr.io/example-project/quickstart-image).
    • PUBLIC_KEY_ID ist die ID, die dem öffentlichen Schlüssel aus dem von Ihnen generierten Schlüsselpaar zugeordnet ist. Der öffentliche Schlüssel selbst wird im Attestierer gespeichert.
    • PRIVATE_KEY_FILE ist die Datei, die den privaten Schlüssel aus dem generierten Schlüsselpaar enthält. Die Attestierungsnutzlast wird mit diesem Schlüssel signiert.
    • IMAGE_DIGEST ist der SHA-256-Digest des Image-Manifests (z. B. sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea882eb722c3be4). Informationen zum Abrufen des Image-Digests finden Sie unter Versionen eines Images auflisten in Container Registry.

Jedes Container-Image, das in Container-Registry oder in einer anderen Registry gespeichert ist, hat einen eindeutigen Pfad zu seinem Speicherort sowie einen SHA-256-Digest, der die Version des Images eindeutig identifiziert. Attestierungen verweisen auf den vollständigen Image-Pfad und den Digest. Damit können Sie bestimmte Versionen eines Images autorisieren.

Das folgende Beispiel zeigt einen vollständigen Registry-Pfad:

gcr.io/example-project/quickstart-image@sha256:bedb3feb23e81d162e33976fd7b245adff00379f4755c0213e84405e5b1e0988

Attestierung mit einer PKIX-Signatur mithilfe eines lokal gespeicherten Schlüssels erstellen

So gehen Sie bei Attestierungen vor, die mit einem öffentlichen PKIX-Schlüssel signiert wurden:

  1. Generieren Sie eine Attestierungsnutzlast, die auf den Registry-Pfad verweist und an die Binärautorisierung gesendet wird.
  2. Signieren Sie die Nutzlast und generieren Sie eine PKIX-Signaturdatei.
  3. Rufen Sie die ID des öffentlichen Schlüssels ab.
  4. Erstellen Sie die Attestierung mit der Signaturdatei und der ID des öffentlichen Schlüssels.

Attestierungsnutzlast erstellen

Die Attestierungsnutzlast ist eine Datei im JSON-Format, die auf den Speicherort des Container-Images verweist.

So erstellen Sie die Nutzlastdatei:

gcloud

Geben Sie Folgendes ein:

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

Die Nutzlastdatei sieht in etwa so aus:

{
  "critical": {
    "identity": {
      "docker-reference": "gcr.io/google-samples/hello-app"
    },
    "image": {
      "docker-manifest-digest": "sha256:bedb3feb23e81d162e33976fd7b245
adff00379f4755c0213e84405e5b1e0988"
    },
    "type": "Google cloud binauthz container signature"
  }
}

REST

Erstellen Sie eine Nutzlastdatei namens /tmp/generated_payload.json mit den oben festgelegten Umgebungsvariablen:

cat > /tmp/generated_payload.json << EOM
{
  "critical": {
    "identity": {
      "docker-reference": "${IMAGE_PATH}"
    },
    "image": {
      "${IMAGE_DIGEST}"
    },
    "type": "Google cloud binauthz container signature"
  }
}
EOM

Nutzlast signieren und Signaturdatei erstellen

Nachdem Sie die Nutzlastdatei erstellt haben, müssen Sie sie mit dem privaten kryptografischen Schlüssel aus dem zuvor generierten Schlüsselpaar signieren. Denken Sie daran, dass der entsprechende öffentliche Schlüssel im zugehörigen Attestierer gespeichert wurde. Der öffentliche Schlüssel in diesem Attestierer wird zum Prüfen dieser Signatur beim Deployment verwendet.

Informationen zum Erstellen eines Attestierers finden Sie unter Attestierer mithilfe der Befehlszeile erstellen und Attestierer mithilfe der Console erstellen.

Ein vollständiges Beispiel mit allen einzelnen Schritten erhalten Sie unter Erste Schritte mit der Befehlszeile und Erste Schritte mit der Console.

So signieren Sie die Nutzlastdatei:

  1. Signieren Sie die Nutzlast mit dem lokalen privaten PKIX-Schlüssel und geben Sie eine Signaturdatei aus:

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

    Die Signaturdatei ist eine digital signierte Version der JSON-Nutzlastdatei, die Sie oben erstellt haben.

ID des öffentlichen Schlüssels abrufen

Sie müssen, wenn Sie eine Attestierung erstellen, die ID eines öffentlichen Schlüssels zusammen mit der Signaturdatei an die Binärautorisierung senden.

So rufen Sie die ID des öffentlichen Schlüssels ab:

  1. Speichern Sie die ID des öffentlichen Schlüssels.

    Um die ID des öffentlichen Schlüssels des Attestierers aufzurufen, verwenden Sie gcloud container binauthz attestors describe ${ATTESTOR_NAME}:

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
    

Attestierung erstellen

gcloud

Zum Erstellen der Attestierung geben Sie Folgendes ein:

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

Alternativ können Sie Folgendes eingeben, um die Attestierung zu erstellen und um zu bestätigen, dass sie vom bereitgestellten Attestierer geprüft werden kann:

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

Hinweis: Die Schlüssel-ID kann ein beliebiger String sein.

REST

So erstellen Sie die Attestierung:

  1. Rufen Sie den mit der Attestierung verknüpften Attestierer ab und extrahieren Sie die gespeicherte ID des öffentlichen Schlüssels:

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

    Die Binärautorisierung gibt ein JSON-Objekt zurück, das in etwa so aussieht:

    {
      "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"
    }
    
  2. Erstellen Sie in einem Texteditor eine JSON-Datei in /tmp/attestation.json, in der die Attestierung beschrieben wird:

    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
    

    Dabei ist KEY_ID die ID des öffentlichen Schlüssels, die im vorherigen Schritt zurückgegeben wurde.

  3. Erstellen Sie die Attestierung:

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

Attestierung mit einer PKIX-Signatur erstellen, die auf dem Cloud Key Management Service basiert

So erstellen Sie eine Attestierung mit einer PKIX-Signatur, die auf dem Cloud Key Management Service basiert:

  1. Richten Sie Umgebungsvariablen zum Speichern von Informationen zu den Projekten ein, in denen Ihre Attestierungen, Attestierer und Cloud Key Management Service-Schlüssel gespeichert sind, sowie zum Speichern von Informationen zu Ihrem PKIX-Schlüsselpaar:

    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
    

    Dabei gilt:

    • KMS_KEY_PROJECT_ID ist die ID des Projekts, in dem Ihre Cloud Key Management Service-Schlüssel gespeichert sind.
    • KMS_KEY_LOCATION ist der Speicherort des Schlüssels (global ist die Standardeinstellung).
    • KMS_KEYRING_NAME ist der Name des Schlüsselbunds.
    • KMS_KEY_NAME ist der Name des Schlüssels.
    • KMS_KEY_VERSION ist die Schlüsselversion.
  2. Signieren Sie die Attestierung und erstellen Sie sie:

    gcloud

    Geben Sie Folgendes in die Befehlszeile ein:

    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

    1. Erstellen Sie eine Nutzlastdatei namens /tmp/generated_payload.json mit den oben festgelegten Umgebungsvariablen:

      cat > /tmp/generated_payload.json << EOM
      {
        "critical": {
          "identity": {
            "docker-reference": "${IMAGE_PATH}"
          },
          "image": {
            "${IMAGE_DIGEST}"
          },
          "type": "Google cloud binauthz container signature"
        }
      }
      EOM
      
    2. Signieren Sie die Nutzlastdatei:

      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
      

      Dabei steht DIGEST_ALGORITHM für sha256, sha384 oder sha512. Dies ist der Digest-Algorithmus der Schlüsselversion, die Sie zum Signieren verwenden.

      Mit diesem Befehl wird eine Datei namens /tmp/generated_payload.json.sig ausgegeben, die die digitale Signatur enthält.

    3. Rufen Sie den Attestierer ab, in dessen Namen Sie die Attestierung signieren, und extrahieren Sie die gespeicherte ID des öffentlichen Schlüssels:

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

      Die Binärautorisierung gibt ein JSON-Objekt zurück, das in etwa so aussieht:

      {
        "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"
      }
      
    4. Erstellen Sie in einem Texteditor eine JSON-Datei in /tmp/attestation.json, in der die Attestierung beschrieben wird:

      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
      

      Dabei ist KEY_ID die ID des öffentlichen Schlüssels, die im vorherigen Schritt zurückgegeben wurde.

    5. Erstellen Sie die Attestierung:

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

Attestierung auf Erstellung prüfen

So überprüfen Sie, ob die Attestierung erstellt wurde:

gcloud

Geben Sie Folgendes in die Befehlszeile ein:

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

REST

Rufen Sie eine Liste der Attestierungen ab:

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"

Wenn viele Attestierungen vorhanden sind, wird in der Antwort eventuell ein "nextPageToken" zurückgegeben. In diesem Fall sollte die Anfrage wiederholt werden, wobei für den Abfrageparameter "pageToken" der Wert "nextPageToken" festgelegt sein sollte, um weitere Attestierungen abzurufen. Wenn "nextPageToken" leer ist, bedeutet dies, dass keine weiteren Ergebnisse vorhanden sind.

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

Weitere Informationen