יצירת אישורים

בדף הזה מוסבר איך ליצור אישור של Binary Authorization.

אתם משתמשים באישורים כדי לאשר פריסה של קובצי אימג' ספציפיים של קונטיינרים בפלטפורמות כמו Google Kubernetes Engine‏ (GKE) ו-Cloud Run. כדי להשתמש באישורים, צריך לדרוש אישורים בכלל המתאים במדיניות.

אישור יחיד יכול לאשר תמונות זהות שמאוחסנות בכמה מיקומים שונים או בכמה רישומים שונים, כמו Artifact Registry,‏ Container Registry או רישום חיצוני של קונטיינרים.

בזמן הפריסה, Binary Authorization משתמש במאמתים כדי לאמת הצהרות.

כדי להגדיר את Binary Authorization ב-Cloud Run, ב-GKE, ב-Google Distributed Cloud וב-Cloud Service Mesh, אפשר לעיין במאמר הגדרה לפי פלטפורמה ולבחור את הפלטפורמה הרצויה.

משתמשי GKE: במדריך המלא הזה מוסבר איך להשתמש ב-Binary Authorization וב-Google Kubernetes Engine‏ (GKE) כדי לאכוף אימותים. אפשר לעיין במאמרים תחילת העבודה עם כלי שורת הפקודה או תחילת העבודה עם מסוף Google Cloud .

לפני שמתחילים

במאמר סקירה כללית של הצהרות מפורטים השלבים שצריך לבצע לפני שיוצרים הצהרה.

  1. הפעלת Binary Authorization

  2. יוצרים מאמתים באמצעות Google Cloud המסוף,‏ Google Cloud CLI או API בארכיטקטורת REST.

הגדרת הסביבה

  1. מציינים את מזהי הפרויקטים:

    ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID
    ATTESTATION_PROJECT_ID=ATTESTATION_PROJECT_ID
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ATTESTOR_PROJECT_ID: שם הפרויקט שבו מאחסנים את המאמתים
    • ATTESTATION_PROJECT_ID: שם הפרויקט שבו מאחסנים את האישורים

    אם רוצים שהאישור ייווצר באותו פרויקט שבו נוצרו המאמתים, צריך להשתמש באותו מזהה פרויקט בשני המשתנים. במאמר הגדרה של כמה פרויקטים יש מדריך מקיף שמסביר איך להשתמש בפרויקטים שונים כדי להדגים הפרדה בין תפקידים.

  2. מציינים את השם של המאשר ואת פרטי התמונה:

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

    מחליפים את מה שכתוב בשדות הבאים:

    • ATTESTOR_NAME: השם של הגורם המאמת, למשל build-secure או prod-qa.
    • IMAGE_PATH: ‏URI שמייצג נתיב של תמונה. למרות שכתובת ה-URI חייבת לכלול דומיין ושם תמונה, היא לא צריכה להתייחס לתמונה בפועל. אין גישה לתמונות במהלך יצירת האישור. דוגמאות לנתיבי תמונות:

      • us-docker.pkg.dev/google-samples/containers/gke/hello-app
      • gcr.io/example-project/quickstart-image
      • example.com/hello-app.
    • IMAGE_DIGEST: ה-digest של מניפסט התמונה. לדוגמה, sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567 הוא הגיבוב של התמונה שמשויך לנתיב התמונה us-docker.pkg.dev/google-samples/containers/gke/hello-app. במאמר ניהול תמונות מוסבר איך מקבלים את ה-digest של תמונה ב-Artifact Registry. במאמר הצגת רשימת הגרסאות של תמונה מוסבר איך מקבלים את ה-digest של תמונה ב-Container Registry.

הענקת תפקידים בניהול הזהויות והרשאות הגישה

כדי ליצור אישורים, צריך להקצות את התפקידים הבאים בניהול הזהויות והרשאות הגישה (IAM) לזהות שיוצרת את מאמת האישורים, באופן הבא:

  • roles/containeranalysis.notes.attacher במשאב ההערה שמשויך לגורם המאמת (attestor).
  • roles/containeranalysis.occurrences.editor במשאב של פרויקט האימות.

יוצרים אימות (attestation) על סמך גורם מאמת (attestor). המאשר משויך להערה של ניתוח ארטיפקטים. יצירת אישור בתורה יוצרת מופע של Artifact Analysis ומצרפת אותו להערה.

מידע נוסף על הענקת גישה

במאמר יצירת אישורים באמצעות Cloud Build מוסבר איך ליצור אישור בצינור Cloud Build.

יצירת אישור

יצירת אישור באמצעות מפתח שמאוחסן באופן מקומי

כדי ליצור אישורים שחתומים באמצעות מפתח מקומי:

  1. יוצרים קובץ מטען ייעודי (payload) של חתימה:

    gcloud

    כדי ליצור את קובץ המטען הייעודי (payload) של החתימה, מזינים את הפקודה הבאה:

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

    קובץ המטען הייעודי (payload) בפורמט JSON נראה כמו הפלט הבא:

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

    יוצרים קובץ מטען ייעודי (payload) בשם /tmp/generated_payload.json באמצעות משתני הסביבה שהגדרתם קודם במסמך הזה:

    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. חותמים על מטען הייעודי (payload) באמצעות המפתח הפרטי כדי ליצור קובץ חתימה.

    במדריך הזה נעשה שימוש באלגוריתם המומלץ Elliptic Curve Digital Signature Algorithm (ECDSA) לחתימה. אפשר גם להשתמש באלגוריתם RSA. מידע נוסף על אלגוריתמים לחתימה מופיע במאמר מטרות ואלגוריתמים של מפתחות. במדריך הזה נעשה שימוש גם בפורמט החתימה של תשתית מפתח ציבורי (X.509) ‏(PKIX). אפשר גם להשתמש ב-PGP.

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

    מחליפים את PRIVATE_KEY_FILE בנתיב למפתח הפרטי שיצרתם כשבניתם את המאמת.

  3. מקבלים את מזהה המפתח הציבורי.

    אפשר לאחזר את מזהה המפתח הציבורי מהמאמת באמצעות הפקודה הבאה:

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
    
  4. יוצרים את האישור:

    gcloud

    כדי ליצור ולאמת את ההצהרה, מזינים את הפרטים הבאים:

    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
    

    הדגל validate בודק שאפשר לאמת את האישור על ידי המאשר שהגדרתם במדיניות.

    הערה: מזהה המפתח יכול להיות כל מחרוזת.

    ‫API בארכיטקטורת REST

    כדי ליצור את האישור:

    1. מאחזרים את הגורם המאשר שמשויך לאישור ומוציאים את מזהה המפתח הציבורי שמאוחסן:

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

      התגובה של Binary Authorization היא אובייקט JSON שדומה לזה:

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

      המפתח הציבורי מופיע בשדה id.

    2. יוצרים קובץ JSON ב-/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. יוצרים את האישור:

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

יצירת אישור באמצעות Cloud KMS

כדי ליצור אישור באמצעות Cloud Key Management Service:

  1. יוצרים משתני סביבה:

    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
    

    מחליפים את מה שכתוב בשדות הבאים:

    • KMS_KEY_PROJECT_ID: מזהה הפרויקט שבו מאוחסנים המפתחות של Cloud Key Management Service
    • KMS_KEY_LOCATION: המיקום של המפתח (global הוא ברירת המחדל)
    • KMS_KEYRING_NAME: השם של אוסף המפתחות
    • KMS_KEY_NAME: השם של המפתח
    • KMS_KEY_VERSION: גרסת המפתח
  2. חותמים ויוצרים את האישור:

    gcloud

    מזינים את הפקודה הבאה:

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

    הדגל validate בודק שאפשר לאמת את האישור על ידי המאשר שהגדרתם במדיניות.

    ‫API בארכיטקטורת REST

    1. יוצרים קובץ מטען ייעודי (payload) בשם /tmp/generated_payload.json באמצעות משתני הסביבה שהגדרתם למעלה:

      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. חתימה על קובץ המטען הייעודי:

      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
      

      מחליפים את DIGEST_ALGORITHM באלגוריתם לעיבוד הקלט. בדוגמאות במדריך הזה נעשה שימוש ב-sha256 digest. אפשר להשתמש ב-sha256, ב-sha384 או ב-sha512.

      בדוגמה הזו, הפלט אמור להיראות כך:

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

      בפלט הזה, SIGNATURE הוא החתימה בקידוד base64 של קובץ המטען הייעודי.

    3. שומרים את החתימה במשתנה סביבה:

      PAYLOAD_SIGNATURE=PAYLOAD_SIGNATURE
      
    4. מאחזרים את המאמת שבשמו חותמים על האישור, ומחלצים את מזהה המפתח הציבורי ומזהה ההערה שמאוחסנים:

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

      התגובה של Binary Authorization היא אובייקט JSON שדומה לזה:

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

      מזהה המפתח הציבורי מופיע בשדה id ומזהה ההערה מופיע בשדה noteReference.

    5. שומרים את מזהה המפתח הציבורי במשתנה סביבה:

      PUBLIC_KEY_ID="PUBLIC_KEY_ID"
      NOTE_URI="NOTE_URI"
      

      מחליפים את מה שכתוב בשדות הבאים:

      • PUBLIC_KEY_ID: המזהה של המפתח הציבורי של הגורם המאשר.
      • NOTE_URI: ה-URI של הערת Artifact Analysis שמשויכת לגורם המאמת (attestor).
    6. יוצרים קובץ JSON ב-/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. יוצרים את האישור:

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

יצרתם את האישור.

בדיקה שהאישור נוצר

כדי לוודא שהאישור נוצר, אפשר להציג רשימה של אישורים שמשויכים לתמונה.

gcloud

כדי לאחזר רשימה של אישורים, מזינים את הפקודה הבאה:

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

‫API בארכיטקטורת REST

כדי לבקש רשימה של אישורים, מזינים את הפקודה הבאה:

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

אם יש הרבה אישורים, יכול להיות שהתשובה תכיל ערך nextPageToken. במקרה כזה, אפשר לאחזר את דף התוצאות הבא על ידי חזרה על הבקשה והוספה של פרמטר השאילתה pageToken, באופן הבא:

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}

מחליפים את NEXT_PAGE_TOKEN בערך nextPageToken בתגובה מהבקשה הקודמת.

אם nextPageToken ריק, זה אומר שאין יותר תוצאות.

מחיקת האישור

לפני שמוחקים את האישור, כדאי לבצע את הפעולות הבאות:

  1. חשוב להבין את ההשלכות של מחיקת החשבון. מחיקה של אירוע אישור תחסום בסופו של דבר פריסה של תמונות קונטיינר שמשויכות לאישור.

  2. מפסיקים את כל הקונטיינרים הפעילים שמשויכים לאישורים שרוצים למחוק.

  3. מוחקים את כל העותקים של האישורים בכל מקום שהם נמצאים בו, למשל אישורים במאגרי Artifact Registry ו-Artifact Analysis.

  4. כדי לוודא שהתמונות המושפעות באמת חסומות, צריך לנסות לפרוס אותן מחדש.

כדי למחוק אישור, מריצים את הפקודות הבאות:

  1. הצגת רשימת אישורים:

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

    האישור מכיל מזהה של מקרה. הפלט אמור להיראות כך:

    projects/ATTESTOR_PROJECT_ID/occurrences/OCCURRENCE_ID
    
  2. שומרים את מזהה המופע.

    שומרים את מזהה המופע של האישור שרוצים למחוק.

    OCCURRENCE_ID=OCCURRENCE_ID
    
  3. מוחקים את האישור:

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

    כדי לוודא שהאישורים נמחקו, מריצים שוב את הפקודה לרישום האישורים.

המאמרים הבאים