בפוסט הקודם שלנו בנושא CI/CD Pipelines, ראינו איך לפרוץ א CI/CD תרחיש ש ככל הנראה היה מוגן.
בואו נזכור את הנקודה שלנו בפוסט הקודם: התחלנו עם כמה pipeline שהיה פגיע ל הרעלה עקיפה Pipeline הוצאה לפועל (I-PPE) וכדי לתקן את זה, החלטנו לפצל את pipeline לשניים:
- 1st pipeline (Build CI), בטוח ל-D-PPE ו-I-PPE, יבדוק את קוד ה-PR, יבצע את הבנייה וייצר ארטיפקט
- 2nd pipeline (Test CI), גם בטוח ל-D-PPE ו-I-PPE יבדוק את קוד הבסיס (כדי למנוע שינוי בסקריפט המעטפת) ויבצע את הסקריפטים המקוריים כנגד הארטיפקט.
- כדי לסנכרן את CI הבדיקה pipeline לרוץ אחרי Build CI pipeline, השתמשנו workflow_run הדק.
קראנו לזה כתרחיש מספר 3.

למרות שכפי שציינו באותו פוסט, ישנם פתרונות אחרים, החלטנו ליישם את ה"פתרון" הזה מסיבות פדגוגיות, כדי שנוכל להתעמק בפגיעויות של CI/CD pipelines.
לאחר מכן, ראינו כיצד לפרוץ את התרחיש הזה על ידי הרעלת החפץזה מה שאנחנו קוראים הרעלת חפצים, כלומר היכולת לשנות (לפרוץ) את ה- pipeline לוגיקה על ידי שינוי pipeline חפץ.
מה הבעיה בגישה הזו? ראינו שהבעיה מתעוררת כאשר משתמש כלשהו "יוצר" דף חדש pipeline.
אם משתמש פותח הודעה פרטית המכילה הודעה חדשה pipeline, גיטהאב יבצע את זה pipeline (בהינתן תנאים מסוימים, כפי שראינו) בפוסט).
לאחר מכן המשתמש יכול ליצור חדש pipeline עם אותו שם כמו Build CI!! כן, זה מפתיע, אבל GitHub מאפשר לך ליצור שניים pipelineעם אותו שם!!
כאשר המשתמש פותח הודעה פרטית עם שינויים אלה, ה"חדש" pipeline יוצא להורג (העלאת חפץ מורעל) ו-Deploy CI pipeline יבוצע לאחר מכן, וכתוצאה מכך סקריפט המעטפת "המשתנה" ידרוס את סקריפט המעטפת "המקורי" שנמצא ב- pipeline סביבת עבודה. לכן, "פתרון" זה אינו עוקף את הפגיעות של I-PPE (כפי שניתן לראות בהמשך)

מהן הבעיות? לפחות, ישנן כמה בעיות:
- ראשית, איך לוודא שלא טופלו בעיות בתהליך הבנייה? בתרחיש זה, המשתמש הזדוני הצליח לשנות את תהליך הבנייה המיועד באמצעות שלו pipeline כדי ליצור חפץ מורעל.
- שנית, כיצד נוכל להעריך את מקורו של חפץ?
שאלות אלה משליכות אותנו לזרועותיהם של אישורי תוכנה תְחוּם!!
אישורי תוכנה
An עֵדוּת הוא חתיכת נתונים המייצג הוכחה לאירועבעולם האמיתי, אנחנו בדרך כלל קוראים לזה אישורים.
לדוגמה, כאשר מעבדה מבצעת בדיקת דם, נתונים על הבדיקה מתועדים ומאושרים. תוצאות בדיקת הדם לאימות ו ניתן למעקב.

קרוב יותר לתחום ה-IT שלנו, אפשר לנחש מה יהיה תרגום של תהליך זה, למשל, לתהליך קומפילציה.

מידע על סביבת שרת הקומפילציה והכלים, החומרים (קוד המקור) והמוצרים/ארטיפקטים (הקוד הבינארי) יהיו חלק מאימות כזה.
ברור שהאישור חייב להיווצר על ידי מאשר מורשה (מאומת ובלתי ניתן להכחשה) כדי להבטיח אמינות.
סביר להניח שחלקכם חושבים... ומה ה... ההבדל בין חתימות לאימות?
חתימות קוד והוכחות
ברמה גבוהה, א חֲתִימָה נוצר באמצעות זוג מפתחות וארטיפקט. זוג המפתחות מורכב ממפתח ציבורי ומפתח פרטי.

המשתמש חותם על חפץ באמצעות המפתח הפרטי, ולאחר מכן אחרים יכולים לאמת את החתימה באמצעות המפתח הציבורי. יש לשמור את המפתח הפרטי בסוד, אך המפתח הציבורי מופץ באופן נרחב.
ניתן להשתמש בחתימות כדי להוכיח שבעל המפתח הפרטי השתמש במפתח הפרטי כדי לחתום על החפץ.
חתימות אל תוכיח
- של המשתמש הכוונה לחתום על החפץ (ייתכן שהם הוטעו), או
- כוונת המשתמש לבצע כל דבר טענה ספציפית לגבי החפץ
עם עדויותבמקום לחתום על חפץ ישירות, משתמשים יוצרים סוג כלשהו של מסמך זֶה לוכד את כוונתם מאחורי החתימה על החפץ וכל דבר אחר טענות ספציפיות נעשה כחלק מחתימה זו.
מסגרת אימות In-toto
המסגרת הנפוצה ביותר היא מסגרת אימות in-toto
- מגדיר standard פורמט לאימות אשר קושרים את הנושאים, את החפצים המתוארים, למטא-נתונים מאומתים אודות החפצים
- מספק סט של פרדיקטים מוגדרים מראש לתקשורת מטא-נתונים מאומתים לאורך ובין שרשראות אספקת תוכנה
בואו נפרט קצת על פורמט ההסמכה.
An תעודה הוא מסמך חתום דיגיטלית זה מכיל הצהרות.
השמיים הצהרה היא השכבה האמצעית של האימות, הקושרת אותו לנקודה מסוימת נושא וזיהוי חד משמעי של סוגי ה- לְבַסֵס:
- נושא: הפניה מאובטחת קריפטוגרפית לחפץ (בדרך כלל באמצעות גיבוב), ו
- מנבא: קבוצה של ספציפיים טענות לגבי אותו חפץ מכונה הצהרה. ניתן להשתמש בטענות אלו כדי לבטא (ומאוחר יותר להוכיח) כל דבר שתוכלו לחשוב עליו! הן יכולות לייצג אישור ידני, מקור חפץ, תוצאות בדיקה אוטומטיות, נתיב ביקורת או יותר!
כאשר הצהרה זו חתומה באופן קריפטוגרפי, היא מכונה תעודה

בדרך זו, כדוגמה, אליס יוצרת הצהרה (Statement) לגבי חפץ וחותמת עליו באמצעות המפתח הפרטי שלה, ויוצרת אימות (Attestation).
- בוב יכול אז אימות החתימה באותה הצהרה, המאפשרת לו לסמוך על הטענות בְּתוֹך.
בוב יכול להשתמש בטענות האלה להחליט האם לאפשר או לא לאפשר שימוש בחפץ זה.

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

כפי שניתן לראות בתמונה למעלה, נקודות הפגיעה מרובות. בדרך זו, הצרכן pipeline (מבחן CI בדוגמה שלנו) חייב להעריך את שלמות תהליך הבנייה כמו גם שלמות החפץ עצמו.
בדוגמה שלנו, החפץ המורעל נוצר על ידי הכנסת חפץ חדש (מורעל) pipeline שמשבש את תהליך הבנייה. אבל המשתמש הזדוני היה יכול:
- שנה את הקוד לאחר הוצאתו מה- SCM כדי ליצור קובץ בינארי זדוני
- החלף את הקובץ הבינארי הנכון שנוצר על ידי הקומפילציה בכל קובץ בינארי זדוני אחר
- לפגוע במרשם החפצים ולהעלות חפץ מורעל שנבנה בכל דרך אחרת
- וכו '
כפי שאתם יכולים לראות, ייתכנו מספר נקודות "התעסקות".
מה חשוב כאן? ברור להגן על כל נקודות ה"התעסקות" הללו. אבל, בסופו של דבר, מה שהכי חשוב הוא ש"הצרכן" של החפץ יוכל להעריך את שלמותו, ולהחליט אם להמשיך איתו או לא.
אנחנו יכולים להעריך את שלמותו של חפץ בשתי דרכים.
אחת מהן היא על ידי הערכת ה- מוֹצָא של החפץ.
על ידי יצירת אימות מקור, אנו מספקים מטא-דאטה שימושיים (מאומתים כראוי ולא מופרכים) אודות החפץ. בדוגמאות הבאות, נשתמש ב- מלח קסיגני (שכבת אימות תוכנה לאמון), הרכיב ליצירה, רישום ואימות של אימות תוכנה.

- name: Building ...
run: |
# mvn will compile and create target/MyApp.war
mvn clean package
- name: Generating provenance
run: |
#!/usr/bin/env bash
shopt -s expand_aliases
alias salt=$PWD/salt_pro/xygeni_salt/salt
echo " "
echo "-----------"
echo "Generating Provenance with CLI ..."
salt at slsa \
--basedir ${GITHUB_WORKSPACE}/target \
--key="${PRIVATE_KEY}" \
--public-key=${GITHUB_WORKSPACE}/Test1_public.pem \
--key-password=${KEY_PASSWD} \
--output-unsigned=${GITHUB_WORKSPACE}/cli_provenance_${PIPELINE}_unsigned.json \
--pipeline ${PIPELINE} --pretty-print \
--file ./MyApp.war
בקוד שלמעלה, ניתן לראות שיש שלב שבונה את קובץ המלחמה ושלב שני שמייצר את אימות מקורכדי לעשות זאת, ה- pipeline משתמש במפתח הפרטי וכולל גם את המפתח הציבורי באימות.
מאחורי הקלעים, של קסיגני מלח הפקודה מאחסנת את האימות ב- פִּנקָס (הידוע גם כרישום אימותים, שיא במקרה שלנו, אבל אפשר להשתמש בכל אחד אחר). עשה זאת, הצרכן pipeline יכול לכלול את Xygeni's מנוע אימות כדי לאמת את מקור החפץ ולהעריך את שלמותו.
- name: 'Verifying the attestation'
run: |
#!/usr/bin/bash
echo " "
echo "-------"
# Calculate sha256sum for the artifact
SHA_SUM=$(sha256sum ./MyApp.war | cut -f1 -d ' ')
# Recover the attestation Id from the sha256sum
ATT_ID=$(echo $(salt -q registry search --digest sha256:$SHA_SUM --format json) | jq -r .[-1].gitoidSha256)
echo " "
echo "-------"
# Download the provenance attestation
echo "Downloading the provenance attestation ..."
salt -q reg get --id=$ATT_ID --format=json > ${GITHUB_WORKSPACE}/provenance_kk.signed.json
echo " "
echo "-------"
echo "Verifying provenance ..."
salt verify \
--basedir ${GITHUB_WORKSPACE} \
--attestation=${GITHUB_WORKSPACE}/provenance_kk.signed.json \
--public-key=${GITHUB_WORKSPACE}/Test1_public.pem \
--file ./MyApp.war
תהליך האימות מעריך:
- השמיים הארטיפקט sha256sum תקף (כלומר, ישנה הצהרה לגבי "נושא" זה), ו
- השמיים האישור מאומת כראוי (הוא נוצר באמצעות המפתח הפרטי המתאים)
תהליך אימות זה יכול להעריך שגם החפץ וגם האישור תקפים.
אבל, כפי שאתם זוכרים, במקרה שלנו, החפץ נוצר על ידי "זדוני" pipeline (כלומר, לא המקורי על ידי שינוי pipeline). לאחר מכן עלינו להמשיך ולבדוק היבט נוסף: ש החפץ נוצר על ידי ה"מקורי" pipeline, לא אף אחד אחר.
לשם כך, פשוט כלול שורה פשוטה כדי לבדוק את התנאי הזה, לדוגמה:
echo " "
echo "-------"
# Download the provenance attestation
echo "Downloading the provenance attestation ..."
salt -q reg get --id=$ATT_ID --format=json > ${GITHUB_WORKSPACE}/provenance_kk.signed.json
WFR=$(jq -r .payload ${GITHUB_WORKSPACE}/provenance_kk.signed.json |base64 -d | jq -r .predicate.buildDefinition.internalParameters.environment.GITHUB_WORKFLOW_REF)
echo $WFR | grep cicd_top10_3_salt\/.github\/workflows\/build.yml
בדיקה נוספת זו תיכשל אם החפץ לא נוצר על ידי ה"בטוחה" שלנו. pipeline.
אם החפץ נוצר על ידי המקור שלנו pipeline (cicd_top10_3_salt/.github/workflows/build.yml), פקודת ה-grep תצליח, אחרת היא תיכשל ותשבור את pipeline וביטול כל צעד נוסף.
ה"בונה" pipeline זוהי רק נקודת חבלה אחת לבדוק, אך כפי שצוין קודם לכן, ישנן כמה נקודות חבלה נוספות שעלינו לבדוק.
לדוגמה, מה אם קוד המקור מטופל לאחר ביצוע התשלום במאגר ולפני פקודת הבנייה? במקרה זה, הקוד שיש לבנות אינו זהה לזה המאוחסן ב- SCM.
לבדוק את נקודת החבלה הזו כל כך קל כמו לבדוק את ה-hashes של החומר בכל שלב.
SHA_ATT_MATERIAL=$(jq -r .payload ${GITHUB_WORKSPACE}/provenance_kk.signed.json | base64 -d | jq -r .predicate.attestations[0].predicate.materials[].digest[])
SHA_STEP_MATERIAL=$(jq -r .payload ${GITHUB_WORKSPACE}/provenance_kk.signed.json | base64 -d | jq -r .predicate.attestations[3].predicate.materials[0].digest[])
מסקנות
לסיכום, א אימות תוכנה היא קביעה הנטענת לגבי פיסת תוכנה, כלומר הצהרה מאומתת (מטא-נתונים) לגבי ארטיפקט תוכנה או אוסף של ארטיפקטים תוכנה.
אימותי תוכנה הם הכללה של חתימת קוד/ארטיפקטים גולמיים. האימות הוא מסמך חתום (בפורמט נתון, בדרך כלל מבוסס על JSON) המקשר מטא-נתונים לארטיפקט. הם מייצגים ראיות המקשרות בין קלטים (חומרים) לפלט (ארטיפקטים שנוצרו) בכל שלב בנייה.
אימותים מספקים תיעוד ניתן לאימות של השלבים שבוצעו לבניית תוצרי התוכנה הסופיים, כולל חומרי קלט לכל שלב ופקודות הבנייה שהורצו.
לסיכום, אימותי תוכנה הם מנגנון מצוין לבדיקת היבטים רבים ושונים של שלמות תהליך הבנייה שלנו.
סיימת את הסדרה? אל תדאג! אל תהסס לחזור ל-'מורעלים Pipeline ביצוע (ציוד מגן אישי)או כל פוסט אחר שמעורר את תשומת ליבכם שוב!
הישארו מעודכנים, נתעמק באימות תוכנה ו... build security בפוסטים נוספים בבלוג.







