1. מבוא
Container Analysis מספק בדיקות לאיתור נקודות חולשה ואחסון מטא-נתונים של קונטיינרים. שירות הסריקה מבצע בדיקות לאיתור נקודות חולשה בתמונות ב-Artifact Registry וב-Container Registry, ולאחר מכן מאחסן את המטא-נתונים שנוצרים ומאפשר שימוש בהם דרך ממשק API. אחסון מטא-נתונים מאפשר לכם לאחסן מידע ממקורות שונים, כולל סריקת נקודות חולשה, שירותי Google Cloud וספקי צד שלישי.
בדיקת נקודות החולשה יכולה להתבצע באופן אוטומטי או על פי דרישה:
- כשהסריקה האוטומטית מופעלת, הסריקה מופעלת באופן אוטומטי בכל פעם שדוחפים תמונה חדשה ל-Artifact Registry או ל-Container Registry. המידע על נקודות החולשה מתעדכן כל הזמן כשמתגלות נקודות חולשה חדשות.
- כשהאפשרות On-Demand Scanning מופעלת, צריך להריץ פקודה כדי לסרוק קובץ אימג' מקומי או קובץ אימג' ב-Artifact Registry או ב-Container Registry. סריקת קונטיינרים על פי דרישה מאפשרת לכם לקבוע מתי תסרקו את הקונטיינרים. לדוגמה, אפשר לסרוק קובץ אימג' שנוצר באופן מקומי ולתקן נקודות חולשה לפני שמאחסנים אותו במרשם. תוצאות הסריקה זמינות למשך עד 48 שעות לאחר השלמת הסריקה, ומידע על נקודות חולשה לא מתעדכן אחרי הסריקה.
כשמשתמשים ב-Container Analysis שמשולב בצינור עיבוד הנתונים של CI/CD, אפשר לקבל החלטות על סמך המטא-נתונים האלה. לדוגמה, אפשר להשתמש ב-Binary Authorization כדי ליצור מדיניות פריסה שמאפשרת פריסה רק של תמונות תואמות מרשומות מהימנות.
מה תלמדו
- איך מפעילים סריקה אוטומטית
- איך מבצעים סריקה על פי דרישה
- איך לשלב סריקה בצינור עיבוד נתונים ל-build
- איך חותמים על תמונות שאושרו
- איך משתמשים בפקדי אישור של GKE כדי לחסום תמונות
- איך מגדירים את GKE כך שיאפשר רק תמונות חתומות שאושרו
2. הגדרה ודרישות
הגדרת סביבה בקצב אישי
- נכנסים למסוף Google Cloud ויוצרים פרויקט חדש או משתמשים מחדש בפרויקט קיים. אם עדיין אין לכם חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.
- שם הפרויקט הוא השם המוצג של המשתתפים בפרויקט. זוהי מחרוזת תווים שלא משמשת את Google APIs. אפשר לעדכן את המיקום הזה בכל שלב.
- מזהה הפרויקט הוא ייחודי לכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו אחרי שמגדירים אותו. מסוף Cloud יוצר באופן אוטומטי מחרוזת ייחודית. בדרך כלל לא משנה מה המחרוזת הזו. ברוב ה-codelabs תצטרכו להפנות למזהה הפרויקט (בדרך כלל הוא מזוהה בתור
PROJECT_ID
). אם המזהה שנוצר לא מוצא חן בעיניכם, תוכלו ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות שם משלכם ולבדוק אם הוא זמין. לא ניתן לשנות את השם אחרי השלב הזה, והוא יישאר למשך כל תקופת הפרויקט. - לידיעתכם, יש ערך שלישי, מספר פרויקט, שמשתמשים בו בחלק מממשקי ה-API. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי העזרה.
- בשלב הבא, כדי להשתמש במשאבים או ב-API של Cloud, תצטרכו להפעיל את החיוב במסוף Cloud. השלמת הקודלאב הזה לא אמורה לעלות הרבה, אם בכלל. כדי להשבית את המשאבים ולמנוע חיובים אחרי סיום המדריך, אפשר למחוק את המשאבים שיצרתם או למחוק את הפרויקט כולו. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בסך 300$.
הפעלת Cloud Shell Editor
סדנת ה-Lab הזו תוכננה ונבדקה לשימוש עם Google Cloud Shell Editor. כדי לגשת לעורך:
- נכנסים לפרויקט ב-Google בכתובת https://console.cloud.google.com.
- בפינה השמאלית העליונה, לוחצים על סמל עורך Cloud Shell.
- ייפתח חלון חדש בחלק התחתון של החלון.
הגדרת הסביבה
ב-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
3. סריקה אוטומטית
הסריקה של הארטיפקטים מופעלת באופן אוטומטי בכל פעם שדוחפים קובץ אימג' חדש ל-Artifact Registry או ל-Container Registry. המידע על נקודות החולשה מתעדכן כל הזמן כשמתגלות נקודות חולשה חדשות. בקטע הזה נדחוף קובץ אימג' ל-Artifact Registry ונבחן את התוצאות.
יצירה של ספריית עבודה ושינוי אליה
mkdir vuln-scan && cd vuln-scan
הגדרת תמונה לדוגמה
יוצרים קובץ בשם Dockerfile עם התוכן הבא.
cat > ./Dockerfile << EOF
FROM gcr.io/google-appengine/debian9@sha256:ebffcf0df9aa33f342c4e1d4c8428b784fc571cdf6fbab0b31330347ca8af97a
# System
RUN apt update && apt install python3-pip -y
# App
WORKDIR /app
COPY . ./
RUN pip3 install Flask==1.1.4
RUN pip3 install gunicorn==20.1.0
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 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
יצירה של קובץ build והעברה (push) של קובץ האימג' ל-AR
איך משתמשים ב-Cloud Build כדי ליצור קונטיינר ולהעביר אותו באופן אוטומטי ל-Artifact Registry. שימו לב לתג bad
בתמונה. כך תוכלו לזהות אותו בשלבים הבאים.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
בדיקת פרטי התמונה
בסיום תהליך ה-build, בודקים את התוצאות של האימג' ושל נקודות החולשה במרכז הבקרה של Artifact Registry.
- פתיחת Artifact Registry במסוף Cloud
- לוחצים על artifact-scanning-repo כדי להציג את התוכן.
- לוחצים על פרטי התמונה.
- לוחצים על סיכום התמונה האחרון
- בסיום הסריקה, לוחצים על הכרטיסייה 'נקודות חולשה' של התמונה.
בכרטיסייה 'נקודות חולשה' יוצגו תוצאות הסריקה האוטומטית של התמונה שיצרתם.
הסריקה האוטומטית מופעלת כברירת מחדל. כדאי לעיין בהגדרות של Artifact Registry כדי לראות איך אפשר להשבית או להפעיל את הסריקה האוטומטית.
4. סריקה על פי דרישה
יש תרחישים שונים שבהם ייתכן שתצטרכו להריץ סריקה לפני שתשלח את התמונה למאגר. לדוגמה, מפתח קונטיינרים יכול לסרוק קובץ אימג' ולתקן את הבעיות לפני שהוא דוחף את הקוד למערכת בקרת הגרסאות. בדוגמה הבאה נתאר איך יוצרים ומנתחים את התמונה באופן מקומי לפני שמבצעים פעולות על סמך התוצאות.
יצירת קובץ אימג'
בשלב הזה תשתמשו ב-Docker המקומי כדי ליצור את קובץ האימג' במטמון המקומי.
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .
סריקת התמונה
אחרי יצירת התמונה, מבקשים סריקה של התמונה. תוצאות הסריקה מאוחסנות בשרת מטא-נתונים. המשימה תושלם עם מיקום התוצאות בשרת המטא-נתונים.
gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--format="value(response.scan)" > scan_id.txt
בדיקת קובץ הפלט
כדאי לעיין בתוצאה של השלב הקודם שנשמרה בקובץ scan_id.txt. שימו לב למיקום הדוח של תוצאות הסריקה בשרת המטא-נתונים.
cat scan_id.txt
בדיקת תוצאות הסריקה המפורטות
כדי להציג את התוצאות בפועל של הסריקה, משתמשים בפקודה list-vulnerabilities
במיקום הדוח שצוין בקובץ הפלט.
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt)
הפלט מכיל כמות משמעותית של נתונים על כל נקודות החולשה בתמונה.
סימון בעיות קריטיות
בני אדם משתמשים בנתונים ששמורים בדוח ישירות רק לעיתים רחוקות. בדרך כלל, התוצאות משמשות תהליך אוטומטי. משתמשים בפקודות הבאות כדי לקרוא את פרטי הדוח ולרשום ביומן אם נמצאו נקודות חולשה קריטיות
export SEVERITY=CRITICAL
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq ${SEVERITY}; then echo "Failed vulnerability check for ${SEVERITY} level"; else echo "No ${SEVERITY} Vulnerabilities found"; fi
הפלט מהפקודה הזו יהיה
Failed vulnerability check for CRITICAL level
5. סריקת צינור עיבוד נתונים ליצירת גרסאות build
בקטע הזה תלמדו איך ליצור צינור עיבוד נתונים אוטומטי ל-build, שיוצר את קובץ האימג' בקונטיינר, סורק אותו ומעריך את התוצאות. אם לא יימצאו נקודות חולשה קריטיות, התמונה תועבר למאגר. אם יימצאו נקודות חולשה קריטיות, ה-build ייכשל ויצא.
מתן גישה לחשבון השירות של 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"
יצירת צינור עיבוד הנתונים של Cloud Build
הפקודה הבאה תיצור בתיקייה קובץ cloudbuild.yaml שישמש בתהליך האוטומטי. בדוגמה הזו, השלבים מוגבלים לתהליך ה-build בקונטיינר. בפועל, צריך לכלול הוראות ובדיקות ספציפיות לאפליקציה בנוסף לשלבים בקונטיינר.
יוצרים את הקובץ באמצעות הפקודה הבאה.
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']
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF
הפעלת צינור עיבוד הנתונים של CI
שולחים את ה-build לעיבוד כדי לוודא שה-build נכשל כשנמצאת נקודת חולשה ברמת קריטית.
gcloud builds submit
בדיקת כשל ב-build
ה-build ששלחתם עכשיו ייכשל כי התמונה מכילה נקודות חולשה קריטיות.
בודקים את הכישלון של ה-build בדף Cloud Build History
תיקון הפגיעות
מעדכנים את קובץ Dockerfile כך שישתמש בתמונת בסיס שלא מכילה נקודות חולשה קריטיות.
משנים את קובץ Dockerfile כך שישתמש בקובץ האימג' של Debian 10 באמצעות הפקודה הבאה:
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
מריצים את תהליך ה-CI עם התמונה הטובה
שולחים את ה-build לעיבוד כדי לוודא שה-build יצליח אם לא יימצאו נקודות חולשה ברמת קריטיות.
gcloud builds submit
בדיקת הצלחת ה-build
ה-build ששלחת עכשיו יצליח כי קובץ האימג' המעודכן לא מכיל נקודות חולשה קריטיות.
בודקים את הצלחת ה-build בדף Cloud Build History
בדיקת תוצאות הסריקה
בדיקת קובץ האימג' תקין ב-Artifact Registry
- פותחים את Artifact Registry במסוף Cloud
- לוחצים על artifact-scanning-repo כדי להציג את התוכן.
- לוחצים על פרטי התמונה.
- לוחצים על סיכום התמונה האחרון
- לוחצים על הכרטיסייה 'נקודות חולשה' של התמונה.
6. חתימה על תמונות
יצירת הערה של גורם אימות
הערה של גורם אימות היא פשוט קטע קטן של נתונים שמשמש בתור תווית לסוג החתימה שחלה. לדוגמה, הערה אחת עשויה לציין סריקת נקודות חולשה, ואילו הערה אחרת עשויה לשמש לצורך אישור של בקרת איכות. ההערה תופיע במהלך תהליך החתימה.
יצירת הערה
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}"
יצירת גורם אימות (attestor)
חותמים משמשים לביצוע תהליך החתימה בפועל על התמונה, והם יצרפו את ההערה לתמונה לצורך אימות מאוחר יותר. יוצרים את המאמת לשימוש מאוחר יותר.
יצירת גורם אימות
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
לאמתן נדרשים מפתחות קריפטוגרפיים כדי לצרף את ההערה ולספק חתימות שניתן לאמת. בשלב הזה תיצורו מפתחות ותשמרו אותם ב-KMS כדי ש-Cloud Build יוכל לגשת אליהם מאוחר יותר.
קודם מוסיפים כמה משתני סביבה כדי לתאר את המפתח החדש
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.
עכשיו משייך את המפתח למאמת באמצעות הפקודה 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) שיצרתם קודם כדי לחתום על קובץ האימג' בקונטיינר שבו עבדתם
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, הפעולה הזו תיצור אירוע חדש ותצרף אותו להערה של המאמת. כדי לוודא שהכול פועל כצפוי, אפשר להציג את האישורים
gcloud container binauthz attestations list \
--attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}
7. חתימה באמצעות Cloud Build
הפעלתם את 'חתימת תמונות' והשתמשתם באופן ידני באימות (attestation) כדי לחתום על התמונה לדוגמה. בפועל, כדאי להחיל את האימותים במהלך תהליכים אוטומטיים כמו צינורות עיבוד נתונים של CI/CD.
בקטע הזה מגדירים את Cloud Build לאימות אוטומטי של תמונות.
תפקידים
מוסיפים את התפקיד 'צפייה באימות של Binary Authorization' לחשבון השירות ב-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 להערות' לחשבון השירות של Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/containeranalysis.notes.attacher
הכנת שלב ה-build בהתאמה אישית ב-Cloud Build
כדי לפשט את תהליך האימות, נשתמש בשלב build מותאם אישית ב-Cloud Build. Google מספקת את השלב הזה של build בהתאמה אישית, שכולל פונקציות עזר כדי לייעל את התהליך. לפני השימוש, צריך ליצור את הקוד של שלב ה-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 בדף Cloud Build History ובודקים את הגרסה האחרונה שנוצרה וההפעלה המוצלחת של שלבי ה-build.
8. כללי מדיניות בקרה על אישור בקשות
Binary Authorization היא תכונה ב-GKE וב-Cloud Run שמאפשרת לאמת כללים לפני שמאפשרים להריץ קובץ אימג' של קונטיינר. האימות מתבצע בכל בקשה להרצת קובץ אימג', בין אם מדובר בצינור עיבוד נתונים מהימן של CI/CD או במשתמש שמנסה לפרוס קובץ אימג' באופן ידני. היכולת הזו מאפשרת לכם לאבטח את סביבות זמן הריצה בצורה יעילה יותר מאשר רק באמצעות בדיקות צינור עיבוד הנתונים של CI/CD.
כדי להבין את היכולת הזו, נשנה את מדיניות ברירת המחדל של GKE כדי לאכוף כלל הרשאה מחמיר.
יצירת אשכול GKE
יוצרים את האשכול ב-GKE:
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"
מדיניות הרשאה לכל
קודם כול צריך לוודא מהו מצב מדיניות ברירת המחדל ואם יש לכם אפשרות לפרוס תמונה כלשהי.
- בדיקת המדיניות הקיימת
gcloud container binauthz policy export
- שימו לב שמדיניות האכיפה מוגדרת כ-
ALWAYS_ALLOW
evaluationMode: ALWAYS_ALLOW
- פריסה של גרסת build לדוגמה כדי לוודא שאפשר לפרוס כל דבר
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
- פותחים את Terminal ומחילים את המדיניות החדשה. ממתינים כמה שניות עד שהשינוי יופץ.
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
9. חסימה של נקודות חולשה ב-GKE
בקטע הזה משלבים את מה שלמדתם עד עכשיו, על ידי הטמעת צינור עיבוד נתונים של CI/CD עם Cloud Build, שמסורק את התמונות ולאחר מכן בודק נקודות חולשה לפני החתימה על התמונה והניסיון לפרוס אותה. GKE ישתמש ב-Binary Authorization כדי לאמת שלתמונה יש חתימה מסריקת נקודות החולשה, לפני שהוא יאפשר לה להריץ את האימג'.
עדכון המדיניות של GKE כך שתחייב אימות
Require images חותמים על ידי האימות (attestor) על ידי הוספת 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
החלת המדיניות
gcloud beta container binauthz policy import binauth_policy.yaml
ניסיון לפרוס את התמונה הלא חתומה
יוצרים מתאר פריסה לאפליקציה שיצרתם מקודם באמצעות הפקודה הבאה. התמונה שבה נעשה שימוש כאן היא התמונה שיצרתם מקודם, שמכילה נקודות חולשה קריטיות ולא מכילה את האימות החתום.
כדי לאמת את החתימה באופן עקבי, בקרי אישור הגישה של GKE צריכים לדעת מהי התמונה המדויקת שרוצים לפרוס. כדי לעשות זאת, צריך להשתמש ב-image digest במקום בתג פשוט.
אחזור של תקציר התמונה של התמונה הפגומה
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
פריסה של קובץ אימג' חתום
אחזור של תקציר התמונה של התמונה הפגומה
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
בודקים את עומס העבודה במסוף ומבחינים בפריסה המוצלחת של התמונה.
10. מעולה!
כל הכבוד, סיימת את הקודלאב!
הנושאים שעסקנו בהם:
- איך מפעילים סריקה אוטומטית
- איך מבצעים סריקה על פי דרישה
- איך לשלב סריקה בצינור עיבוד נתונים ל-build
- איך חותמים על תמונות שאושרו
- איך משתמשים בפקדי אישור של GKE כדי לחסום תמונות
- איך מגדירים את GKE כך שיאפשר רק תמונות חתומות שאושרו
השלב הבא:
- אבטחת פריסות של קובצי אימג' ב-Cloud Run וב-Google Kubernetes Engine | מסמכי העזרה של Cloud Build
- מדריך למתחילים: הגדרת מדיניות Binary Authorization באמצעות GKE | Google Cloud
הסרת המשאבים
כדי להימנע מחיובים בחשבון Google Cloud בגלל השימוש במשאבים שנעשה במסגרת המדריך הזה, אפשר למחוק את הפרויקט שמכיל את המשאבים, או להשאיר את הפרויקט ולמחוק את המשאבים הנפרדים.
מחיקת הפרויקט
הדרך הקלה ביותר לבטל את החיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך.