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

1. מבוא

ead1609267034bf7.png

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

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

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

מה תלמדו

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

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

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

הגדרת סביבה בקצב עצמי

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

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.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

שליחת הגרסה לעיבוד

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

שליחת הגרסה לעיבוד

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

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

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