השילוב של CI/CD מחבר את צינורות ה-CI/CD שלכם להגנה על ארטיפקטים כדי לזהות נקודות חולשה בקונטיינרים במהלך שלב ה-build.
הסורק תומך ב-GitHub Actions, ב-Cloud Build וב-Jenkins. כשמשלבים אותו בפייפליין, הוא מעריך קובצי אימג' של קונטיינרים בהתאם למדיניות ההגנה על ארטיפקטים שלכם לפני שהקובצי אימג' נדחפים למרשם.
יכולות הסורק
השילוב של CI/CD פועל כקובץ בינארי בתהליך העבודה של CI/CD כדי לבצע את המשימות הבאות:
- הערכת מדיניות בזמן ה-build: סריקה של קובצי אימג' חדשים של קונטיינרים בהשוואה למדיניות שהוגדרה ב-Artifact Guard.
- חסימת גרסאות build: מחזירה קודי יציאה ל-CI/CD runner (GitHub Actions, Cloud Build או Jenkins) כדי לחסום גרסאות build שמפירות את מדיניות האבטחה שלכם.
- דיווח על סריקות: שליחת תוצאות סריקת הפגיעויות אל Security Command Center ופלט של דוחות מקומיים בפורמטים JSON או SARIF.
תפקידים ותחומי אחריות
השילוב של CI/CD מיועד לצוותים הבאים:
- צוותי DevOps או צוותי הנדסת פלטפורמות: יצירת מחברי צינורות והוספת שלבים להפעלת סורק להגדרות של תהליכי עבודה של CI/CD.
- אדמינים להגדרות האבטחה: מגדירים את מדיניות הפגיעות בזמן הבנייה שהסורק אוכף.
- מפתחי אפליקציות: כדאי לעיין ביומני ההפעלה של הסריקה בפלט של בניית CI/CD כדי לזהות הפרות מדיניות ולתקן אותן.
מושגים והגדרות חשובים
- נקודות חולשה וחשיפות נפוצות (CVE): נקודת חולשה באבטחת מחשב שנחשפת לציבור ומקבלת מזהה ייחודי.
- רשימת חומרים (SBOM) של תוכנה: רשימה של רכיבי תוכנה ותלותיות שניתנת לקריאה על ידי מכונה, ומשמשת לזיהוי של CVE וסיכוני אבטחה אחרים.
- ארטיפקט: בהקשר של הגנה על ארטיפקטים, קובץ אימג' של קונטיינר שנוצר על ידי פייפליין של CI/CD.
- מחבר: משאב שמקשר את צינור ה-CI/CD שלכם ל-Artifact Guard. כשמעבירים את מזהה המחבר מצינור ה-CI במהלך סריקה, הוא קובע אילו מדיניות מעריכות את התמונה.
- מדיניות CI: מדיניות בנושא פגיעויות שמגדירה את כללי ה-CVE, החומרה והחבילה הספציפיים שנאכפים במהלך בניית CI/CD.
תהליך עבודה כללי
כדי להגדיר ולהריץ סריקות של פגיעויות ב-CI/CD, מבצעים את תהליך העבודה הבא:
- יוצרים מחבר CI לפלטפורמת היעד של CI/CD.
- יוצרים מדיניות הגנה על ארטיפקטים שכוללת את מזהה המחבר בהיקף הפייפליין שלה.
- מגדירים את צינור ה-CI/CD כדי לבצע אימות ל-Google Cloud, ליצור את קובץ אימג' של קונטיינר ולהריץ את קונטיינר הסורק.
כשהפייפליין פועל, הסורק מעריך את קובץ אימג' של קונטיינר בהתאם למדיניות שלכם. אם התמונה מפירה את המדיניות, הסורק מחזיר קוד יציאה של כשל כדי שה-build ייכשל. לאחר מכן, המפתחים יכולים לבדוק את יומני ה-build, לעדכן תלות פגיעה ולהריץ מחדש את ה-build.
לפני שמתחילים
כדי להשתמש בשילוב CI/CD, צריך להפעיל את הגנה על ארטיפקטים. הוראות מפורטות זמינות בקטע לפני שמתחילים במאמרי העזרה בנושא הגנה על ארטיפקטים.
יצירת מחבר
המסוף
כדי ליצור מחבר ב Google Cloud מסוף, פועלים לפי השלבים הבאים:
- במסוף Google Cloud , עוברים אל Security > Settings (אבטחה > הגדרות).
- בכרטיס Artifact guard (הגנה על ארטיפקטים), לוחצים על Manage settings (ניהול הגדרות).
- לוחצים על Create connector (יצירת מחבר) ומזינים את הפרטים הבאים של המחבר:
- מזהה המחבר: הוספת מזהה למחבר.
- תיאור: מזינים תיאור של המחבר.
- פלטפורמת CI/CD: בוחרים את פלטפורמת ה-CI/CD המתאימה מהרשימה. משתמשים במחבר הזה רק בצינורות עיבוד נתונים שנבנו באמצעות פלטפורמת ה-CI/CD שנבחרה.
- לוחצים על יצירה.
הודעה מאשרת שהמחבר נוצר בהצלחה. בטבלה מחברים מופיעים המחברים הזמינים.
CLI של gcloud
כדי ליצור מחבר באמצעות ה-CLI של gcloud, מריצים את הפקודה הבאה:
gcloud alpha scc artifact-guard connectors create CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER) \ --pipeline-type=PIPELINE_TYPE \ [--description=DESCRIPTION] \ [--display-name=DISPLAY_NAME]
מחליפים את מה שכתוב בשדות הבאים:
- CONNECTOR_ID: מזהה של המחבר (לדוגמה,
my-connector). - LOCATION: המיקום של Security Command Center שבו מאוחסנים הנתונים. יש תמיכה רק ב-
global. - ORGANIZATION_ID: מזהה הארגון.
- PROJECT_NUMBER: מספר הפרויקט.
- PIPELINE_TYPE: סוג הפייפליין של CI/CD. הערך חייב להיות אחד מהערכים הבאים:
GOOGLE_CLOUD_BUILDGITHUB_ACTIONSJENKINS_PIPELINE
- DESCRIPTION: תיאור טקסט של המחבר.
- DISPLAY_NAME: שם מוצג ידידותי למשתמש עבור המחבר.
עדכון מחבר
המסוף
כדי לקשר מדיניות למחבר במסוף Google Cloud :
- במסוף Google Cloud , עוברים אל Security > Settings (אבטחה > הגדרות).
- בכרטיס Artifact guard (הגנה על ארטיפקטים), לוחצים על Manage settings (ניהול הגדרות).
- בטבלה מחברים, לוחצים על סמל האפשרויות הנוספות לצד המחבר ובוחרים באפשרות הוספת מדיניות.
- ממשיכים בשלבים ליצירה או לעדכון של מדיניות הגנה על ארטיפקטים. מידע נוסף זמין במאמר יצירת מדיניות.
CLI של gcloud
כדי להציג מחברים קיימים ולעדכן את השיוכים שלהם למדיניות באמצעות ה-CLI של gcloud, משתמשים בפקודות הבאות:
הצגת רשימה של מחברים
gcloud alpha scc artifact-guard connectors list PARENT
מחליפים את מה שכתוב בשדות הבאים:
- PARENT: ארגון או פרויקט. הפורמטים הקבילים של משאב האב כוללים:
organizations/ORGANIZATION_ID/locations/LOCATIONprojects/PROJECT_NUMBER/locations/LOCATION
תיאור מחבר
gcloud alpha scc artifact-guard connectors describe CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
עדכון השיוך של מדיניות מחברים
כדי לקשר מחבר למדיניות, צריך לכלול את מזהה המחבר בהיקף צינור הנתונים של קובץ הגדרת המדיניות ולעדכן את המדיניות באמצעות הפקודה gcloud alpha scc artifact-guard policies update. מידע נוסף זמין במאמר יצירת מדיניות.
מחיקת מחבר
המסוף
כדי למחוק מחבר במסוף Google Cloud :
- במסוף Google Cloud , עוברים אל Security > Settings (אבטחה > הגדרות).
- בכרטיס Artifact guard (הגנה על ארטיפקטים), לוחצים על Manage settings (ניהול הגדרות).
- בטבלה Connectors (מחברים), לוחצים על לצד המחבר ובוחרים באפשרות Delete connector (מחיקת המחבר).
- פועלים לפי הנחיות האישור כדי למחוק את המחבר. כדי לבטל, לוחצים על ביטול.
CLI של gcloud
כדי למחוק מחבר באמצעות ה-CLI של gcloud, מריצים את הפקודה הבאה:
gcloud alpha scc artifact-guard connectors delete CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
הרצת הערכה
יש תמיכה בסריקת פגיעויות ב-GitHub Actions ובצינורות Jenkins. כדי לבצע הערכה, צריך לבצע את הפעולות הבאות:
הגדרת סודות
צינורות CI/CD שפועלים מחוץ ל- Google Cloud יכולים לבצע אימות באמצעות מפתחות של חשבון שירות או איחוד שירותי אימות הזהות של עומסי עבודה. הוראות מפורטות ליצירת סודות מופיעות במאמרים הבאים:
מפתחות לחשבונות שירות
איחוד שירותי אימות הזהות של עומסי עבודה (ל-GitHub Actions)
צריך להוסיף סודות לסביבת ה-CI/CD באחת מהשיטות הבאות:
שימוש במפתח של חשבון שירות
סוד אחד:
-
GCP_CREDENTIALS: התוכן של קובץ מפתח ה-JSON של חשבון השירות שהורדתם.
שיטת איחוד שירותי אימות הזהות של עומסי עבודה
שני סודות:
GCP_WORKLOAD_IDENTITY_PROVIDER: שם המשאב המלא של ספק מאגרי זהויות של עומסי עבודה. לדוגמה,projects/12345/locations/global/workloadIdentityPools/my-pool/providers/my-provider.GCP_SERVICE_ACCOUNT: כתובת האימייל של חשבון השירות שרוצים להתחזות אליו.
תבניות לשילוב צינורות עיבוד נתונים
כדי להפעיל הערכה, צריך ליצור קובץ שספציפי לצינור (Cloud Build, GitHub Actions או Jenkins) באמצעות תבניות הדוגמה הבאות:
Cloud Build
במאמר הגדרות של משתנים מוסבר על כל שדה.
steps: # Step 1: Generate auth token - name: 'gcr.io/cloud-builders/gcloud' id: 'Generate Token' entrypoint: 'bash' args: - '-c' - | echo "Starting token generation..." gcloud auth print-access-token > /workspace/gcp_token.txt if [ $? -eq 0 ]; then echo "Token generated successfully." else echo "Failed to generate token." >&2 exit 1 fi # Step 2: Build the image locally - name: 'gcr.io/cloud-builders/docker' id: 'Build Image' entrypoint: 'bash' args: - '-c' - | echo "🚧 Building Docker image from source code..." docker build -t ${_IMAGE_NAME_TO_SCAN}:${_IMAGE_TAG} . if [ $? -ne 0 ]; then echo "❌ Docker build failed." exit 1 fi echo "✅ Docker image built successfully: ${_IMAGE_NAME_TO_SCAN}:${_IMAGE_TAG}" # Step 3: Image scan for vulnerabilities - id: 'Image-Analysis' name: '${_SCANNER_IMAGE}' entrypoint: 'bash' args: - '-c' - | echo "Starting image scan with scanner: ${_SCANNER_IMAGE}" exit_code=0 docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /workspace:/workspace \ -e GCP_PROJECT_ID="${_PROJECT_ID}" \ -e ORGANIZATION_ID="${_ORGANIZATION_ID}" \ -e IMAGE_NAME="${_IMAGE_NAME_TO_SCAN}" \ -e IMAGE_TAG="${_IMAGE_TAG}" \ -e CONNECTOR_ID="${_CONNECTOR_ID}" \ -e TRIGGER_ID="${_TRIGGER_ID}" \ -e IGNORE_ERRORS="${_IGNORE_ERRORS}" \ -e GCP_ACCESS_TOKEN="$(cat /workspace/gcp_token.txt)" \ "${_SCANNER_IMAGE}" || exit_code=$? echo "Docker run finished with exit code: $exit_code" if [ $exit_code -eq 0 ]; then echo "✅ Evaluation succeeded: Conformant image." elif [ $exit_code -eq 1 ]; then echo "❌ Scan failed: Non-conformant image." exit 1 else if [ "${_IGNORE_ERRORS}" = "true" ]; then echo "⚠️ Server/internal error ignored. Continuing." else echo "❌ Server/internal error. Exiting." exit 1 fi fi # Step 4: Configure Docker authentication for Artifact Registry - name: 'gcr.io/cloud-builders/gcloud' id: 'Configure Docker Auth' entrypoint: 'bash' args: - '-c' - | echo "🔐 Configuring Docker authentication for Artifact Registry..." gcloud auth configure-docker us-east1-docker.pkg.dev -q echo "✅ Docker authentication configured." # Step 5: Push image to Artifact Registry - name: 'gcr.io/cloud-builders/docker' id: 'Push Image to Artifact Registry' entrypoint: 'bash' args: - '-c' - | docker tag "${_IMAGE_NAME_TO_SCAN}:${_IMAGE_TAG}" "us-east1-docker.pkg.dev/${_PROJECT_ID}/${_AR_REPOSITORY}/${_IMAGE_NAME_TO_SCAN}:${_IMAGE_TAG}" echo "🚀 Pushing $_FULL_AR_TAG..." docker push "us-east1-docker.pkg.dev/${_PROJECT_ID}/${_AR_REPOSITORY}/${_IMAGE_NAME_TO_SCAN}:${_IMAGE_TAG}" echo "✅ Image pushed successfully." substitutions: _IMAGE_NAME_TO_SCAN: 'checkout-image' _ORGANIZATION_ID: 'orgId' _CONNECTOR_ID: 'connectorId' _SCANNER_IMAGE: 'us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest' _IMAGE_TAG: 'latest' _TRIGGER_ID: 'cloud-build-job' _PROJECT_ID: 'projectId' _AR_REPOSITORY: 'images' _IGNORE_ERRORS: "false" serviceAccount: "projects/projectId/serviceAccounts/id-compute@" options: logging: CLOUD_LOGGING_ONLY
פעולות GitHub (סוד)
התבנית הזו מיועדת לפעולות GitHub שמשתמשות במפתח סודי.
- מוסיפים את המפתח הסודי של חשבון השירות (
GCP_CREDENTIALS). מידע על שדות נוספים זמין במאמר הגדרות משתנים.
# A workflow to BUILD the app image, RUN the scanner, and PUSH to AR if scan passes name: Build, Scan and Push on: workflow_dispatch: inputs: IMAGE_NAME_TO_SCAN: description: 'The tag for your application image to be built (e.g., my-app:latest)' required: true default: 'checkout-image' GCP_PROJECT_ID: description: 'GCP Project ID for authentication' required: true default: 'projectId' AR_REPOSITORY: description: 'Artifact Registry repository name (e.g., app-repo)' required: false default: 'images' ORGANIZATION_ID: description: 'Your GCP Organization ID' required: true default: 'orgId' CONNECTOR_ID: description: 'The ID for your pipeline connector' required: true default: 'connectorId' SCANNER_IMAGE: description: 'The full registry path for your PRE-BUILT scanner tool' required: true default: 'us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest' IMAGE_TAG: description: 'The Docker image version (of the app image)' required: true default: 'latest' IGNORE_SERVER_ERRORS: description: 'Ignore server errors' required: false type: boolean default: false VERBOSITY: description: 'Verbosity flag' required: false default: 'HIGH' jobs: build-and-scan: runs-on: ubuntu-latest steps: # 1. Check out repository (for your app's Dockerfile) - name: Check out repository uses: actions/checkout@v4 # 2. Authenticate to Google Cloud - name: Authenticate to GCP id: auth uses: 'google-github-actions/auth@v2' with: credentials_json: '${{ secrets.GCP_CREDENTIALS }}' # 3. Set up the gcloud CLI - name: Set up Cloud SDK uses: 'google-github-actions/setup-gcloud@v2' with: project_id: ${{ inputs.GCP_PROJECT_ID }} # 4. Configure Docker (needed to pull SCANNER_IMAGE and push app image) - name: Configure Docker run: gcloud auth configure-docker us-central1-docker.pkg.dev --quiet # 5. Build Application Image Locally (IMAGE_NAME_TO_SCAN) - name: Build Application Image Locally uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile push: false # <-- Do not push load: true # <-- Load image into the runner's local daemon # Tag the image with the name the scanner will look for tags: | ${{ inputs.IMAGE_NAME_TO_SCAN }}:${{ inputs.IMAGE_TAG }} # 6. Run Image Scan (Using the SCANNER_IMAGE) - name: 'Run Image Analysis Scan' if: steps.auth.outcome == 'success' run: | echo "📦 Pulling scanner image and running scan..." SCANNER_IMAGE="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.SCANNER_IMAGE || env.SCANNER_IMAGE }}" GCP_PROJECT_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.GCP_PROJECT_ID || env.GCP_PROJECT_ID }}" ORGANIZATION_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ORGANIZATION_ID || env.ORGANIZATION_ID }}" IMAGE_NAME="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IMAGE_NAME_TO_SCAN || env.IMAGE_NAME_TO_SCAN }}" IMAGE_TAG="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IMAGE_TAG || env.IMAGE_TAG }}" CONNECTOR_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.CONNECTOR_ID || env.CONNECTOR_ID }}" VERBOSITY="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.VERBOSITY || env.VERBOSITY }}" IGNORE_ERRORS="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IGNORE_SERVER_ERRORS || (env.IGNORE_SERVER_ERRORS == 'true') }}" exit_code=0 # This 'docker run' pulls the SCANNER_IMAGE from the registry # and passes the name of the locally-built app image (IMAGE_NAME) docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ${{ steps.auth.outputs.credentials_file_path }}:/tmp/scc-key.json \ -e GCLOUD_KEY_PATH=/tmp/scc-key.json \ -e GCP_PROJECT_ID="${GCP_PROJECT_ID}" \ -e ORGANIZATION_ID="${ORGANIZATION_ID}" \ -e IMAGE_NAME="${IMAGE_NAME}" \ -e IMAGE_TAG="${IMAGE_TAG}" \ -e CONNECTOR_ID="${CONNECTOR_ID}" \ -e BUILD_TAG="${{ github.workflow }}" \ -e BUILD_ID="${{ github.run_number }}" \ -e VERBOSITY="${VERBOSITY}" \ "${SCANNER_IMAGE}" \ || exit_code=$? echo "Docker run finished with exit code: $exit_code" # --- Replicate Jenkins Exit Code Logic --- if [ $exit_code -eq 0 ]; then echo "✅ Evaluation succeeded: Conformant image." elif [ $exit_code -eq 1 ]; then echo "❌ Scan failed: Non-conformant image (vulnerabilities found)." exit 1 # Fail the step else if [ "$IGNORE_ERRORS" = "true" ]; then echo "⚠️ Server/internal error occurred (Code: $exit_code), but IGNORE_SERVER_ERRORS=true. Proceeding." else echo "❌ Server/internal error occurred (Code: $exit_code) during evaluation. Set IGNORE_SERVER_ERRORS=true to override." exit 1 # Fail the step fi fi # 8. Push Application Image (ONLY if scan succeeded) # This step only runs if the 'Run Image Analysis Scan' step above exited with 0 - name: Push Application Image to Artifact Registry run: | # Define the local and remote tags LOCAL_IMAGE_NAME="${{ inputs.IMAGE_NAME_TO_SCAN }}:${{ inputs.IMAGE_TAG }}" # This path is based on your 'Configure Docker' step (us-central1) # and the new AR_REPOSITORY input. FULL_AR_TAG="us-central1-docker.pkg.dev/${{ inputs.GCP_PROJECT_ID }}/${{ inputs.AR_REPOSITORY }}/${{ inputs.IMAGE_NAME_TO_SCAN }}:${{ inputs.IMAGE_TAG }}" echo "Tagging local image ${LOCAL_IMAGE_NAME} as ${FULL_AR_TAG}" docker tag "${LOCAL_IMAGE_NAME}" "${FULL_AR_TAG}" echo "Pushing ${FULL_AR_TAG} to Artifact Registry..." docker push "${FULL_AR_TAG}"
GitHub Actions (WIF)
התבנית הזו מיועדת לפעולות GitHub שמשתמשות באיחוד שירותי אימות הזהות של עומסי עבודה.
- מוסיפים את ספק מאגרי זהויות של עומסי עבודה בסוד של GitHub (
GCP_WORKLOAD_IDENTITY_PROVIDER). - מוסיפים את חשבון השירות בסוד של GitHub (
GCP_SERVICE_ACCOUNT). מידע על שדות נוספים זמין במאמר הגדרות משתנים.
# A workflow to BUILD the app image, RUN the scanner, and PUSH to AR if scan passes name: Build, Scan and Push on: push: branches: - main workflow_dispatch: inputs: IMAGE_NAME_TO_SCAN: description: 'The tag for your application image to be built (e.g., my-app:latest)' required: true default: 'checkout-image' GCP_PROJECT_ID: description: 'GCP Project ID for authentication and configuration' required: true default: 'projectId' ORGANIZATION_ID: description: 'Your GCP Organization ID' required: true default: 'orgId' CONNECTOR_ID: description: 'The ID for your pipeline connector' required: true default: 'connectorId' SCANNER_IMAGE: description: 'The Docker image that contains your scanner script' required: true default: 'us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest' IMAGE_TAG: description: 'The Docker image version' required: true default: 'latest' IGNORE_SERVER_ERRORS: description: 'If true, the pipeline continues on server/internal scanner errors.' required: false type: boolean default: false jobs: image-analysis-job: runs-on: ubuntu-latest permissions: contents: 'read' id-token: 'write' env: IMAGE_NAME_TO_SCAN: 'webgoat/webgoat' GCP_PROJECT_ID: 'projectId' ORGANIZATION_ID: 'orgId' CONNECTOR_ID: 'connectorId' SCANNER_IMAGE: 'us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest' IMAGE_TAG: 'imageTag' IGNORE_SERVER_ERRORS: 'false' steps: # Step 1: Authenticate and create credential file - name: 'Authenticate to Google Cloud' id: 'auth' uses: 'google-github-actions/auth@v2' with: workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }} create_credentials_file: true # Step 2: Set up gcloud SDK - name: 'Set up gcloud SDK' uses: 'google-github-actions/setup-gcloud@v2' # Step 3: Configure Docker for registries - name: 'Configure Docker for Artifact Registry' run: | gcloud auth configure-docker us-central1-docker.pkg.dev --quiet # Step 4: Run Image Analysis Scan and Handle Exit Codes - name: 'Run Image Analysis Scan' run: | echo "📦 Running container from scanner image..." # Determine values: Use manual inputs if available (event_name=workflow_dispatch), otherwise use env defaults SCANNER_IMAGE="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.SCANNER_IMAGE || env.SCANNER_IMAGE }}" GCP_PROJECT_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.GCP_PROJECT_ID || env.GCP_PROJECT_ID }}" ORGANIZATION_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ORGANIZATION_ID || env.ORGANIZATION_ID }}" IMAGE_NAME="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IMAGE_NAME_TO_SCAN || env.IMAGE_NAME_TO_SCAN }}" IMAGE_TAG="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IMAGE_TAG || env.IMAGE_TAG }}" CONNECTOR_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.CONNECTOR_ID || env.CONNECTOR_ID }}" IGNORE_ERRORS="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IGNORE_SERVER_ERRORS || (env.IGNORE_SERVER_ERRORS == 'true') }}" # Variable to store exit code exit_code=0 # Run docker and capture exit code using || trick docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ${{ steps.auth.outputs.credentials_file_path }}:/gcp-creds.json \ -e GOOGLE_APPLICATION_CREDENTIALS=/gcp-creds.json \ -e GCP_PROJECT_ID="${GCP_PROJECT_ID}" \ -e ORGANIZATION_ID="${ORGANIZATION_ID}" \ -e IMAGE_NAME="${IMAGE_NAME}" \ -e IMAGE_TAG="${IMAGE_TAG}" \ -e CONNECTOR_ID="${CONNECTOR_ID}" \ -e RUN_ID="${{ github.run_number }}" \ "${SCANNER_IMAGE}" \ || exit_code=$? echo "Docker run finished with exit code: $exit_code" if [ $exit_code -eq 0 ]; then echo "✅ Evaluation succeeded: Conformant image." elif [ $exit_code -eq 1 ]; then echo "❌ Scan failed: Non-conformant image (vulnerabilities found)." exit 1 # Fail the step else if [ "$IGNORE_ERRORS" = "true" ]; then echo "⚠️ Server/internal error occurred (Code: $exit_code), but IGNORE_SERVER_ERRORS=true. Proceeding." # Do nothing, step passes else echo "❌ Server/internal error occurred (Code: $exit_code) during evaluation. Set IGNORE_SERVER_ERRORS=true to override." exit 1 # Fail the step fi fi
Jenkins (סוד)
- הוספת מפתח סודי לחשבון שירות (
GCP_CREDENTIALS). מידע על שדות נוספים זמין במאמר הגדרות משתנים.
pipeline { agent any parameters { string( name: 'IMAGE_NAME_TO_SCAN', defaultValue: 'checkout-image', description: 'The tag for your application image to be built (e.g., my-app:latest)' ) string( name: 'GCP_PROJECT_ID', defaultValue: 'projectId', description: 'GCP Project ID for authentication' ) string( name: 'AR_REPOSITORY', defaultValue: 'images', description: 'Artifact Registry repository name (e.g., app-repo)' ) string( name: 'ORGANIZATION_ID', defaultValue: 'orgId', description: 'Your GCP Organization ID' ) string( name: 'CONNECTOR_ID', defaultValue: 'connectorId', description: 'The ID for your pipeline connector' ) string( name: 'SCANNER_IMAGE', defaultValue: 'us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest', description: 'The full registry path for your PRE-BUILT scanner tool' ) string( name: 'IMAGE_TAG', defaultValue: 'latest', description: 'The Docker image version (of the app image)' ) booleanParam( name: 'IGNORE_SERVER_ERRORS', defaultValue: false, description: 'Ignore server errors' ) string( name: 'VERBOSITY', defaultValue: 'HIGH', description: 'Verbosity flag' ) } stages { // Stage 1: Check out the source code stage('Checkout') { steps { echo "Checking out source code..." checkout scm } } // Stage 2: Build application image stage('Build Application Image') { steps { echo "Building application image: ${params.IMAGE_NAME_TO_SCAN}:${params.IMAGE_TAG}" sh "docker build -t ${params.IMAGE_NAME_TO_SCAN}:${params.IMAGE_TAG} -f ./Dockerfile ." } } // Stage 3: Authenticate to Google Cloud and run scanner stage('Scan Image') { steps { script { withCredentials([file(credentialsId: 'GCP_CREDENTIALS', variable: 'GCP_KEY_FILE')]) { // Authenticate sh "gcloud auth activate-service-account --key-file=\"$GCP_KEY_FILE\"" sh 'gcloud auth list' sh 'gcloud auth configure-docker gcr.io --quiet' sh 'gcloud auth configure-docker us-central1-docker.pkg.dev --quiet' // Run scanner container def exitCode = sh( script: """ echo "📦 Running scanner container from image: ${params.SCANNER_IMAGE}" docker run --rm \\ -v /var/run/docker.sock:/var/run/docker.sock \\ -v "$GCP_KEY_FILE":/tmp/scc-key.json \\ -e GCLOUD_KEY_PATH=/tmp/scc-key.json \\ -e GCP_PROJECT_ID="${params.GCP_PROJECT_ID}" \\ -e ORGANIZATION_ID="${params.ORGANIZATION_ID}" \\ -e IMAGE_NAME="${params.IMAGE_NAME_TO_SCAN}" \\ -e IMAGE_TAG="${params.IMAGE_TAG}" \\ -e CONNECTOR_ID="${params.CONNECTOR_ID}" \\ -e BUILD_TAG="${env.JOB_NAME}" \\ -e BUILD_ID="${env.BUILD_NUMBER}" \\ "${params.SCANNER_IMAGE}" """, returnStatus: true ) if (exitCode == 0) { echo "✅ Evaluation succeeded: Conformant image." } else if (exitCode == 1) { error("❌ Scan failed: Non-conformant image (vulnerabilities found).") } else { if (params.IGNORE_SERVER_ERRORS) { echo "⚠️ Server/internal error occurred, but IGNORE_SERVER_ERRORS=true. Proceeding with pipeline." } else { error("❌ Server/internal error occurred during evaluation. Set IGNORE_SERVER_ERRORS=true to override.") } } } } } } // Stage 4: Push Application Image stage('Push Application Image') { steps { script { def localImage = "${params.IMAGE_NAME_TO_SCAN}:${params.IMAGE_TAG}" def remoteTag = "us-central1-docker.pkg.dev/${params.GCP_PROJECT_ID}/${params.AR_REPOSITORY}/${params.IMAGE_NAME_TO_SCAN}:${params.IMAGE_TAG}" echo "Tagging local image ${localImage} as ${remoteTag}" sh "docker tag ${localImage} ${remoteTag}" echo "Pushing ${remoteTag} to Artifact Registry..." sh "docker push ${remoteTag}" } } } }
הגדרות של משתנים
בקטע הזה מפורטים שדות המשתנים שמשמשים בתבניות לשילוב צינורות.
IMAGE_NAME_TO_SCAN (חובה)
- מציין את התג של תמונת האפליקציה שתיבנה.
GCP_PROJECT_ID (חובה)
- מציינת את Google Cloud מזהה הפרויקט שמשמש לאימות ולתצורה.
AR_REPOSITORY (אופציונלי)
- מציינים את השם של מאגר Artifact Registry שבו הצינור מפרסם את התמונה אם ה-build מצליח.
ORGANIZATION_ID (חובה)
- מזהה הארגון Google Cloud .
CONNECTOR_ID (חובה)
- מציין את מזהה המחבר של צינור עיבוד הנתונים שבו רוצים להשתמש.
SCANNER_IMAGE (חובה)
התמונה של הסורק המובנה מנתחת קוד, מזהה נקודות חולשה על ידי הערכת תמונות בהתאם למדיניות במהלך הבנייה, ומפיקה תוצאת התאמה כדי לקבוע אם צינור ה-CI/CD עובר או נכשל.
פרטי התמונה:
us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest
VERBOSITY (אופציונלי)
- הסורק תומך בדגל
VERBOSITYאופציונלי שקובע את רמת הפירוט שמוצגת בפלט הסריקה. הפלט של הסורק משתנה בהתאם לרמת הפירוט ולתוצאת התאימות (עבר או נכשל). אפשר להגדיר את דגל הפירוט לערך
LOWאוHIGH. אם לא מציינים ערך, ברירת המחדל היאLOW.
דרגת מלל נמוכה (תמציתית)
ArtifactGuard Conformance: Pass
- פרטים על שמות המדיניות.
- מספק רק את הסיכום של מספר ה-CVE לפי חומרה.
ArtifactGuard Conformance: Fail
- פרטים על הסיבה לכישלון.
- רשימה של נקודות החולשה הנפוצות (CVE) הספציפיות שגרמו לכשל.
- מספקת סיכום של מספר ה-CVEs שמסווגים לפי חומרה.
דרגת מלל גבוהה (מפורט)
רשימה מקיפה של כל נקודות החולשה שנמצאו.
ArtifactGuard Conformance: Pass
- רשימה של כל ה-CVE שזוהו במדיניות.
- מספקת סיכום של מספר ה-CVE, בפילוח לפי חומרת הבעיה.
- רשימה מקיפה של כל נקודות החולשה שזוהו.
ArtifactGuard Conformance: Fail
- כולל את הסיבה לכישלון.
- רשימה של נקודות החולשה הנפוצות (CVE) שגורמות לכשל.
- רשימה של כל ה-CVE שזוהו במדיניות.
- מספקת סיכום של מספר ה-CVE, בפילוח לפי חומרת הבעיה.
- רשימה מקיפה של כל נקודות החולשה שזוהו.
IGNORE_SERVER_ERRORS (אופציונלי)
- דגל בוליאני אופציונלי. אם
true, הצינור ממשיך לפעול למרות שגיאות השרת. ברירת המחדל היאfalse.
התחלת הערכה
במהלך תהליך build, שיטה שמבוססת על Docker מעריכה את התמונה בהתאם למדיניות שהוגדרה מראש. הלוגיקה של סריקת נקודות החולשה נמצאת בתוך
us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest
התמונה.
כדי להפעיל סריקת פגיעויות בצינור ה-CI/CD, מריצים את הפקודה הבאה:
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ${{ steps.auth.outputs.credentials_file_path }}:/gcp-creds.json \
-e GOOGLE_APPLICATION_CREDENTIALS=/gcp-creds.json \
-e GCP_PROJECT_ID="${GCP_PROJECT_ID}" \
-e ORGANIZATION_ID="${ORGANIZATION_ID}" \
-e IMAGE_NAME="${IMAGE_NAME}" \
-e IMAGE_TAG="${IMAGE_TAG}" \
-e CONNECTOR_ID="${CONNECTOR_ID}" \
-e RUN_ID="${{ github.run_number }}" \
"${SCANNER_IMAGE}" \
|| exit_code=$?
השילוב של CI/CD מעביר את קודי היציאה של קונטיינר Docker לזמן הריצה של Jenkins או GitHub Actions, שקובע את מצב ההצלחה או הכשל של צינור עיבוד הנתונים.
פתרון בעיות
בקטע הזה מפורטות שגיאות נפוצות ומוסבר איך לפתור אותן.
כשלים ב-CreateConnector
| שדה | חובה/אופציונלי | מגבלות |
|---|---|---|
name |
חובה | פורמט: הערך צריך להתאים לביטוי הרגולרי
[a-zA-Z0-9\\-\\s_]+$ הערך צריך להתאים לאחד או יותר מהדברים הבאים:
אורך מקסימלי: 64 תווים. |
pipeline_type |
חובה | צריך להזין אחד מהערכים הבאים של enum:
|
description |
אופציונלי | האורך המקסימלי הוא 256 תווים. |
display_name |
אופציונלי | האורך המקסימלי הוא 256 תווים. |
שגיאות אחרות
בטבלה הבאה מפורטות כמה שגיאות נפוצות ודרכים לפתור אותן.
| הודעת השגיאה | הסיבה | פעולה/פתרון |
|---|---|---|
ההרשאה artifactscanguard.connectors.create
נדחתה במשאב |
למשתמש או לחשבון השירות חסרה הרשאת IAM במשאב (פרויקט, תיקייה או ארגון) artifactscanguard.connectors.create
. |
נותנים למשתמש שקורא ל-API תפקיד IAM שכולל את ההרשאה artifactscanguard.connectors.create. |
status.ErrFailedPrecondition |
יכול להיות שתהליך ההצטרפות עדיין מתבצע גם אם Google Cloud המסוף מציג את השירות כמופעל. | דיווח על בעיה לצוות התמיכה. |
status.ErrInvalidArgument |
כשלים באימות השדות | מוודאים שהבקשה CreateConnector עומדת במגבלות שצוינו. |