CodeMender יכול לסרוק כל בקשת משיכה בצינור עיבוד הנתונים של האינטגרציה הרציפה (CI) והפיתוח הרציף (CD). הבדיקה נכשלת כש-CodeMender מוצא פגיעות ברמת חומרה CRITICAL או HIGH בקוד שמשתנה בבקשת משיכת הקוד. ממצאים בקוד שלא השתנה בבקשת משיכה מופיעים בדוח, אבל הם לא גורמים לסימון הבדיקה כנכשלת.
במאמר הזה מוסבר איך:
- סריקת בקשות למשיכת קוד באמצעות GitHub Actions, ופתיחת בקשה למשיכת קוד עם תיקונים על ידי CodeMender.
- סריקת בקשות משיכה באמצעות Cloud Build.
- סורקים את השינויים לפני כל commit באמצעות Git pre-commit hook.
איך פועלות סריקות של בקשות משיכה
כדי לסרוק בקשת משיכה, מריצים את הפקודה cm find עם הדגל --diff וענף הבסיס של בקשת המשיכה:
cm find . --diff=origin/main
בתגובה לפקודה הזו, CodeMender מבצע את הפעולות הבאות:
- הכלי משווה בין הענף של בקשת משיכת השינויים לבין ענף הבסיס, וסורק את קובצי המקור שעברו שינוי ואת הקבצים שתלויים בהם באופן ישיר, כמו קבצים שקוראים לפונקציות וקבצים שמייבאים פונקציות.
- מבדילה בין נקודות חולשה חדשות שנוצרו או נחשפו בבקשת ה-pull לבין ממצאים קיימים, שמסומנים בתווית
[LEGACY / UNTOUCHED]. בדיקת ה-CI חוסמת רק פגיעויות שנגרמות כתוצאה מבקשת המשיכה. - הכלי יוצא עם סטטוס 1 אם ממצא שנגרם על ידי בקשת המשיכה תואם לחומרת הבעיה ב-
--fail-on. ערך ברירת המחדל הואCRITICAL,HIGH.
במאמר מצבי החיפוש של CodeMender מוסבר איך --diff פועל בהשוואה למצבי סריקה אחרים.
לפני שמתחילים
CodeMender זמין בגרסת טרום-השקה ציבורית לקבוצה מוגבלת של לקוחות. כדי לקבל גישה, צריך לפנות לצוות המכירות.
-
In the Cloud de Confiance console, on the project selector page, select or create a Cloud de Confiance project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
If you're using an existing project for this guide, verify that you have the permissions required to complete this guide. If you created a new project, then you already have the required permissions.
-
Verify that billing is enabled for your Cloud de Confiance project.
Enable the Agent Platform API and Cloud Resource Manager API APIs, if any are not already enabled.
Roles required to enable APIs
To enable APIs, you need the
serviceusage.services.enablepermission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.-
Install the Google Cloud CLI.
-
Configure the gcloud CLI to use your federated identity.
For more information, see Sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init
מוודאים שגרסת CodeMender CLI שלכם תומכת בסריקות של בקשות משיכה. הצינורות שמופיעים במסמך הזה מורידים את הגרסה היציבה האחרונה בכל פעם שהם פועלים. כדי לבדוק התקנה מקומית, מריצים את הפקודה cm find --help ומחפשים את הדגל --diff. כדי לעדכן את ה-CLI, מריצים את cm update. מידע נוסף זמין במאמר התקנה והגדרה של ה-CLI.
התפקידים הנדרשים
כדי לקבל את ההרשאות שדרושות להגדרת שילובי CI/CD ל-CodeMender, בקשו מהאדמין להקצות לכם את התפקידים הבאים ב-IAM בפרויקט:
- אדמין בחשבון שירות (
roles/iam.serviceAccountAdmin) - אדמין IAM בפרויקט (
roles/resourcemanager.projectIamAdmin) -
הגדרת איחוד שירותי אימות הזהות של עומסי עבודה ל-GitHub Actions:
אדמין במאגר זהויות של עומסי עבודה (
roles/iam.workloadIdentityPoolAdmin) -
יוצרים טריגרים של Cloud Build:
- עריכה ב-Cloud Build (
roles/cloudbuild.builds.editor) - משתמש בחשבון שירות (
roles/iam.serviceAccountUser)
- עריכה ב-Cloud Build (
-
מריצים את ה-hook של Git לפני השמירה באופן מקומי:
משתמש ב-Agent Platform (
roles/aiplatform.user)
להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.
יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.
כדי לוודא שלחשבון השירות של CI/CD יש את ההרשאות הנדרשות להפעלת CodeMender בצינור CI/CD, צריך לבקש מהאדמין להקצות לחשבון השירות של CI/CD את תפקידי ה-IAM הבאים:
- משתמש ב-Agent Platform (
roles/aiplatform.user) בפרויקט שלך -
כתיבת יומני build של Cloud Build:
כותב יומנים (
roles/logging.logWriter) בפרויקט -
שמירת דוחות SARIF בקטגוריה של Cloud Storage:
Storage Object User (
roles/storage.objectUser) בקטגוריה
להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.
יכול להיות שהאדמין גם יוכל לתת לחשבון השירות של CI/CD את ההרשאות שנדרשות באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש אחרים.
שיקולי אבטחה
כשמפעילים את CodeMender בתהליך עבודה של GitHub Actions, בטריגר לפיתוח גרסת Build של Cloud Build או בGit pre-commit hook, CodeMender פועל בלי לבקש אישור. לפני שמגדירים את השילובים האלה, כדאי לקחת בחשבון את הנקודות הבאות:
- הודעות לאישור: הדגל
--yesמשבית את ההודעות שמוצגות למשתמש ומבקשות ממנו לאשר את הפקודות של הסוכן ואת הכתיבה לקובץ. הדגל--bypass-warningמדלג על האזהרה שהסוכן יכול לשנות קבצים ולהריץ פקודות במערכת שלכם. לפני שמשתמשים בדגלים האלה, חשוב לקרוא את התנאים של גרסת טרום ההשקה בתחילת המסמך, כולל התנאים לגבי השבתת האישור האנושי. - ארגז חול: צינורות הנתונים משביתים את ארגז החול של CodeMender באמצעות
--sandbox=false. לפקודות שהסוכן מריץ, כמו בנייה ובדיקות כשהוא מתקן ממצא, יש את אותה גישה כמו למשימה, כוללCloud de Confiance by S3NS האישורים והגישה לרשת. ארגז החול של Linux משתמש במרחבי שמות של משתמשים, שחלק מסביבות ה-CI, כמו קונטיינרים ללא הרשאות, לא תומכות בהם. השביתו את ארגז החול רק בסביבות מבודדות וחד-פעמיות. אם סביבת ה-CI תומכת בארגז החול, מסירים את--sandbox=false. - Runners: הפעלת תהליך העבודה של GitHub Actions ב-Runners באירוח GitHub, כמו
ubuntu-24.04, שמפעילים כל משימה במכונה וירטואלית חדשה. אל תשתמשו ב-runners באירוח עצמי שנעשה בהם שימוש חוזר בין משימות. - קוד לא מהימן: קוד בבקשת משיכה יכול להכיל טקסט שמנסה להכווין את הסוכן. תהליך העבודה של פעולות GitHub סורק רק בקשות משיכה מענפים באותו מאגר, ורק משתמשים עם הרשאת כתיבה יכולים ליצור אותן. ב-Cloud Build, משתמשים בבקרה על תגובות כדי שבעלים או משתפי פעולה יצטרכו לאשר בנייה של בקשות משיכה ממשתתפים אחרים.
- גישה: מקצים לכל חשבון שירות רק את התפקידים הנדרשים של ניהול זהויות והרשאות גישה (IAM) בשביל צינור עיבוד הנתונים שלו.
סריקת בקשות משיכה באמצעות GitHub Actions
תהליך העבודה בקטע הזה סורק כל בקשת משיכה במאגר ב-GitHub.com. כש-CodeMender מוצא נקודת חולשה ברמת חומרה CRITICAL או HIGH בשינויים של בקשת המשיכה, תהליך העבודה מבצע את הפעולות הבאות:
- הבדיקה CodeMender scan נכשלת.
- מריץ את
cm fixלכל ממצא, ופותח בקשת משיכה עם התיקונים לענף של בקשת המשיכה.
תהליך העבודה גם מעלה את הממצאים לסריקת הקוד של GitHub.
הגדרת איחוד שירותי אימות הזהות של עומסי עבודה
תהליך העבודה מאמת את Cloud de Confiance באמצעות איחוד שירותי אימות הזהות של עומסי עבודה, כך שלא צריך לאחסן מפתח של חשבון שירות ב-GitHub. מריצים את הפקודות הבאות באמצעות Google Cloud CLI:
מגדירים משתני Shell לפרויקט ולמאגר:
PROJECT_ID="PROJECT_ID" GITHUB_ORG="GITHUB_ORG" REPO="GITHUB_ORG/REPOSITORY"מחליפים את מה שכתוב בשדות הבאים:
-
PROJECT_ID: מזהה הפרויקט ב- Cloud de Confiance . -
GITHUB_ORG: שם הארגון ב-GitHub, או שם המשתמש ב-GitHub של מאגר בחשבון אישי. -
REPOSITORY: השם של המאגר ב-GitHub.
-
מפעילים את ממשקי ה-API שבהם נעשה שימוש ב-Workload Identity Federation:
gcloud services enable iam.googleapis.com \ cloudresourcemanager.googleapis.com iamcredentials.googleapis.com \ sts.googleapis.com --project="${PROJECT_ID}"יוצרים חשבון שירות לזרימת העבודה ומקצים לו את תפקיד המשתמש ב-Agent Platform ב-IAM (
roles/aiplatform.user):gcloud iam service-accounts create codemender-ci \ --project="${PROJECT_ID}" \ --display-name="CodeMender CI" gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member="serviceAccount:codemender-ci@${PROJECT_ID}.s3ns.iam.gserviceaccount.com" \ --role="roles/aiplatform.user"יוצרים מאגר זהויות של עומסי עבודה. אם כבר יש לכם מאגר ל-GitHub Actions, דלגו על השלב הזה והשתמשו במזהה של המאגר במקום
githubבשלבים הבאים.gcloud iam workload-identity-pools create github \ --project="${PROJECT_ID}" \ --location="global" \ --display-name="GitHub Actions"יוצרים ספק עבור GitHub במאגר. תנאי המאפיין מקבל טוקנים רק ממאגרים שבבעלות
GITHUB_ORG.gcloud iam workload-identity-pools providers create-oidc codemender \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github" \ --display-name="CodeMender" \ --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \ --attribute-condition="assertion.repository_owner == '${GITHUB_ORG}'" \ --issuer-uri="https://token.actions.githubusercontent.com"מאפשרים לתהליכי עבודה במאגר להשתמש בחשבון השירות:
POOL_ID=$(gcloud iam workload-identity-pools describe github \ --project="${PROJECT_ID}" \ --location="global" \ --format="value(name)") gcloud iam service-accounts add-iam-policy-binding \ "codemender-ci@${PROJECT_ID}.s3ns.iam.gserviceaccount.com" \ --project="${PROJECT_ID}" \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/${POOL_ID}/attribute.repository/${REPO}"מבקשים את השם המלא של הספק. תצטרכו אותו בקטע הבא.
gcloud iam workload-identity-pools providers describe codemender \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github" \ --format="value(name)"הפלט אמור להיראות כך:
projects/123456789/locations/global/workloadIdentityPools/github/providers/codemender
השינויים באיחוד שירותי אימות הזהות של עומסי העבודה וב-IAM ייכנסו לתוקף תוך 5 דקות לכל היותר. מידע נוסף זמין במאמר הגדרה של איחוד שירותי אימות הזהות של עומסי עבודה עם צינורות עיבוד נתונים לפריסה.
הוספת סודות למאגר
במאגר, עוברים אל הגדרות > Secrets and variables (סודות ומשתנים)> Actions (פעולות), ומוסיפים את הסודות הבאים במאגר:
| סוד | ערך |
|---|---|
GCP_PROJECT_ID |
מזהה הפרויקט. |
GCP_WIF_PROVIDER |
השם המלא של הספק מהקטע הקודם. |
GCP_WIF_SERVICE_ACCOUNT |
codemender-ci@PROJECT_ID.s3ns.iam.gserviceaccount.com, כאשר PROJECT_ID הוא מזהה הפרויקט.
|
מידע נוסף זמין במאמר שימוש בסודות ב-GitHub Actions.
קביעת הגדרות המאגר
- כדי לאפשר למשימת התיקון האוטומטי לפתוח בקשות משיכה, עוברים אל Settings > Actions > General. בקטע Workflow permissions (הרשאות של תהליך העבודה), בוחרים באפשרות Allow GitHub Actions to create and approve pull requests (מתן הרשאה ל-GitHub Actions ליצור ולאשר בקשות משיכה), ואז לוחצים על Save (שמירה). מאגר בארגון יורש את ההגדרה הזו מהארגון. אם אתם לא יכולים לשנות את זה, בקשו מבעלי הארגון. אם אתם לא משתמשים בתיקון אוטומטי, דלגו על השלב הזה. מידע נוסף מופיע במאמר בנושא ניהול ההגדרות של GitHub Actions במאגר.
- מוודאים שסריקת הקוד ב-GitHub זמינה למאגר. במאגרים פרטיים ופנימיים, כדי לסרוק את הקוד צריך להשתמש ב-GitHub Code Security. אם סריקת הקוד לא זמינה, מחקו את השלב Upload results to code scanning ואת ההרשאות
security-eventsו-actionsממשימת הסריקה. אחרת, ההעלאה נכשלת, וכך גם עבודת הסריקה. מידע נוסף זמין במאמר העלאת קובץ SARIF ל-GitHub.
הוספת תהליך העבודה
שומרים את תהליך העבודה הבא במאגר בתור .github/workflows/codemender.yml:
name: CodeMender
on:
pull_request:
permissions: {}
defaults:
run:
shell: bash
env:
CM_DOWNLOAD_URL: https://artifactregistry.googleapis.com/download/v1/projects/cmoc-prod/locations/us/repositories/codemender-cli-production/files/cm%3Astable%3Acm-linux-amd64.zip:download?alt=media
jobs:
scan:
name: CodeMender scan
# Workflows for fork and Dependabot pull requests can't read this
# repository's secrets, so they can't authenticate to Google Cloud.
if: >-
github.event.pull_request.head.repo.full_name == github.repository &&
github.actor != 'dependabot[bot]'
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
contents: read
id-token: write # Workload Identity Federation
security-events: write # Upload SARIF to code scanning
actions: read # Upload SARIF from a private repository
outputs:
findings: ${{ steps.scan.outputs.findings }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # cm needs the base branch history
persist-credentials: false
- uses: google-github-actions/auth@v3
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
service_account: ${{ secrets.GCP_WIF_SERVICE_ACCOUNT }}
- name: Install the CodeMender CLI
run: |
curl -fsSL -o "$RUNNER_TEMP/cm.zip" "$CM_DOWNLOAD_URL"
unzip -q -o "$RUNNER_TEMP/cm.zip" -d "$RUNNER_TEMP/cm"
echo "$RUNNER_TEMP/cm" >> "$GITHUB_PATH"
- name: Scan the pull request
id: scan
env:
BASE_REF: ${{ github.base_ref }}
FAIL_ON: CRITICAL,HIGH
run: |
cm init
status=0
cm find . \
--diff="origin/$BASE_REF" \
--diff-workers=16 \
--fail-on="$FAIL_ON" \
--format=sarif \
--output=codemender.sarif \
--sandbox=false \
--yes \
--bypass-warning || status=$?
# Save the findings that failed the scan for the autofix job. Like the
# CI gate, skip findings labeled [LEGACY / UNTOUCHED]: they're in code
# that the pull request didn't change.
echo '[]' > "$RUNNER_TEMP/codemender-findings.json"
if [ "$status" -ne 0 ]; then
cm report --format=json --status=OPEN \
| jq --arg fail_on "$FAIL_ON" '
($fail_on | ascii_upcase | split(",")) as $severities
| [.[]
| select(.title | startswith("[LEGACY / UNTOUCHED]") | not)
| select(.severity | ascii_upcase | IN($severities[]))]' \
> "$RUNNER_TEMP/codemender-findings.json"
fi
echo "findings=$(jq length "$RUNNER_TEMP/codemender-findings.json")" >> "$GITHUB_OUTPUT"
exit "$status"
- name: Upload results to code scanning
if: ${{ !cancelled() && hashFiles('codemender.sarif') != '' }}
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: codemender.sarif
category: codemender
- name: Save findings for autofix
if: ${{ !cancelled() && steps.scan.outputs.findings > 0 }}
uses: actions/upload-artifact@v7
with:
name: codemender-findings
path: ${{ runner.temp }}/codemender-findings.json
retention-days: 1
autofix:
name: CodeMender autofix
needs: scan
if: ${{ !cancelled() && needs.scan.outputs.findings > 0 }}
runs-on: ubuntu-24.04
timeout-minutes: 60
permissions:
contents: write # Push the fix branch
pull-requests: write # Open the fix pull request
id-token: write # Workload Identity Federation
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.head_ref }}
persist-credentials: false
- uses: google-github-actions/auth@v3
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
service_account: ${{ secrets.GCP_WIF_SERVICE_ACCOUNT }}
- name: Install the CodeMender CLI
run: |
curl -fsSL -o "$RUNNER_TEMP/cm.zip" "$CM_DOWNLOAD_URL"
unzip -q -o "$RUNNER_TEMP/cm.zip" -d "$RUNNER_TEMP/cm"
echo "$RUNNER_TEMP/cm" >> "$GITHUB_PATH"
- uses: actions/download-artifact@v8
with:
name: codemender-findings
path: ${{ runner.temp }}/codemender
- name: Fix findings
run: |
# Keep CodeMender state and the auth action's credentials file out of
# the commits, and out of the `git clean` that cm fix runs.
printf '%s\n' .cm_project 'gha-creds-*.json' >> .git/info/exclude
cm init
# Fix in the repository root instead of each file's directory.
printf 'project_paths:\n - "%s"\n' "$GITHUB_WORKSPACE" \
>> ~/.codemender/config.yaml
cm report import -f "$RUNNER_TEMP/codemender/codemender-findings.json"
git config user.name "github-actions[bot]"
git config user.email \
"41898282+github-actions[bot]@users.noreply.github.com"
cm report --format=json --status=OPEN \
| jq -r '.[] | [.finding_id, .title] | @tsv' \
> "$RUNNER_TEMP/findings.tsv"
while IFS=$'\t' read -r id title; do
# cm fix exits 0 when it makes no edits, so also check for changes.
if cm fix "$id" \
--sandbox=false --yes --bypass-warning < /dev/null &&
! git diff --quiet; then
git commit -q -a -m "Fix $title" -m "CodeMender finding $id"
else
echo "::warning::CodeMender didn't fix \"$title\" ($id)."
fi
# Discard files the fix agent created, such as test output.
git reset -q --hard
git clean -q -fd
done < "$RUNNER_TEMP/findings.tsv"
- uses: peter-evans/create-pull-request@v8
with:
branch: codemender/fix-pr-${{ github.event.pull_request.number }}
base: ${{ github.head_ref }}
title: "CodeMender fixes for #${{ github.event.pull_request.number }}"
body: |
CodeMender generated these fixes for findings in #${{ github.event.pull_request.number }}.
Review each commit before you merge this pull request into `${{ github.head_ref }}`.
פרטי תהליך העבודה
התרשים הבא מציג את האינטראקציה בין הסריקה של בקשת המיזוג לבין עבודות התיקון האוטומטי:
הפעולה CodeMender scan מבצעת את הפעולות הבאות:
- הפונקציה מאחזרת את בקשת המיזוג עם ההיסטוריה המלאה שלה. בבקשות משיכה, GitHub בודק את ה-commit של המיזוג של הסתעפות בקשת המשיכה לתוך הסתעפות הבסיס.
- מבצע אימות ב- Cloud de Confiance ומוריד את הגרסה היציבה האחרונה של CodeMender CLI.
- מריצים את הפקודה
cm find --diffמול ענף הבסיס. המשימה תיכשל אם CodeMender ימצא חולשה ברמת החומרה שצוינה ב-FAIL_ONבשינויים של בקשת ה-Pull. - הדוח מועלה לסריקת הקוד ב-GitHub, גם אם הסריקה נכשלת. הדוח כולל ממצאים עם התווית
[LEGACY / UNTOUCHED]. בנוסף, סריקת הקוד מציגה ממצא בבדיקות של בקשת המשיכה כשכל שורות הממצא נמצאות בהבדלים של בקשת המשיכה. - שומר את הממצאים שנכשלו בעבודה לצורך תיקון אוטומטי.
משימת הסריקה לא פועלת בבקשות משיכה מפיצולים או מ-Dependabot, כי תהליכי העבודה של בקשות המשיכה האלה לא יכולים לקרוא את הסודות של המאגר.
ב-GitHub, משימה שדילגו עליה מדווחת כמשימה שהסתיימה בהצלחה, כך שהבדיקה לא חוסמת את בקשות המשיכה האלה, גם אם מגדירים אותה כבדיקה נדרשת. אפשר לבדוק את בקשות המשיכה (pull request) האלה בעצמך, או לסרוק אותן באופן מקומי באמצעות cm find --diff.
משימת התיקון האוטומטי של CodeMender פועלת כשמשימת הסריקה שומרת את הממצאים. הוא מבצע את הפעולות הבאות:
- הפונקציה מאחזרת את הענף של בקשת המיזוג.
- הכלי מריץ
cm fixלכל ממצא ומבצע כל תיקון בנפרד. אם CodeMender לא מתקן ממצא, המשימה מתעדת אזהרה ביומן. העבודה שומרת רק שינויים בקבצים שכבר נמצאים במאגר, ומוחקת קבצים שסוכן התיקון יוצר, כמו פלט של בדיקות. - פותח בקשת משיכה מהענף
codemender/fix-pr-NUMBERלענף בקשת המשיכה, כאשרNUMBERהוא מספר בקשת המשיכה. אם בקשת המיזוג לתיקון כבר קיימת, העדכון מתבצע במשימה. אם CodeMender לא מתקן ממצאים, או אם המשימה מגיעה למגבלת הזמן של 60 דקות, המשימה לא פותחת בקשת משיכה.
בדיקה ומיזוג של תיקונים
GitHub לא מפעיל באופן אוטומטי תהליכי עבודה לבקשות משיכה שתהליך עבודה יוצר באמצעות GITHUB_TOKEN. כדי לסרוק את בקשת המיזוג של התיקון, משתמש עם גישת כתיבה למאגר לוחץ על Approve workflows to run (אישור הפעלת תהליכי עבודה) בבקשת המיזוג של התיקון.
כשממזגים את בקשת משיכה (pull request) לתיקון, הענף של בקשת משיכה (pull request) משתנה, ותהליך העבודה סורק שוב את בקשת משיכה (pull request) המקורית.
התאמה אישית של תהליך העבודה
אפשר להתאים אישית את תהליך העבודה בדרכים הבאות:
- כדי לשנות את רמות החומרה שגורמות לבדיקה להיכשל, בשלב Scan the pull request, מגדירים את
FAIL_ONלרשימה של רמות חומרה מופרדות בפסיקים בלי רווחים, כמוCRITICAL,HIGH,MEDIUM. הערכים התקינים הםCRITICAL,HIGH,MEDIUMו-LOW. - כדי לדווח על ממצאים בלי שהבדיקה תיכשל, צריך להגדיר את
FAIL_ON: "". תהליך העבודה עדיין מעלה ממצאים לסריקת הקוד, אבל הוא לא מפעיל את משימת התיקון האוטומטי. כדי לסרוק בקשות למשיכת קוד רק בענפים מסוימים, מוסיפים
branchesפילטר לטריגרpull_request. לאחר מכן, תהליך העבודה לא סורק בקשות משיכה לתיקון, כי הבסיס שלהן הוא ענף של בקשת משיכה:on: pull_request: branches: [main]כדי להשבית את התיקון האוטומטי, מוחקים את המשימה
autofixואת השלב Save findings for autofix.
סריקת בקשות משיכה באמצעות Cloud Build
ה-build בחלק הזה סורק כל בקשת משיכה במאגר ב-GitHub שמחובר ל-Cloud Build. ה-build והבדיקה של GitHub נכשלים כש-CodeMender מוצא פרצת אבטחה ברמת חומרה CRITICAL או HIGH בשינויים של בקשת ה-pull. ה-build לא מתקן את הממצאים.
לפני שמתחילים, צריך לבצע את הפעולות הבאות:
- מקשרים את המאגר ל-Cloud Build כמאגר מהדור השני. מידע נוסף זמין במאמר בנושא חיבור למאגר GitHub.
מפעילים את Cloud Build API ואת IAM API בפרויקט שיש לו גישה ל-CodeMender. הגרסה משתמשת ב-CodeMender בפרויקט שמריץ את הגרסה.
PROJECT_ID="PROJECT_ID" gcloud services enable cloudbuild.googleapis.com iam.googleapis.com \ --project="${PROJECT_ID}"מחליפים את
PROJECT_IDבמזהה הפרויקט ב- Cloud de Confiance.
יצירה של חשבון שירות
יוצרים חשבון שירות ל-build. כדי להשתמש ב-CodeMender, מקצים לו את תפקיד ה-IAM "משתמש בפלטפורמת הסוכנים" (roles/aiplatform.user), וכדי לכתוב יומני build, מקצים לו את התפקיד "כתיבת יומנים" (roles/logging.logWriter):
SA="codemender-build@${PROJECT_ID}.s3ns.iam.gserviceaccount.com"
gcloud iam service-accounts create codemender-build \
--project="${PROJECT_ID}" \
--display-name="CodeMender Cloud Build"
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${SA}" \
--role="roles/aiplatform.user"
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${SA}" \
--role="roles/logging.logWriter"
כדי לשמור דוחות SARIF בקטגוריה של Cloud Storage, צריך לתת לחשבון השירות גם גישה לקטגוריה:
BUCKET="BUCKET"
gcloud storage buckets add-iam-policy-binding "gs://${BUCKET}" \
--member="serviceAccount:${SA}" \
--role="roles/storage.objectUser"
מחליפים את BUCKET בשם של הקטגוריה שלכם ב-Cloud Storage.
הוספת הגדרות ה-build
מבצעים commit של תצורת ה-build הבאה לשורש של המאגר בתור cloudbuild.yaml:
# Scans a pull request with CodeMender. The build fails when CodeMender finds
# a CRITICAL or HIGH vulnerability in the pull request's changes.
steps:
- id: install-codemender
name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
script: |
#!/usr/bin/env bash
set -euo pipefail
curl -fsSL -o /tmp/cm.zip "$_CM_DOWNLOAD_URL"
python3 -m zipfile -e /tmp/cm.zip /workspace/.codemender-cli
chmod +x /workspace/.codemender-cli/cm
- id: fetch-history
name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
script: |
#!/usr/bin/env bash
set -euo pipefail
: "${_BASE_BRANCH:?Run this build from a pull request trigger.}"
# Triggers check out only the pull request's commit. CodeMender needs the
# history back to where the pull request branched from the base branch.
# Fetch from origin, or from GitHub if origin isn't configured.
refspec="+refs/heads/$_BASE_BRANCH:refs/remotes/origin/$_BASE_BRANCH"
git fetch --quiet --unshallow origin "$refspec" ||
git fetch --quiet --unshallow \
"https://github.com/$REPO_FULL_NAME.git" "$refspec"
merge_base=$(git merge-base HEAD "origin/$_BASE_BRANCH")
echo "Merge base with $_BASE_BRANCH: $merge_base"
- id: scan
name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
script: |
#!/usr/bin/env bash
set -uo pipefail
export PATH="/workspace/.codemender-cli:$PATH"
# The project that has access to CodeMender.
export GOOGLE_CLOUD_PROJECT="$PROJECT_ID"
cm init || exit 1
status=0
cm find . \
--diff="origin/$_BASE_BRANCH" \
--diff-workers=16 \
--fail-on=CRITICAL,HIGH \
--format=sarif \
--output=codemender.sarif \
--sandbox=false \
--yes \
--bypass-warning || status=$?
# cm find writes the SARIF report when the scan completes.
if [ -f codemender.sarif ]; then
# cm find doesn't print finding details, so print them here.
cm report --status=OPEN --format=md
if [ -n "${_REPORT_BUCKET:-}" ]; then
gcloud storage cp codemender.sarif \
"gs://$_REPORT_BUCKET/codemender/$BUILD_ID.sarif" || status=1
fi
fi
exit "$status"
substitutions:
_CM_DOWNLOAD_URL: https://artifactregistry.googleapis.com/download/v1/projects/cmoc-prod/locations/us/repositories/codemender-cli-production/files/cm%3Astable%3Acm-linux-amd64.zip:download?alt=media
_REPORT_BUCKET: '' # Optional: a bucket to save the SARIF report in.
timeout: 1200s
options:
automapSubstitutions: true
logging: CLOUD_LOGGING_ONLY
יצירת הטריגר
יוצרים טריגר שמריץ את ה-build לכל בקשת משיכה (pull request) אל main:
REGION="REGION"
CONNECTION="CONNECTION"
REPOSITORY="REPOSITORY"
gcloud builds triggers create github \
--project="${PROJECT_ID}" \
--region="${REGION}" \
--name="codemender-scan" \
--repository="projects/${PROJECT_ID}/locations/${REGION}/connections/${CONNECTION}/repositories/${REPOSITORY}" \
--pull-request-pattern='^main$' \
--comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY \
--build-config=cloudbuild.yaml \
--service-account="projects/${PROJECT_ID}/serviceAccounts/${SA}"
מחליפים את מה שכתוב בשדות הבאים:
-
REGION: האזור של החיבור למאגר ב-Cloud Build. -
CONNECTION: השם של חיבור המאגר של Cloud Build. -
REPOSITORY: השם של המאגר המחובר ב-Cloud Build.
שימו לב לאפשרויות הבאות:
-
--pull-request-patternהוא ביטוי רגולרי לענף הבסיס של בקשת משיכת השינויים. משתמשים בתווים^ו-$כדי להתאים את כל שם הענף. - עם
--comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY, ה-build מופעל באופן אוטומטי לבקשות משיכה מבעלי המאגר וממשתפי פעולה. בבקשות משיכה של משתתפים אחרים, ה-build פועל אחרי שהבעלים או שותף העריכה מגיבים/gcbrunעל בקשת המשיכה. - כדי לשמור דוחות SARIF בדלי, מוסיפים את
--substitutions=_REPORT_BUCKET="${BUCKET}".
אפשר גם ליצור את הטריגר במסוף Cloud de Confiance . מידע נוסף זמין במאמר בנושא יצירת מאגרים מ-GitHub.
כדי להציג את יומני ה-build ב-GitHub, מוסיפים את --include-logs-with-status כשיוצרים את הטריגר, ונותנים לחשבון השירות את התפקיד "צפייה ביומנים" (roles/logging.viewer). כל מי שיכול לראות את הבדיקה ב-GitHub יכול לקרוא את יומני ה-build, כולל הממצאים.
איך מתבצעת הבנייה
התהליך כולל שלושה שלבים:
-
install-codemenderמוריד את הגרסה היציבה האחרונה של CodeMender CLI. -
fetch-historyמאחזר את ההסתעפות הבסיסית ואת ההיסטוריה ש-CodeMender צריך. Cloud Build בודק רק את הקומיט שהתחיל את הבנייה. השלב מאחזר מהמאגר המרוחקorigin. אם לא מגדירים אתorigin, השלב מאחזר מ-GitHub בלי פרטי כניסה, וזה עובד רק במאגרים ציבוריים. במקרה כזה, מאגר פרטי צריך פרטי כניסה, כמו מפתח SSH. מידע נוסף זמין במאמר גישה ל-GitHub מ-build באמצעות מפתחות SSH. -
scanמריץ אתcm find --diffמול ענף הבסיס. בסיום הסריקה, כל הממצאים מודפסים ביומן הבנייה. אם מגדירים את_REPORT_BUCKET, השלב גם מעתיק את דוח ה-SARIF אלgs://BUCKET/codemender/BUILD_ID.sarif.
כדי לשנות את רמות החומרה שגורמות לכך שה-build ייכשל, עורכים את --fail-on בשלב scan. אם מריצים את ה-build בלי טריגר של בקשת משיכה, הוא נכשל עם ההודעה Run this build from a pull request trigger.
סריקה לפני כל קומיט
הוק pre-commit של Git יכול לסרוק את השינויים שהכנתם ולחסום את ה-commit אם CodeMender מוצא חולשה ברמת חומרה CRITICAL או HIGH. מפתחים יכולים לדלג על ה-hook, אז כדאי להשתמש בו בנוסף לסריקה ב-CI, ולא במקומה.
כל מפתח שמשתמש ב-hook צריך:
- ה-CLI של CodeMender, מותקן ומוגדר כמו שמתואר בקטע התקנה והגדרה של ה-CLI, כולל
gcloud auth application-default loginו-cm init. הוו צריךcmבPATH. - התפקיד Agent Platform User (משתמש ב-Agent Platform) (
roles/aiplatform.user) בפרויקט עם גישה ל-CodeMender. CodeMender משתמש בפרויקט שבמשתנה הסביבהGOOGLE_CLOUD_PROJECT. אם המשתנה הזה לא מוגדר, CodeMender משתמש בפרויקט מ-Application Default Credentials או בפרויקט שמוגדר כברירת מחדל ב-CLI של gcloud.
כדי להוסיף את ה-hook, שומרים את הסקריפט הבא בשם .git/hooks/pre-commit במאגר:
#!/bin/sh
# Scans staged changes with CodeMender before each commit.
if ! cm find . --diff --staged --fail-on=CRITICAL,HIGH \
--yes --bypass-warning; then
echo "CodeMender blocked this commit. To see the findings, run:" >&2
echo " cm report --status=OPEN" >&2
echo "To commit anyway, run git commit --no-verify." >&2
exit 1
fi
הופכים את הסקריפט לקובץ הפעלה, ואז מוסיפים את .cm_project לקובץ .gitignore, כדי לא לבצע commit לקובץ שנוצר על ידי CodeMender למעקב אחרי המאגר:
chmod +x .git/hooks/pre-commit
echo .cm_project >> .gitignore
כשמריצים את git commit, ה-hook סורק את הקבצים עם השינויים שהועברו ל-stage. הסריקה עשויה להימשך כמה דקות. ה-hook לא משבית את ארגז החול של CodeMender.
כדי לבצע את ה-commit בלי הסריקה, מריצים את git commit --no-verify.
סריקת דגלים
הדגלים הבאים של cm find שולטים בסריקות של בקשות משיכה. כדי לראות את כל הדגלים, מריצים את הפקודה cm
find --help:
| דגל | ברירת מחדל | תיאור |
|---|---|---|
--diff[=REF] |
מושבת |
סורק את השינויים בהשוואה ל-REF, כמו
origin/main. בלי REF, הסריקות
לא כוללות שינויים שלא נשמרו בקבצים שעוקבים אחריהם (בהשוואה ל-HEAD). אי אפשר להשתמש באפשרות הזו עם --deep.
|
--staged |
מושבת | ב---diff, הסריקות מתבצעות רק על שינויים שהועברו לשלב ההכנה. |
--diff-depth DEPTH |
1 |
עומק המעבר לניתוח ההשפעה (1 עד 3, ברירת מחדל: 1-hop). |
--diff-workers COUNT |
4 |
מספר הקבצים לסריקה בו-זמנית, מ-1 עד 16. |
--diff-max-neighbors COUNT |
10 |
המספר המקסימלי של קבצים תלויים לסריקה. |
--fail-on SEVERITIES |
CRITICAL,HIGH |
במקרה של --diff, רמות החומרה שגורמות ל-cm find
לצאת עם סטטוס 1. אם הערך ריק, הממצאים לא משפיעים על סטטוס היציאה.
|
--fail-on-truncation |
מושבת |
עם --diff, יוצא עם סטטוס 1 אם CodeMender מוצא יותר קבצים תלויים ממה ש---diff-max-neighbors מאפשר.
|
--format FORMAT |
table |
פורמט הדוח: table, json או sarif.
|
--output FILE |
פלט רגיל | הקובץ שאליו ייכתב הדוח. |
פתרון בעיות
בקטע הזה מוסבר איך לפתור בעיות נפוצות שקשורות להפעלת CodeMender בצינורות עיבוד נתונים של CI/CD.
ההרשאה נדחתה
ביומן מופיעה שורה כמו זו:
[1/1] ❌ src/app.py: start session failed: StartSession failed with HTTP 403 Forbidden.
ההודעה יכולה לכלול גם את Permission 'aiplatform.interactions.create'
denied. זה מה שכדאי לבדוק:
- לפרויקט יש גישה ל-CodeMender.
- לחשבון השירות או למשתמש יש את התפקיד "משתמש בפלטפורמת הסוכנים" (
roles/aiplatform.user) בפרויקט. - Agent Platform API מופעל בפרויקט.
- הכלי CodeMender משתמש בפרויקט הנכון. ב-GitHub Actions, בודקים את הסוד
GCP_PROJECT_ID. Cloud Build משתמש בפרויקט שבו מופעלת הבנייה. באופן מקומי, בודקים את משתנה הסביבהGOOGLE_CLOUD_PROJECT, או את פרויקט ברירת המחדל אם המשתנה לא מוגדר.
הגדרת המשאב בתהליך
אם ביומן מופיע Resource setup has just started. Please try again shortly. או Resource setup is in progress. Please try again shortly., סימן ש-CodeMender מגדיר משאבים לפרויקט. בדרך כלל זה לוקח כמה דקות. מריצים את המשימה שוב מאוחר יותר.
סימון לא ידוע: --diff
אם הפקודה cm find נכשלת עם Error: unknown flag: --diff, הגרסה של ה-CLI לא תומכת בסריקות של בקשות משיכה. מריצים את cm update או מורידים את הגרסה האחרונה.
לא נמצא ענף בסיס
אם הפקודה cm find נכשלת עם שגיאה כמו השגיאה הבאה, הענף הבסיסי לא נמצא ב-checkout:
Error: retrieving VCS diff: git diff failed: exit status 128: fatal: ambiguous argument 'origin/main': unknown revision or path not in the working tree.
לפני שמריצים את הפקודה cm find, צריך לאחזר את ענף הבסיס ואת ההיסטוריה שלו. ב-GitHub Actions, מגדירים את fetch-depth: 0 ב-actions/checkout.
קבצים שלא נסרקו
שורה עם ❌, כמו [1/1] ❌ src/app.py: start session failed, מציינת ש-CodeMender לא הצליח לסרוק את הקובץ הזה. צריך לבדוק את השגיאה בשורה ואז להריץ את העבודה שוב.
אין בקשת משיכה לתיקון
אם תהליך העבודה לא פותח בקשת משיכה לתיקון, צריך לבדוק את הדברים הבאים:
- אם משימת התיקון האוטומטי נכשלת כשיוצרים את בקשת משיכת השינויים, מפעילים את האפשרות Allow GitHub Actions to create and approve pull requests (מתן הרשאה ל-GitHub Actions ליצור ולאשר בקשות משיכת שינויים). מידע נוסף זמין במאמר קביעת הגדרות למאגר.
- אם עבודת התיקון האוטומטי מצליחה בלי לפתוח בקשת משיכה, CodeMender לא תיקן אף ממצא. ביומן המשימה מוצגת אזהרה לכל ממצא ש-CodeMender לא תיקן.
העלאת סריקת הקוד נכשלה
אם שלב ההעלאה נכשל עם GitHub Code Security or GitHub Advanced Security
must be enabled for this repository to use code scanning, הפעילו את GitHub Code Security למאגר או מחקו את שלב ההעלאה. מידע נוסף זמין במאמר קביעת הגדרות למאגר.
האזהרה לא אושרה
אם הפקודה cm נכשלת עם השגיאה warning not acknowledged. Please run interactively once to
acknowledge or pass --bypass-warning, CodeMender צריך אישור שהוא לא יכול לבקש בסביבה לא אינטראקטיבית. מוסיפים את --bypass-warning לפקודה. לפני שתעשו זאת, קראו את תנאי התצוגה המקדימה בחלק העליון של הדף הזה.
לקבלת עזרה נוספת, אפשר לפנות לצוות המכירות.