1. מבוא
Binary Authorization הוא אמצעי אבטחה בזמן הפריסה, שמבטיח שרק תמונות קונטיינר מהימנות ייפרסו ב-Google Kubernetes Engine (GKE) או ב-Cloud Run. באמצעות Binary Authorization, אתם יכולים לדרוש חתימה של תמונות על ידי רשויות מהימנות במהלך תהליך הפיתוח, ולאחר מכן לאכוף את אימות החתימה במהלך הפריסה. אכיפת האימות מאפשרת לכם לשלוט טוב יותר בסביבת הקונטיינר, כי היא מבטיחה שרק תמונות מאומתות ישולבו בתהליך ה-build וההפצה.
התרשים הבא מציג את הרכיבים בהגדרה של Binary Authorization/Cloud Build:
**איור 1.**צינור Cloud Build שיוצר אישור של Binary Authorization.
בצינור הזה:
- הקוד ליצירת קובץ אימג' של קונטיינר מועבר למאגר קוד מקור, כמו Cloud Source Repositories.
- כלי לאינטגרציה רציפה (CI), Cloud Build יוצר ובודק את הקונטיינר.
- ה-build מעביר את קובץ האימג' של הקונטיינר אל Container Registry או אל מאגר אחר שבו מאוחסנים קובצי האימג' שנוצרו.
- Cloud Key Management Service, שמספק ניהול מפתחות לצמד מפתחות קריפטוגרפיים, חותם על קובץ האימג' של הקונטיינר. החתימה שמתקבלת מאוחסנת באישור חדש שנוצר.
- בזמן הפריסה, הגורם המאשר מאמת את האישור באמצעות המפתח הציבורי מזוג המפתחות. Binary Authorization אוכף את המדיניות על ידי דרישה של אימותים (attestations) חתומים כדי לפרוס את קובץ אימג' של קונטיינר.
בשיעור ה-Lab הזה נתמקד בכלים ובטכניקות לאבטחת ארטיפקטים שנפרסו. בחינת ה-Lab הזו מתמקדת בארטיפקטים (מאגרי מידע) אחרי שהם נוצרו אבל לפני שהם נפרסו בסביבה מסוימת.
מה תלמדו
- חתימה על תמונות
- מדיניות בקרה על אישור בקשות
- חתימה על תמונות סרוקות
- אישור תמונות חתומות
- חסימה של תמונות לא חתומות
2. הגדרה ודרישות
הגדרת סביבה בקצב אישי
- נכנסים ל-מסוף Google Cloud ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. אם עדיין אין לכם חשבון Gmail או Google Workspace, אתם צריכים ליצור חשבון.



- שם הפרויקט הוא השם המוצג למשתתפים בפרויקט. זו מחרוזת תווים שלא נמצאת בשימוש ב-Google APIs. אפשר לעדכן את המיקום הזה בכל שלב.
- מזהה הפרויקט הוא ייחודי לכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו אחרי שהוא מוגדר. מסוף Cloud יוצר באופן אוטומטי מחרוזת ייחודית, ובדרך כלל לא צריך לדעת מה היא. ברוב ה-Codelabs, תצטרכו להפנות למזהה הפרויקט (בדרך כלל הוא מזוהה כ-
PROJECT_ID). אם אתם לא אוהבים את המזהה שנוצר, אתם יכולים ליצור מזהה אקראי אחר. אפשר גם לנסות שם משתמש משלכם ולבדוק אם הוא זמין. אי אפשר לשנות את ההגדרה הזו אחרי השלב הזה, והיא תישאר כזו למשך הפרויקט. - לידיעתכם, יש ערך שלישי, מספר פרויקט, שחלק מממשקי ה-API משתמשים בו. מידע נוסף על שלושת הערכים האלה מופיע במאמרי העזרה.
- בשלב הבא, תצטרכו להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבי Cloud או בממשקי API של Cloud. העלות של התרגול הזה לא אמורה להיות גבוהה, ואולי לא תהיה עלות בכלל. כדי להשבית את המשאבים ולא לחייב אתכם אחרי שתסיימו את המדריך הזה, תוכלו למחוק את המשאבים שיצרתם או למחוק את כל הפרויקט. משתמשים חדשים ב-Google Cloud זכאים לתוכנית תקופת ניסיון בחינם בשווי 300$.
הגדרת הסביבה
ב-Cloud Shell, מגדירים את מזהה הפרויקט ואת מספר הפרויקט. שומרים אותם כמשתנים PROJECT_ID ו-PROJECT_ID.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
--format='value(projectNumber)')
הפעלת שירותים
מפעילים את כל השירותים הנדרשים:
gcloud services enable \
cloudkms.googleapis.com \
cloudbuild.googleapis.com \
container.googleapis.com \
containerregistry.googleapis.com \
artifactregistry.googleapis.com \
containerscanning.googleapis.com \
ondemandscanning.googleapis.com \
binaryauthorization.googleapis.com
יצירת מאגר Artifact Registry
בשיעור ה-Lab הזה נשתמש ב-Artifact Registry כדי לאחסן ולסרוק את התמונות. יוצרים את המאגר באמצעות הפקודה הבאה.
gcloud artifacts repositories create artifact-scanning-repo \
--repository-format=docker \
--location=us-central1 \
--description="Docker repository"
מגדירים את Docker כך שישתמש בפרטי הכניסה שלכם ב-gcloud כשניגשים אל Artifact Registry.
gcloud auth configure-docker us-central1-docker.pkg.dev
יצירה של ספריית עבודה ומעבר אליה
mkdir vuln-scan && cd vuln-scan
הגדרת תמונה לדוגמה
יוצרים קובץ בשם Dockerfile עם התוכן הבא.
cat > ./Dockerfile << EOF
from python:3.8-slim
# App
WORKDIR /app
COPY . ./
RUN pip3 install Flask==2.1.0
RUN pip3 install gunicorn==20.1.0
CMD exec gunicorn --bind :\$PORT --workers 1 --threads 8 main:app
EOF
יוצרים קובץ בשם main.py עם התוכן הבא
cat > ./main.py << EOF
import os
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
name = os.environ.get("NAME", "Worlds")
return "Hello {}!".format(name)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF
יצירה של קובץ האימג' ושליחתו ל-AR
משתמשים ב-Cloud Build כדי ליצור את הקונטיינר ולהעביר אותו בדחיפה באופן אוטומטי ל-Artifact Registry.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
3. חתימה על תמונות
מהו מאמת (Attestor)
גורם מאמת
- האדם או התהליך הזה אחראים לקישור אחד בשרשרת האמון של המערכת.
- הם מחזיקים במפתח קריפטוגרפי, וחותמים על תמונה אם היא עוברת את תהליך האישור שלהם.
- יוצר המדיניות קובע את המדיניות בצורה כללית ומופשטת, אבל הגורם המאשר אחראי לאכוף באופן קונקרטי היבט מסוים של המדיניות.
- יכול להיות שזה אדם אמיתי, כמו בודק QA או מנהל, או שזה בוט במערכת CI.
- האבטחה של המערכת תלויה במידת המהימנות שלהם, ולכן חשוב לשמור על האבטחה של המפתחות הפרטיים שלהם.
כל אחד מהתפקידים האלה יכול לייצג אדם יחיד או צוות של אנשים בארגון. בסביבת ייצור, התפקידים האלה כנראה ינוהלו על ידי פרויקטים נפרדים ב-Google Cloud Platform (GCP), והגישה למשאבים תשותף ביניהם באופן מוגבל באמצעות Cloud IAM.

המאמתים ב-Binary Authorization מיושמים על גבי Cloud Container Analysis API, ולכן חשוב להסביר איך הם פועלים לפני שממשיכים. ממשק Container Analysis API נועד לאפשר לכם לשייך מטא-נתונים לתמונות קונטיינר ספציפיות.
לדוגמה, אפשר ליצור הערה כדי לעקוב אחרי נקודת החולשה Heartbleed. ספקי אבטחה יוצרים סורקים כדי לבדוק את קובצי האימג' של הקונטיינרים ולחפש את נקודת החולשה, ויוצרים אירוע שמשויך לכל קונטיינר שנפרץ.

בנוסף למעקב אחרי נקודות חולשה, Container Analysis נועד להיות API גנרי של מטא-נתונים. Binary Authorization משתמש ב-Container Analysis כדי לשייך חתימות לקובצי האימג' של הקונטיינרים שהוא מאמת**.** הערה של Container Analysis משמשת לייצוג גורם מאמת (attestor) יחיד, ואירועים נוצרים ומשויכים לכל קונטיינר שאושר על ידי גורם מאמת (attestor).
ב-Binary Authorization API נעשה שימוש במושגים attestors (מאמתים) ו-attestations (אישורים), אבל הם מיושמים באמצעות Notes (הערות) ו-Occurrences (מופעים) תואמים ב-Container Analysis API.

יצירת הערה של מאשר
הערת גורם מאמת (attestor) היא פשוט נתון קטן שמשמש כתווית לסוג החתימה שמוחלת. לדוגמה, הערה אחת יכולה לציין סריקת פגיעות, והערה אחרת יכולה לשמש לאישור בקרת איכות. ההערה תצוין במהלך תהליך החתימה.

יצירת הערה
cat > ./vulnz_note.json << EOM
{
"attestation": {
"hint": {
"human_readable_name": "Container Vulnerabilities attestation authority"
}
}
}
EOM
שמירת ההערה
NOTE_ID=vulnz_note
curl -vvv -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @./vulnz_note.json \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
אימות ההערה
curl -vvv \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
ההערה שלכם נשמרת עכשיו ב-Container Analysis API.
יצירת גורם מאמת (attestor)
המאמתים משמשים לביצוע תהליך החתימה בפועל של התמונה, והם יצרפו מופע של ההערה לתמונה לצורך אימות מאוחר יותר. כדי להשתמש בבודק, צריך גם לרשום את ההערה ב-Binary Authorization:

יצירת גורם מאמת
ATTESTOR_ID=vulnz-attestor
gcloud container binauthz attestors create $ATTESTOR_ID \
--attestation-authority-note=$NOTE_ID \
--attestation-authority-note-project=${PROJECT_ID}
אימות המאשר
gcloud container binauthz attestors list
שימו לב שהשורה האחרונה מציינת NUM_PUBLIC_KEYS: 0 שתספקו מפתחות בשלב מאוחר יותר
חשוב גם לדעת ש-Cloud Build יוצר באופן אוטומטי את built-by-cloud-build המאשר בפרויקט כשמריצים build שיוצר תמונות. לכן הפקודה שלמעלה מחזירה שני מאמתים, vulnz-attestor ו-built-by-cloud-build. אחרי שקובצי האימג' נוצרים בהצלחה, מערכת Cloud Build חותמת עליהם באופן אוטומטי ויוצרת אישורים.
הוספת תפקיד IAM
לחשבון השירות של Binary Authorization צריכות להיות הרשאות לצפייה בהערות האישור. הענקת הגישה באמצעות קריאה ל-API
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")
BINAUTHZ_SA_EMAIL="service-${PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
cat > ./iam_request.json << EOM
{
'resource': 'projects/${PROJECT_ID}/notes/${NOTE_ID}',
'policy': {
'bindings': [
{
'role': 'roles/containeranalysis.notes.occurrences.viewer',
'members': [
'serviceAccount:${BINAUTHZ_SA_EMAIL}'
]
}
]
}
}
EOM
שימוש בקובץ ליצירת מדיניות IAM
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @./iam_request.json \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"
הוספת מפתח KMS
כדי להשתמש ב-attestor הזה, הרשות שלכם צריכה ליצור זוג מפתחות קריפטוגרפיים שאפשר להשתמש בהם לחתימה על קובצי אימג' בקונטיינרים. אפשר לעשות את זה באמצעות Google Cloud Key Management Service (KMS).
קודם מוסיפים כמה משתני סביבה כדי לתאר את המפתח החדש
KEY_LOCATION=global
KEYRING=binauthz-keys
KEY_NAME=codelab-key
KEY_VERSION=1
יצירת אוסף מפתחות להחזקת קבוצה של מפתחות
gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"
יצירת זוג מפתחות אסימטריים חדש לחתימה בשביל המאמת
gcloud kms keys create "${KEY_NAME}" \
--keyring="${KEYRING}" --location="${KEY_LOCATION}" \
--purpose asymmetric-signing \
--default-algorithm="ec-sign-p256-sha256"
המפתח אמור להופיע בדף KMS במסוף Google Cloud.
עכשיו משייכים את המפתח לגורם המאמת (attestor) באמצעות הפקודה gcloud binauthz:
gcloud beta container binauthz attestors public-keys add \
--attestor="${ATTESTOR_ID}" \
--keyversion-project="${PROJECT_ID}" \
--keyversion-location="${KEY_LOCATION}" \
--keyversion-keyring="${KEYRING}" \
--keyversion-key="${KEY_NAME}" \
--keyversion="${KEY_VERSION}"
אם מדפיסים שוב את רשימת הרשויות, אמור להופיע בה מפתח רשום:
gcloud container binauthz attestors list
יצירת אישור חתום
בשלב הזה, התכונות מוגדרות כך שתוכלו לחתום על תמונות. משתמשים ב-Attestor שיצרתם קודם כדי לחתום על קובץ האימג' של הקונטיינר שעבדתם איתו.
אישור צריך לכלול חתימה קריפטוגרפית כדי לציין שהמאשר אימת תמונה מסוימת של מאגר ושהיא בטוחה להרצה באשכול. כדי לציין איזה קובץ אימג' של קונטיינר צריך לאמת, צריך לקבוע את ה-digest שלה.
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:latest \
--format='get(image_summary.digest)')
עכשיו אפשר להשתמש ב-gcloud כדי ליצור את האישור. הפקודה מקבלת את פרטי המפתח שרוצים להשתמש בו לחתימה, ואת קובץ אימג' של קונטיינר הספציפי שרוצים לאשר.
gcloud beta container binauthz attestations sign-and-create \
--artifact-url="${CONTAINER_PATH}@${DIGEST}" \
--attestor="${ATTESTOR_ID}" \
--attestor-project="${PROJECT_ID}" \
--keyversion-project="${PROJECT_ID}" \
--keyversion-location="${KEY_LOCATION}" \
--keyversion-keyring="${KEYRING}" \
--keyversion-key="${KEY_NAME}" \
--keyversion="${KEY_VERSION}"
במונחים של Container Analysis, הפעולה הזו תיצור אירוע חדש ותצרף אותו להערה של גורם מאמת (attestor). כדי לוודא שהכול פעל כמו שצריך, אפשר להציג את האישורים
gcloud container binauthz attestations list \
--attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}
4. מדיניות בקרה על אישור בקשות
Binary Authorization היא תכונה ב-GKE וב-Cloud Run שמאפשרת לאמת כללים לפני שמאפשרים להריץ קובץ אימג' של קונטיינר. האימות מתבצע בכל בקשה להפעלת תמונה, בין אם היא מגיעה מצינור CI/CD מהימן או ממשתמש שמנסה לפרוס תמונה באופן ידני. היכולת הזו מאפשרת לכם לאבטח את סביבות זמן הריצה בצורה יעילה יותר מאשר בדיקות של צינור עיבוד הנתונים של CI/CD בלבד.
כדי להבין את היכולת הזו, תשנו את מדיניות ברירת המחדל של GKE כדי לאכוף כלל הרשאה מחמיר.
יצירת אשכול GKE
יוצרים את אשכול GKE עם הפעלת Binary Authorization:
gcloud beta container clusters create binauthz \
--zone us-central1-a \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE
מאפשרים ל-Cloud Build לפרוס את האשכול הזה:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/container.developer"
מדיניות מתן הרשאה לכל קובצי ה-Cookie
קודם כל, צריך לאמת את מצב המדיניות שמוגדר כברירת מחדל ואת היכולת שלכם לפרוס תמונה כלשהי
- בדיקת המדיניות הקיימת
gcloud container binauthz policy export
- שימו לב שמדיניות האכיפה מוגדרת ל
ALWAYS_ALLOW
evaluationMode: ALWAYS_ALLOW
- פריסת דוגמה כדי לוודא שאפשר לפרוס כל דבר
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- אימות הפריסה
kubectl get pods
יוצג הפלט הבא

- מחיקת פריסה
kubectl delete pod hello-server
מדיניות דחייה של כולם
עכשיו מעדכנים את המדיניות כך שלא תהיה אפשרות להציג תמונות.
- ייצוא המדיניות הנוכחית לקובץ שאפשר לערוך
gcloud container binauthz policy export > policy.yaml
- שנה את המדיניות
בכלי לעריכת טקסט, משנים את הערך של evaluationMode מ-ALWAYS_ALLOW ל-ALWAYS_DENY.
edit policy.yaml
קובץ ה-YAML של המדיניות צריך להיראות כך:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_DENY enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
המדיניות הזו פשוטה יחסית. השורה globalPolicyEvaluationMode מציינת שהמדיניות הזו מרחיבה את המדיניות הגלובלית שהוגדרה על ידי Google. כך כל הקונטיינרים הרשמיים של GKE יכולים לפעול כברירת מחדל. בנוסף, המדיניות מגדירה defaultAdmissionRule שקובעת שכל שאר הפודים יידחו. כלל ההרשאה כולל שורה של enforcementMode, שמציינת שצריך לחסום את כל הפודים שלא עומדים בדרישות של הכלל הזה, כך שהם לא יוכלו לפעול באשכול.
הוראות ליצירת כללי מדיניות מורכבים יותר זמינות במסמכי התיעוד של Binary Authorization.

- פותחים את הטרמינל, מחילים את המדיניות החדשה וממתינים כמה שניות עד שהשינוי יתעדכן.
gcloud container binauthz policy import policy.yaml
- ניסיון לפרוס עומס עבודה לדוגמה
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- הפריסה נכשלת עם ההודעה הבאה
Error from server (VIOLATES_POLICY): admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/google-samples/hello-app:1.0 denied by Binary Authorization default admission rule. Denied by always_deny admission rule
חזרה למדיניות שמאפשרת הכול
לפני שעוברים לקטע הבא, חשוב להחזיר את השינויים במדיניות
- שנה את המדיניות
בכלי לעריכת טקסט, משנים את הערך של evaluationMode מ-ALWAYS_DENY ל-ALWAYS_ALLOW.
edit policy.yaml
קובץ ה-YAML של המדיניות צריך להיראות כך:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_ALLOW enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- החלת המדיניות שהוחזרה
gcloud container binauthz policy import policy.yaml
5. חתימה על תמונות סרוקות
הפעלתם את חתימת התמונות והשתמשתם ב-Attestor באופן ידני כדי לחתום על תמונת הדוגמה. בפועל, כדאי להשתמש באישורים במהלך תהליכים אוטומטיים כמו צינורות עיבוד נתונים של CI/CD.
בקטע הזה מגדירים את Cloud Build כדי לאמת תמונות באופן אוטומטי
תפקידים
מוסיפים את התפקיד Binary Authorization Attestor Viewer לחשבון השירות ב-Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/binaryauthorization.attestorsViewer
הוספת התפקיד Cloud KMS CryptoKey Signer/Verifier לחשבון השירות של Cloud Build (חתימה מבוססת-KMS):
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/cloudkms.signerVerifier
מוסיפים את התפקיד Container Analysis Notes Attacher לחשבון השירות של Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/containeranalysis.notes.attacher
מתן גישה לחשבון השירות ב-Cloud Build
ל-Cloud Build צריכות להיות הרשאות גישה ל-API של סריקה לפי דרישה. נותנים גישה באמצעות הפקודות הבאות.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/ondemandscanning.admin"
הכנת שלב Custom Build ב-Cloud Build
כדי לפשט את תהליך האימות, נשתמש בשלב Custom Build ב-Cloud Build. Google מספקת את שלב ה-Build המותאם אישית הזה, שמכיל פונקציות עזר לייעול התהליך. לפני שמשתמשים בקוד של שלב בנייה בהתאמה אישית, צריך לבנות אותו בתוך קונטיינר ולהעביר אותו בדחיפה ל-Cloud Build. כדי לעשות זאת, מריצים את הפקודות הבאות:
git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
cd cloud-builders-community/binauthz-attestation
gcloud builds submit . --config cloudbuild.yaml
cd ../..
rm -rf cloud-builders-community
הוספת שלב חתימה לקובץ cloudbuild.yaml
בשלב הזה תוסיפו את שלב האימות לצינור Cloud Build.
- השלב של החתימה מפורט בהמשך.
לצפייה בלבד. אין להעתיק
#Sign the image only if the previous severity check passes
- id: 'create-attestation'
name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
args:
- '--artifact-url'
- 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image'
- '--attestor'
- 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
- '--keyversion'
- 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
- כותבים קובץ cloudbuild.yaml עם הצינור המלא שמופיע בהמשך.
cat > ./cloudbuild.yaml << EOF
steps:
# build
- id: "build"
name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
waitFor: ['-']
#Run a vulnerability scan at _SECURITY level
- id: scan
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
(gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--location us \
--format="value(response.scan)") > /workspace/scan_id.txt
#Analyze the result of the scan
- id: severity check
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi
#Retag
- id: "retag"
name: 'gcr.io/cloud-builders/docker'
args: ['tag', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#pushing to artifact registry
- id: "push"
name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#Sign the image only if the previous severity check passes
- id: 'create-attestation'
name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
args:
- '--artifact-url'
- 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good'
- '--attestor'
- 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
- '--keyversion'
- 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good
EOF
הרצת ה-Build
gcloud builds submit
בדיקת ה-build בהיסטוריה של Cloud Build
פותחים את Cloud Console ועוברים אל הדף Cloud Build History. בודקים את הגרסה האחרונה ואת הביצוע המוצלח של שלבי ה-Build.
6. אישור תמונות חתומות
בקטע הזה נעדכן את GKE כך שישתמש ב-Binary Authorization כדי לאמת שלתמונה יש חתימה מסריקת הפגיעויות לפני שמאפשרים להפעיל את התמונה.

עדכון המדיניות של GKE לדרישת אישור
כדי לדרוש שהתמונות ייחתמו על ידי הגורם המאשר, מוסיפים clusterAdmissionRules למדיניות GKE BinAuth
כרגע, באשכול מופעלת מדיניות עם כלל אחד: לאפשר קונטיינרים ממאגרים רשמיים ולדחות את כל השאר.
מחליפים את המדיניות בהגדרה המעודכנת באמצעות הפקודה שלמטה.
COMPUTE_ZONE=us-central1-a
cat > binauth_policy.yaml << EOM
defaultAdmissionRule:
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
evaluationMode: ALWAYS_DENY
globalPolicyEvaluationMode: ENABLE
clusterAdmissionRules:
${COMPUTE_ZONE}.binauthz:
evaluationMode: REQUIRE_ATTESTATION
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
requireAttestationsBy:
- projects/${PROJECT_ID}/attestors/vulnz-attestor
EOM
עכשיו אמור להיות לכם קובץ חדש בדיסק, שנקרא updated_policy.yaml. מעכשיו, במקום שהכלל שמוגדר כברירת מחדל ידחה את כל התמונות, הוא יבדוק קודם אם יש אימותים של המאמת.

מעלים את המדיניות החדשה ל-Binary Authorization:
gcloud beta container binauthz policy import binauth_policy.yaml
פריסה של תמונה חתומה
מקבלים את תקציר התמונה של התמונה הטובה
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:good \
--format='get(image_summary.digest)')
שימוש ב-digest בהגדרות של Kubernetes
cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
name: deb-httpd
spec:
selector:
app: deb-httpd
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb-httpd
spec:
replicas: 1
selector:
matchLabels:
app: deb-httpd
template:
metadata:
labels:
app: deb-httpd
spec:
containers:
- name: deb-httpd
image: ${CONTAINER_PATH}@${DIGEST}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
EOM
פריסת האפליקציה ב-GKE
kubectl apply -f deploy.yaml
בודקים את עומס העבודה במסוף ורושמים לעצמכם את הפריסה המוצלחת של התמונה.
7. חסימה של תמונות לא חתומות
יצירת תמונה
בשלב הזה תשתמשו ב-Docker מקומי כדי ליצור את קובץ האימג' במטמון המקומי.
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad .
דחיפת התמונה הלא חתומה למאגר
docker push us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
קבלת תקציר תמונה לתמונה לא טובה
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:bad \
--format='get(image_summary.digest)')
שימוש ב-digest בהגדרות של Kubernetes
cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
name: deb-httpd
spec:
selector:
app: deb-httpd
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb-httpd
spec:
replicas: 1
selector:
matchLabels:
app: deb-httpd
template:
metadata:
labels:
app: deb-httpd
spec:
containers:
- name: deb-httpd
image: ${CONTAINER_PATH}@${DIGEST}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
EOM
ניסיון לפרוס את האפליקציה ב-GKE
kubectl apply -f deploy.yaml
בודקים את עומס העבודה במסוף ורושמים את השגיאה שמציינת שהפריסה נדחתה:
No attestations found that were valid and signed by a key trusted by the attestor
8. מעולה!
כל הכבוד, סיימתם את ה-Codelab!
הנושאים שנדון בהם:
- חתימה על תמונות
- מדיניות בקרה על אישור בקשות
- חתימה על תמונות סרוקות
- אישור תמונות חתומות
- חסימה של תמונות לא חתומות
השלב הבא:
- אבטחת פריסות של תמונות ב-Cloud Run וב-Google Kubernetes Engine | מסמכי Cloud Build
- מדריך למתחילים: הגדרת מדיניות Binary Authorization באמצעות GKE | Google Cloud
הסרת המשאבים
כדי להימנע מחיובים בחשבון Google Cloud בגלל השימוש במשאבים שנעשה במסגרת המדריך הזה, אפשר למחוק את הפרויקט שמכיל את המשאבים, או להשאיר את הפרויקט ולמחוק את המשאבים בנפרד.
מחיקת הפרויקט
הדרך הקלה ביותר לבטל את החיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך.
—
העדכון האחרון: 21 במרץ 2023

