הגבלת פריסות של פריסות באמצעות Binary Auth

1. מבוא

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

בתרשים הבא מוצגים הרכיבים בהגדרה של Binary Authorization או Cloud Build:

צינור אימות (attestation) של Cloud Build Binary Authorization.**איור 1.**צינור עיבוד הנתונים של Cloud Build שיוצר אימות ב-Binary Authorization.

בצינור עיבוד הנתונים הזה:

  1. הקוד לבניית קובץ האימג' בקונטיינר מועבר למאגר מקור, כמו Cloud Source Repositories.
  2. Cloud Build הוא כלי אינטגרציה רציפה (CI) לפיתוח ובדיקה של הקונטיינר.
  3. גרסת ה-build מעבירה את קובץ האימג' של הקונטיינר ל-Container Registry או למרשם אחר שמאחסן את התמונות שנוצרו.
  4. Cloud Key Management Service, שמספק ניהול מפתחות לזוג המפתחות הקריפטוגרפיים, חותם על קובץ האימג' של הקונטיינר. לאחר מכן החתימה שתתקבל נשמרת בתהליך אימות (attestation) חדש שנוצר.
  5. בזמן הפריסה, המאמת מאמת את האימות באמצעות המפתח הציבורי מזוג המפתחות. Binary Authorization אוכף את המדיניות באמצעות דרישה של אימותים (attestation) חתומים כדי לפרוס את קובץ האימג' בקונטיינר.

בשיעור ה-Lab הזה נתמקד בכלים ובטכניקות לאבטחת ארטיפקטים שנפרסו. שיעור ה-Lab הזה מתמקדים בארטיפקטים (קונטיינרים) אחרי שהם נוצרו אבל לא נפרסו בסביבה מסוימת.

מה תלמדו

  • חתימת תמונה
  • מדיניות בקרה על אישור בקשות
  • חתימה על תמונות סרוקות
  • בתהליך הרשאה לתמונות חתומות
  • תמונות לא חתומות חסומות

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

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

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

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא משמשת את Google APIs. אפשר לעדכן אותו בכל שלב.
  • Project ID הוא ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-Codelabs תצטרכו להפנות אל מזהה הפרויקט (בדרך כלל הוא מזוהה כ-PROJECT_ID). אם המזהה שנוצר לא מוצא חן בעיניך, יש לך אפשרות ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות תבנית משלך ולבדוק אם היא זמינה. לא ניתן לשנות אותו אחרי השלב הזה, והוא יישאר למשך הפרויקט.
  • לידיעתך, יש ערך שלישי – Project Number (מספר פרויקט), שחלק מממשקי ה-API משתמשים בו. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא אמור לעלות הרבה, אם בכלל. כדי להשבית את המשאבים ולא לצבור חיובים מעבר למדריך הזה, אתם יכולים למחוק את המשאבים שיצרתם או למחוק את הפרויקט כולו. משתמשים חדשים ב-Google Cloud זכאים להצטרף לתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

הגדרת סביבה

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

הגדרת Docer לשימוש בפרטי הכניסה של 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. חתימת תמונה

מהו גורם מאמת

הגורם המאמת

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

כל אחד מהתפקידים האלה יכול לייצג אדם פרטי או צוות של אנשים בארגון. בסביבת ייצור, סביר להניח שהתפקידים האלה ינוהלו על ידי פרויקטים נפרדים ב-Google Cloud Platform (GCP), והגישה למשאבים ישותפו ביניהם באופן מוגבל באמצעות Cloud IAM.

a37eb2ed54b9c2eb.png

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

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

208aa5ebc53ff2b3.png

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

ב-Binary Authorization API נעשה שימוש במושגים של 'גורמים מאמתים' ו-'attestations', אבל הם מיושמים באמצעות הערות ואירועים תואמים ב-Container Analysis API.

63a701bd0057ea17.png

יצירה של הערת גורם מאמת

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

919f997db0ffb881.png

יצירת הערה

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.

יצירת גורם מאמת

המאמתים משמשים לביצוע תהליך החתימה על התמונות בפועל, והם מצרפים לתמונה אירוע של ההערה לצורך אימות מאוחר יותר. כדי להשתמש במזהה שלך, עליך לרשום את הפתק גם ב-Binary Authorization:

ed05d438c79b654d.png

יצירת גורם מאמת

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

1e3af7c177f7a311.png

לפני שתוכלו להשתמש במזהה הזה, ברשות שלכם צריכה ליצור זוג מפתחות קריפטוגרפיים שישמש לחתימה על תמונות קונטיינר. ניתן לעשות זאת באמצעות 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.

בשלב הזה, משייכים את המפתח למאמת באמצעות הפקודה 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

יצירת הצהרה חתומה

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

858d7e6feeb6f159.png

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

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 כדי ליצור את האימות (attestation). הפקודה פשוט לוקחת את הפרטים של המפתח שבו רוצים להשתמש לצורך חתימה, ואת תמונת הקונטיינר הספציפית שרוצים לאשר.

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, ייווצר אירוע חדש ותצרף אותו להערה של המאמת. כדי להבטיח שהכול יפעל כמו שצריך, אפשר לרשום את האימותים (attestation) שלך

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 שמופעלת בו הרשאה בינארית:

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"

מתן הרשאה לכל כללי המדיניות

קודם עליך לאמת את מצב המדיניות שמוגדר כברירת מחדל ואת היכולת שלך לפרוס כל קובץ אימג'

  1. עיון במדיניות הקיימת
gcloud container binauthz policy export
  1. שימו לב שמדיניות האכיפה מוגדרת כך: ALWAYS_ALLOW

evaluationMode: ALWAYS_ALLOW

  1. פריסת Sample כדי לוודא שאפשר לפרוס כל דבר
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. איך לוודא שהפריסה פעלה
kubectl get pods

הפלט הבא יוצג

161db370d99ffb13.png

  1. מחיקת הפריסה
kubectl delete pod hello-server

דחייה של כל כללי המדיניות

עכשיו צריך לעדכן את המדיניות כדי לאסור את כל התמונות.

  1. ייצוא המדיניות הנוכחית לקובץ שניתן לעריכה
gcloud container binauthz policy export  > policy.yaml
  1. שנה את המדיניות

בכלי לעריכת טקסט, משנים את ערך ההערכה מ-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, שלפיו כל מערכי ה-Pod האחרים יידחו. כלל הכניסה כולל את השורה enforcementMode, שלפיה צריך לחסום את ההפעלה של כל ה-Pods שלא תואמים לכלל הזה באשכול.

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

657752497e59378c.png

  1. פותחים את 'טרמינל' ומחילים את המדיניות החדשה וממתינים כמה שניות עד שהשינוי ייכנס לתוקף
gcloud container binauthz policy import policy.yaml
  1. ניסיון לפריסה של עומס עבודה לדוגמה
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. הפריסה נכשלה עם ההודעה הבאה
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

כדי להתיר את כל סוגי האירועים, צריך לבטל את המדיניות

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

  1. שנה את המדיניות

בכלי לעריכת טקסט, משנים את ערך ההערכה מ-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
  1. החלת המדיניות שבוטלה
gcloud container binauthz policy import policy.yaml

5. חתימה על תמונות סרוקות

הפעלת חתימת תמונה והשתמשת באופן ידני במאמת כדי לחתום את התמונה לדוגמה. בפועל, כדאי להחיל הצהרות במהלך תהליכים אוטומטיים, כמו צינורות עיבוד נתונים של 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

הוספת תפקיד חותם/מאמת של CryptoKey ב-Cloud KMS לחשבון שירות ב-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"

הכנת השלב של build בהתאמה אישית ב-Cloud Build

תשתמשו בשלב Custom 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.

  1. בהמשך מפורטים שלב החתימה.

לבדיקה בלבד. לא להעתיק

#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'
  1. תכתוב קובץ 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, ובודקים את ה-build האחרון ואת הביצוע של שלבי ה-build.

6. בתהליך הרשאה לתמונות חתומות

בקטע הזה מעדכנים את GKE כך שישתמש ב-Binary Authorization לאימות התמונה שיש בה חתימה מסריקת נקודות החולשה לפני שמאפשרים להריץ את התמונה.

d5c41bb89e22fd61.png

עדכון המדיניות של GKE לדרישת אימות (attestation)

לדרוש שתמונות חתומות על ידי המאמת על ידי הוספת clusterAdmissionRules למדיניות BinAuth ב-GKE.

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

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

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. עכשיו, במקום שכלל ברירת המחדל דוחה את כל התמונות, בשלב הראשון הוא בודק את הגורם המאמת.

822240fc0b02408e.png

העלאת המדיניות החדשה ל-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)')

שימוש בתקציר בהגדרות של 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)')

שימוש בתקציר בהגדרות של 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!

נושאים שטיפלנו בהם:

  • חתימת תמונה
  • מדיניות בקרה על אישור בקשות
  • חתימה על תמונות סרוקות
  • בתהליך הרשאה לתמונות חתומות
  • תמונות לא חתומות חסומות

השלב הבא:

הסרת המשאבים

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

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

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

עדכון אחרון: 21.03.23