אבטחת גרסאות build של קונטיינרים

1. מבוא

ead1609267034bf7.png

פגיעויות בתוכנה הן חולשות שעלולות לגרום לכשל מערכת מקרי או לספק לגורמים זדוניים אמצעי לפריצה לתוכנה. Container Analysis מספק שני סוגים של סריקת מערכת הפעלה כדי למצוא נקודות חולשה בקונטיינרים:

  • ה-On-Demand Scanning API מאפשר לכם לסרוק ידנית קובצי אימג' של קונטיינרים כדי לאתר נקודות חולשה במערכת ההפעלה, באופן מקומי במחשב או מרחוק ב-Container Registry או ב-Artifact Registry.
  • ה-API של Container Scanning מאפשר לכם לאתר נקודות חולשה במערכת ההפעלה באופן אוטומטי, ולסרוק בכל פעם שאתם דוחפים אימג' ל-Container Registry או ל-Artifact Registry. הפעלת ה-API הזה מפעילה גם סריקות של חבילות שפה כדי לזהות פגיעויות ב-Go וב-Java.

ממשק ה-On-Demand Scanning API מאפשר לסרוק תמונות שמאוחסנות באופן מקומי במחשב, או מרחוק ב-Container Registry או ב-Artifact Registry. כך תוכלו לשלוט בצורה מדויקת בקונטיינרים שאתם רוצים לסרוק כדי לזהות נקודות חולשה. אתם יכולים להשתמש בסריקה לפי דרישה כדי לסרוק תמונות בצינור ה-CI/CD לפני שתחליטו אם לאחסן אותן במאגר.

מה תלמדו

בשיעור ה-Lab הזה:

  • יצירת קובצי אימג' באמצעות Cloud Build
  • שימוש ב-Artifact Registry לקונטיינרים
  • שימוש בסריקה אוטומטית של נקודות חולשה
  • הגדרת סריקה על פי דרישה
  • הוספת סריקת תמונות ב-CICD ב-Cloud Build

2. הגדרה ודרישות

הגדרת סביבה בקצב אישי

  1. נכנסים ל-מסוף Google Cloud ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. אם עדיין אין לכם חשבון Gmail או Google Workspace, אתם צריכים ליצור חשבון.

b35bf95b8bf3d5d8.pnga99b7ace416376c4.pngbd84a6d3004737c5.png

  • שם הפרויקט הוא השם המוצג למשתתפים בפרויקט. זו מחרוזת תווים שלא נמצאת בשימוש ב-Google APIs. אפשר לעדכן את המיקום הזה בכל שלב.
  • מזהה הפרויקט הוא ייחודי לכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו אחרי שהוא מוגדר. מסוף Cloud יוצר באופן אוטומטי מחרוזת ייחודית, ובדרך כלל לא צריך לדעת מה היא. ברוב ה-Codelabs, תצטרכו להפנות למזהה הפרויקט (בדרך כלל הוא מזוהה כ-PROJECT_ID). אם אתם לא אוהבים את המזהה שנוצר, אתם יכולים ליצור מזהה אקראי אחר. אפשר גם לנסות שם משתמש משלכם ולבדוק אם הוא זמין. אי אפשר לשנות את ההגדרה הזו אחרי השלב הזה, והיא תישאר כזו למשך הפרויקט.
  • לידיעתכם, יש ערך שלישי, מספר פרויקט, שחלק מממשקי ה-API משתמשים בו. מידע נוסף על שלושת הערכים האלה מופיע במאמרי העזרה.
  1. בשלב הבא, תצטרכו להפעיל את החיוב במסוף 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 

3. יצירת קובצי אימג' באמצעות Cloud 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"

יצירה של ספריית עבודה ומעבר אליה

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

יצירת צינור עיבוד נתונים ב-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: ['-']


EOF

הפעלת צינור ה-CI

שליחת ה-build לעיבוד

gcloud builds submit

בדיקת פרטי גרסת ה-Build

אחרי שתהליך build יתחיל, תוכלו לעקוב אחרי ההתקדמות בלוח הבקרה של Cloud Build.

  1. פותחים את Cloud Build ב-Cloud Console.
  2. לוחצים על הגרסה כדי לראות את התוכן

4. ‫Artifact Registry for Containers

יצירת מאגר 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

עדכון צינור עיבוד הנתונים של Cloud Build

משנים את צינור ה-build כדי לדחוף את התמונה שמתקבלת אל Artifact Registry

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: ['-']

# push 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']

images:
  - us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF

הפעלת צינור ה-CI

שליחת ה-build לעיבוד

gcloud builds submit

5. סריקה אוטומטית של נקודות חולשה

סריקת ארטיפקטים מופעלת באופן אוטומטי בכל פעם שמעלים אימג' חדש ל-Artifact Registry או ל-Container Registry. המידע על נקודות החולשה מתעדכן כל הזמן כשמתגלות נקודות חולשה חדשות. בקטע הזה תבדקו את התמונה שבניתם והעברתם ל-Artifact Registry, ותעיינו בתוצאות של פגיעות האבטחה.

בדיקת פרטי התמונה

אחרי שתהליך ה-build הקודם מסתיים, בודקים את התוצאות של האימג' והפגיעות בלוח הבקרה של Artifact Registry.

  1. פותחים את Artifact Registry ב-Cloud Console.
  2. כדי לראות את התוכן, לוחצים על artifact-scanning-repo.
  3. לחיצה על פרטי התמונה
  4. לחיצה על התקציר האחרון של התמונה
  5. אחרי שהסריקה מסתיימת, לוחצים על הכרטיסייה 'פגיעויות' של התמונה.

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

361be7b3bf293fca.png

האפשרות להפעיל סריקה אוטומטית מופעלת כברירת מחדל. כדאי לעיין בהגדרות של Artifact Registry כדי לראות איך אפשר להפעיל או להשבית את הסריקה האוטומטית.

6. סריקה על פי דרישה

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

יצירת תמונה

בשלב הזה תשתמשו ב-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

7. סריקה ב-CICD באמצעות Cloud 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

שולחים את הגרסה לעיבוד כדי לוודא שהגרסה נשברת כשנמצאת פגיעות ברמת חומרה CRITICAL.

gcloud builds submit

בדיקת כשל בבנייה

הגרסה ששלחת עכשיו תיכשל כי התמונה מכילה פגיעויות קריטיות.

בדיקת הכשל ב-build בדף Cloud Build History

תיקון הפגיעות

מעדכנים את קובץ ה-Docker כדי להשתמש בתמונת בסיס שלא מכילה פגיעויות קריטיות.

מחליפים את קובץ ה-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 יצליח אם לא יימצאו פגיעויות ברמת חומרה CRITICAL.

gcloud builds submit

בדיקת ההצלחה של בניית האפליקציה

ה-build ששלחתם עכשיו יצליח כי התמונה המעודכנת לא מכילה פגיעויות קריטיות.

בדיקת ההצלחה של הבנייה בדף ההיסטוריה של Cloud Build

בדיקת תוצאות הסריקה

בדיקת התמונה הטובה ב-Artifact Registry

  1. פותחים את Artifact Registry ב-Cloud Console.
  2. כדי לראות את התוכן, לוחצים על artifact-scanning-repo.
  3. לחיצה על פרטי התמונה
  4. לחיצה על התקציר האחרון של התמונה
  5. לוחצים על הכרטיסייה 'פגיעויות' של התמונה.

8. מעולה!

כל הכבוד, סיימתם את ה-Codelab!

הנושאים שנדון בהם:

  • יצירת קובצי אימג' באמצעות Cloud Build
  • ‫Artifact Registry for Containers
  • סריקה אוטומטית של נקודות חולשה
  • סריקה על פי דרישה
  • סריקה ב-CICD באמצעות Cloud Build

השלב הבא:

הסרת המשאבים

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

מחיקת הפרויקט

הדרך הקלה ביותר לבטל את החיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך.

העדכון האחרון: 21 במרץ 2023