In CI/CD einbinden

CodeMender kann jede Pull-Anfrage in Ihrer CI/CD-Pipeline (Continuous Integration/Continuous Delivery) scannen. Die Prüfung schlägt fehl, wenn CodeMender im Code, der durch den Pull-Request geändert wird, eine Sicherheitslücke mit dem Schweregrad CRITICAL oder HIGH findet. Ergebnisse im Code, die durch die Pull-Anfrage nicht geändert wurden, werden im Bericht angezeigt, führen aber nicht dazu, dass die Prüfung fehlschlägt.

Dieses Dokument enthält Anleitungen für folgende Aufgaben:

  • Pull-Anfragen mit GitHub Actions scannen und von CodeMender eine Pull-Anfrage mit Korrekturen öffnen lassen.
  • Pull-Anfragen mit Cloud Build scannen.
  • Scannen Sie Ihre Änderungen vor jedem Commit mit einem Git-Pre-Commit-Hook.

So funktionieren Pull-Anfrage-Scans

Um eine Pull-Anfrage zu scannen, führen Sie cm find mit dem Flag --diff und dem Basis-Branch der Pull-Anfrage aus:

cm find . --diff=origin/main

Als Reaktion auf diesen Befehl führt CodeMender Folgendes aus:

  1. Vergleicht den Pull-Request-Branch mit dem Basis-Branch und scannt die geänderten Quelldateien sowie die Dateien, die direkt von ihnen abhängen, z. B. Aufrufer und Importeure.
  2. Unterscheidet neue Sicherheitslücken, die durch die Pull-Anfrage eingeführt oder offengelegt werden, von bereits vorhandenen Ergebnissen, die mit [LEGACY / UNTOUCHED] gekennzeichnet sind. Ihr CI-Check blockiert nur bei Sicherheitslücken, die durch den Pull-Request verursacht werden.
  3. Wird mit dem Status 1 beendet, wenn ein durch die Pull-Anfrage verursachter Befund mit einem Schweregrad in --fail-on übereinstimmt. Der Standardwert ist CRITICAL,HIGH.

Weitere Informationen dazu, wie --diff im Vergleich zu anderen Scanmodi abschneidet, finden Sie unter CodeMender-Suchmodi.

Hinweis

CodeMender ist für eine begrenzte Anzahl von Kunden im Rahmen der öffentlichen Vorschau verfügbar. Wenden Sie sich an Ihr Vertriebsteam, um Zugriff zu erhalten.

  1. Melden Sie sich in Ihrem Google Cloud -Konto an. Wenn Sie mit Google Cloudnoch nicht vertraut sind, erstellen Sie einfach ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud 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 the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

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

  4. Verify that billing is enabled for your Google Cloud project.

  5. 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.enable permission. 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.

    Enable the APIs

  6. Install the Google Cloud CLI.

  7. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  8. To initialize the gcloud CLI, run the following command:

    gcloud init
  9. In the Google Cloud console, on the project selector page, select or create a Google Cloud 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 the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

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

  11. Verify that billing is enabled for your Google Cloud project.

  12. 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.enable permission. 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.

    Enable the APIs

  13. Install the Google Cloud CLI.

  14. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  15. To initialize the gcloud CLI, run the following command:

    gcloud init

Ihre CodeMender CLI-Version muss Pull-Anfrage-Scans unterstützen. Die Pipelines in diesem Dokument laden bei jeder Ausführung den neuesten stabilen Release herunter. Wenn Sie eine lokale Installation prüfen möchten, führen Sie cm find --help aus und suchen Sie nach dem Flag --diff. Führen Sie cm update aus, um die CLI zu aktualisieren. Weitere Informationen finden Sie unter CLI installieren und konfigurieren.

Erforderliche Rollen

Bitten Sie Ihren Administrator, Ihnen die folgenden IAM-Rollen für das Projekt zuzuweisen, damit Sie die nötigen Berechtigungen für die Einrichtung von CI/CD-Integrationen für CodeMender haben:

Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff auf Projekte, Ordner und Organisationen verwalten.

Sie können die erforderlichen Berechtigungen auch über benutzerdefinierte Rollen oder andere vordefinierte Rollen erhalten.

Damit das CI/CD-Dienstkonto die erforderlichen Berechtigungen zum Ausführen von CodeMender in einer CI/CD-Pipeline hat, bitten Sie Ihren Administrator, dem CI/CD-Dienstkonto die folgenden IAM-Rollen zu gewähren:

  • Agent Platform User (roles/aiplatform.user) für Ihr Projekt
  • Cloud Build-Build-Logs schreiben: Log-Autor (roles/logging.logWriter) für Ihr Projekt
  • SARIF-Berichte in einem Cloud Storage-Bucket speichern: Storage Object User (roles/storage.objectUser) für den Bucket

Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff auf Projekte, Ordner und Organisationen verwalten.

Ihr Administrator kann dem CI/CD-Dienstkonto möglicherweise auch die erforderlichen Berechtigungen über benutzerdefinierte Rollen oder andere vordefinierte Rollen erteilen.

Sicherheitsaspekte

Wenn Sie CodeMender in einem GitHub Actions-Workflow, einem Cloud Build-Trigger oder einem Git-Pre-Commit-Hook ausführen, wird CodeMender ohne Bestätigung ausgeführt. Beachten Sie vor dem Einrichten dieser Integrationen Folgendes:

  • Bestätigungsaufforderungen: Das Flag --yes deaktiviert die Aufforderungen, in denen Sie die Befehle des Agents und das Schreiben von Dateien bestätigen müssen. Mit dem Flag --bypass-warning wird die Warnung übersprungen, dass der Agent Dateien ändern und Befehle auf Ihrem System ausführen kann. Bevor Sie diese Flags verwenden, lesen Sie die Vorschau-Nutzungsbedingungen am Anfang dieses Dokuments, einschließlich der Bedingungen zum Deaktivieren der Bestätigung durch den Menschen.
  • Sandbox: Die Pipelines deaktivieren die CodeMender-Sandbox mit --sandbox=false. Befehle, die der Agent ausführt, z. B. Builds und Tests, wenn er ein Problem behebt, haben denselben Zugriff wie der Job, einschließlich seinerGoogle Cloud -Anmeldedaten und des Netzwerkzugriffs. Für die Linux-Sandbox werden Nutzer-Namespaces verwendet, die von einigen CI-Umgebungen, z. B. nicht privilegierten Containern, nicht unterstützt werden. Deaktivieren Sie die Sandbox nur in isolierten, temporären Umgebungen. Wenn Ihre CI-Umgebung die Sandbox unterstützt, entfernen Sie --sandbox=false.
  • Runner: Führen Sie den GitHub Actions-Workflow auf von GitHub gehosteten Runnern wie ubuntu-24.04 aus. Jeder Job wird auf einer neuen virtuellen Maschine ausgeführt. Verwenden Sie keine selbstgehosteten Runner, die zwischen Jobs wiederverwendet werden.
  • Nicht vertrauenswürdiger Code: Code in einer Pull-Anfrage kann Text enthalten, mit dem versucht wird, den Agent zu manipulieren. Der GitHub Actions-Workflow scannt nur Pull-Anfragen von Branches im selben Repository, die nur von Nutzern mit Schreibzugriff erstellt werden können. Verwenden Sie für Cloud Build die Kommentarsteuerung, damit ein Inhaber oder Mitbearbeiter Builds für Pull-Anfragen von anderen Mitwirkenden genehmigen muss.
  • Zugriff: Weisen Sie jedem Dienstkonto nur die erforderlichen IAM-Rollen für die zugehörige Pipeline zu.

Pull-Anfragen mit GitHub Actions scannen

Der Workflow in diesem Abschnitt scannt jede Pull-Anfrage in einem Repository auf GitHub.com. Wenn CodeMender eine Sicherheitslücke mit dem Schweregrad CRITICAL oder HIGH in den Änderungen der Pull-Anfrage findet, führt der Workflow die folgenden Schritte aus:

  • Die CodeMender-Prüfung schlägt fehl.
  • Führt cm fix für jedes Ergebnis aus und öffnet eine Pull-Anfrage mit den Korrekturen im Branch der Pull-Anfrage.

Der Workflow lädt die Ergebnisse auch in GitHub Code Scanning hoch.

Identitätsföderation von Arbeitslasten einrichten

Der Workflow authentifiziert sich bei Google Cloud mit Workload Identity-Föderation, sodass Sie keinen Dienstkontoschlüssel in GitHub speichern müssen. Führen Sie die folgenden Befehle mit der Google Cloud CLI aus:

  1. Legen Sie Shell-Variablen für Ihr Projekt und Ihr Repository fest:

    PROJECT_ID="PROJECT_ID"
    GITHUB_ORG="GITHUB_ORG"
    REPO="GITHUB_ORG/REPOSITORY"
    

    Ersetzen Sie Folgendes:

    • PROJECT_ID: Projekt-ID in Google Cloud .
    • GITHUB_ORG: Ihr GitHub-Organisationsname oder Ihr GitHub-Nutzername für ein Repository in einem persönlichen Konto.
    • REPOSITORY: der Name Ihres GitHub-Repositorys.
  2. Aktivieren Sie die APIs, die von der Identitätsföderation von Arbeitslasten verwendet werden:

    gcloud services enable iam.googleapis.com \
        cloudresourcemanager.googleapis.com iamcredentials.googleapis.com \
        sts.googleapis.com --project="${PROJECT_ID}"
    
  3. Erstellen Sie ein Dienstkonto für den Workflow und weisen Sie ihm die IAM-Rolle „Agent Platform User“ (roles/aiplatform.user) zu:

    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}.iam.gserviceaccount.com" \
        --role="roles/aiplatform.user"
    
  4. Erstellen Sie einen Workload Identity-Pool. Wenn Sie bereits einen Pool für GitHub Actions haben, überspringen Sie diesen Schritt und verwenden Sie die ID Ihres Pools anstelle von github in den folgenden Schritten.

    gcloud iam workload-identity-pools create github \
        --project="${PROJECT_ID}" \
        --location="global" \
        --display-name="GitHub Actions"
    
  5. Erstellen Sie einen Anbieter für GitHub im Pool. Für das Attribut „condition“ werden nur Tokens aus Repositories akzeptiert, die GITHUB_ORG gehören.

    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"
    
  6. Workflows in Ihrem Repository das Dienstkonto verwenden lassen:

    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}.iam.gserviceaccount.com" \
        --project="${PROJECT_ID}" \
        --role="roles/iam.workloadIdentityUser" \
        --member="principalSet://iam.googleapis.com/${POOL_ID}/attribute.repository/${REPO}"
    
  7. Rufen Sie den vollständigen Namen des Anbieters ab. Sie benötigen sie im nächsten Abschnitt.

    gcloud iam workload-identity-pools providers describe codemender \
        --project="${PROJECT_ID}" \
        --location="global" \
        --workload-identity-pool="github" \
        --format="value(name)"
    

    Die Ausgabe sieht etwa so aus:

    projects/123456789/locations/global/workloadIdentityPools/github/providers/codemender
    

Es kann bis zu 5 Minuten dauern, bis Änderungen an der Workload Identity-Föderation und IAM wirksam werden. Weitere Informationen finden Sie unter Workload Identity-Föderation mit Bereitstellungspipelines konfigurieren.

Repository-Secrets hinzufügen

Rufen Sie in Ihrem Repository Einstellungen > Secrets und Variablen > Actions auf und fügen Sie die folgenden Repository-Secrets hinzu:

Secret Wert
GCP_PROJECT_ID Ihre Projekt-ID.
GCP_WIF_PROVIDER Der vollständige Name des Anbieters aus dem vorherigen Abschnitt.
GCP_WIF_SERVICE_ACCOUNT codemender-ci@PROJECT_ID.iam.gserviceaccount.com, wobei PROJECT_ID Ihre Projekt-ID ist.

Weitere Informationen finden Sie unter Secrets in GitHub Actions verwenden.

Repository-Einstellungen konfigurieren

  1. Damit der Autofix-Job Pull-Requests öffnen kann, gehen Sie zu Einstellungen > Aktionen > Allgemein. Wählen Sie unter Workflow permissions (Workflowberechtigungen) die Option Allow GitHub Actions to create and approve pull requests (GitHub Actions das Erstellen und Genehmigen von Pull Requests erlauben) aus und klicken Sie dann auf Save (Speichern). Ein Repository in einer Organisation übernimmt diese Einstellung von der Organisation. Wenn Sie die Rolle nicht ändern können, wenden Sie sich an einen Organisationsinhaber. Wenn Sie die automatische Korrektur nicht verwenden, überspringen Sie diesen Schritt. Weitere Informationen finden Sie unter GitHub Actions-Einstellungen für ein Repository verwalten.
  2. Prüfen Sie, ob die GitHub-Codeüberprüfung für das Repository verfügbar ist. Für private und interne Repositories ist für die Codeüberprüfung GitHub Code Security erforderlich. Wenn die Code-Analyse nicht verfügbar ist, löschen Sie den Schritt Ergebnisse in die Code-Analyse hochladen und die Berechtigungen security-events und actions aus dem Scan-Job. Andernfalls schlägt der Upload fehl und damit auch der Scanvorgang. Weitere Informationen finden Sie unter SARIF-Datei auf GitHub hochladen.

Workflow hinzufügen

Übernehmen Sie den folgenden Workflow für Ihr Repository als .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 }}`.

Workflowdetails:

Das folgende Diagramm zeigt, wie die Pull-Anfrage-Scan- und Autofix-Jobs interagieren:

Eine Pull-Anfrage wird gescannt. Wenn es keine blockierenden Ergebnisse gibt, wird die Prüfung bestanden. Andernfalls schlägt die Prüfung fehl, CodeMender öffnet eine Pull-Anfrage für die Korrektur und beim Zusammenführen der Korrekturen wird die Pull-Anfrage noch einmal gescannt.

Der Job CodeMender-Scan führt folgende Aktionen aus:

  1. Checkt die Pull-Anfrage mit ihrem vollständigen Verlauf aus. Bei Pull-Anfragen checkt GitHub einen Merge-Commit des Pull-Anfragezweigs in den Basiszweig aus.
  2. Authentifiziert sich bei Google Cloud und lädt das aktuelle stabile Release der CodeMender-Befehlszeile herunter.
  3. Führt cm find --diff für den Basis-Branch aus. Der Job schlägt fehl, wenn CodeMender in den Änderungen des Pull-Requests eine Sicherheitslücke mit einem Schweregrad findet, der in FAIL_ON aufgeführt ist.
  4. Der Bericht wird in GitHub-Code-Scanning hochgeladen, auch wenn der Scan im Job fehlschlägt. Der Bericht enthält Ergebnisse mit dem Label [LEGACY / UNTOUCHED]. Beim Code-Scanning wird auch ein Ergebnis in den Prüfungen des Pull-Requests angezeigt, wenn alle Zeilen des Ergebnisses im Diff des Pull-Requests enthalten sind.
  5. Speichert die Ergebnisse, die dazu geführt haben, dass der Job für den Autofix-Job fehlgeschlagen ist.

Der Scanjob wird nicht für Pull Requests aus Forks oder von Dependabot ausgeführt, da Workflows für diese Pull Requests die Geheimnisse des Repositorys nicht lesen können. GitHub meldet einen übersprungenen Job als erfolgreich. Die Prüfung blockiert diese Pull-Anfragen also nicht, auch wenn Sie sie als erforderliche Prüfung festlegen. Sehen Sie sich diese Pull-Requests selbst an oder scannen Sie sie lokal mit cm find --diff.

Der Job CodeMender-Autofix wird ausgeführt, wenn im Scanjob Ergebnisse gespeichert werden. Dabei wird Folgendes ausgeführt:

  1. Checkt den Pull-Anfrage-Branch aus.
  2. Führt cm fix für jedes Ergebnis aus und committet jede Korrektur separat. Wenn CodeMender ein Ergebnis nicht korrigiert, wird im Job eine Warnung protokolliert. Beim Job werden nur Änderungen an Dateien übernommen, die sich bereits im Repository befinden. Alle Dateien, die vom Fix-Agent erstellt werden, z. B. Testergebnisse, werden verworfen.
  3. Erstellt eine Pull-Anfrage vom Branch codemender/fix-pr-NUMBER in den Pull-Anfrage-Branch, wobei NUMBER die Nummer der Pull-Anfrage ist. Wenn die Pull-Anfrage für die Korrektur bereits vorhanden ist, wird sie durch den Job aktualisiert. Wenn CodeMender keine Probleme behebt oder der Job das Zeitlimit von 60 Minuten erreicht, wird kein Pull-Request geöffnet.

Korrekturen prüfen und zusammenführen

GitHub führt Workflows für Pull-Anfragen, die von einem Workflow mit dem GITHUB_TOKEN erstellt werden, nicht automatisch aus. Um die Pull-Anfrage für den Fix zu scannen, klickt ein Nutzer mit Schreibzugriff auf das Repository in der Pull-Anfrage für den Fix auf Workflows zur Ausführung genehmigen.

Wenn Sie die Pull-Anfrage für den Fix zusammenführen, ändert sich der Pull-Anfrage-Branch und der Workflow scannt die ursprüngliche Pull-Anfrage noch einmal.

Workflow anpassen

Sie können den Workflow auf folgende Weise anpassen:

  • Wenn Sie die Schweregrade ändern möchten, bei denen die Prüfung fehlschlägt, legen Sie im Schritt Pull-Request scannen FAIL_ON auf eine durch Kommas getrennte Liste von Schweregraden ohne Leerzeichen fest, z. B. CRITICAL,HIGH,MEDIUM. Gültige Werte sind CRITICAL, HIGH, MEDIUM und LOW.
  • Wenn Sie Ergebnisse melden möchten, ohne dass die Prüfung fehlschlägt, legen Sie FAIL_ON: "" fest. Im Workflow werden weiterhin Ergebnisse in den Code-Scan hochgeladen, der Autofix-Job wird jedoch nicht ausgeführt.
  • Wenn Sie Pull-Requests nur in einigen Branches scannen möchten, fügen Sie dem pull_request-Trigger einen branches-Filter hinzu. Im Workflow werden dann keine Pull-Anfragen für Korrekturen gescannt, da ihre Basis ein Pull-Request-Branch ist:

    on:
      pull_request:
        branches: [main]
    
  • Wenn Sie die automatische Korrektur deaktivieren möchten, löschen Sie den Job autofix und den Schritt Ergebnisse für die automatische Korrektur speichern.

Pull-Anfragen mit Cloud Build scannen

Bei diesem Build wird jede Pull-Anfrage in einem GitHub-Repository gescannt, das mit Cloud Build verbunden ist. Der Build und der GitHub-Check schlagen fehl, wenn CodeMender eine Sicherheitslücke mit dem Schweregrad CRITICAL oder HIGH in den Änderungen des Pull-Requests findet. Der Build behebt keine Probleme.

Führen Sie zuerst folgende Schritte aus:

  1. Verbinden Sie Ihr Repository als Repository der zweiten Generation mit Cloud Build. Weitere Informationen finden Sie unter Verbindung zu einem GitHub-Repository herstellen.
  2. Aktivieren Sie die Cloud Build API und die IAM API in dem Projekt, das Zugriff auf CodeMender hat. Der Build verwendet CodeMender im Projekt, in dem der Build ausgeführt wird.

    PROJECT_ID="PROJECT_ID"
    gcloud services enable cloudbuild.googleapis.com iam.googleapis.com \
        --project="${PROJECT_ID}"
    

    Ersetzen Sie PROJECT_ID durch Ihre Google CloudProjekt-ID.

Dienstkonto erstellen

Erstellen Sie ein Dienstkonto für den Build. Weisen Sie ihm die IAM-Rolle „Agent Platform User“ (roles/aiplatform.user) zu, damit er CodeMender verwenden kann, und die Rolle „Logs Writer“ (roles/logging.logWriter), damit er Build-Logs schreiben kann:

SA="codemender-build@${PROJECT_ID}.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"

Wenn Sie SARIF-Berichte in einem Cloud Storage-Bucket speichern möchten, gewähren Sie dem Dienstkonto auch Zugriff auf den Bucket:

BUCKET="BUCKET"

gcloud storage buckets add-iam-policy-binding "gs://${BUCKET}" \
    --member="serviceAccount:${SA}" \
    --role="roles/storage.objectUser"

Ersetzen Sie BUCKET durch den Namen Ihres Cloud Storage-Buckets.

Build-Konfiguration hinzufügen

Übertragen Sie die folgende Build-Konfiguration als cloudbuild.yaml in das Stammverzeichnis Ihres Repositorys:

# 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

Trigger erstellen

Erstellen Sie einen Trigger, der den Build für jede Pull-Anfrage in main ausführt:

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

Ersetzen Sie Folgendes:

  • REGION: Die Region Ihrer Cloud Build-Repository-Verbindung.
  • CONNECTION: der Name Ihrer Cloud Build-Repository-Verbindung.
  • REPOSITORY: Der Name des verbundenen Repositorys in Cloud Build.

Beachten Sie die folgenden Optionen:

  • --pull-request-pattern ist ein regulärer Ausdruck für den Basis-Branch der Pull-Anfrage. Verwenden Sie ^ und $, um den gesamten Zweignamen abzugleichen.
  • Mit --comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY werden Builds automatisch für Pull-Anfragen von Repository-Inhabern und Mitwirkenden ausgeführt. Bei Pull-Anfragen von anderen Mitwirkenden wird der Build ausgeführt, nachdem ein Inhaber oder Mitbearbeiter /gcbrun zum Pull-Anfrage kommentiert hat.
  • Wenn Sie SARIF-Berichte in einem Bucket speichern möchten, fügen Sie --substitutions=_REPORT_BUCKET="${BUCKET}" hinzu.

Sie können den Trigger auch in der Google Cloud Console erstellen. Weitere Informationen finden Sie unter Repositories aus GitHub erstellen.

Wenn Sie Build-Logs in GitHub anzeigen möchten, fügen Sie beim Erstellen des Triggers --include-logs-with-status hinzu und weisen Sie dem Dienstkonto die Rolle „Logs Viewer“ (roles/logging.viewer) zu. Jeder, der die Prüfung in GitHub aufrufen kann, kann dann die Build-Logs einschließlich der Ergebnisse lesen.

So funktioniert der Build

Der Build umfasst drei Schritte:

  1. Mit install-codemender wird der neueste stabile Release der CodeMender-Befehlszeile heruntergeladen.
  2. Mit fetch-history wird der Basiszweig und der Verlauf abgerufen, den CodeMender benötigt. Cloud Build checkt nur den Commit aus, mit dem der Build gestartet wurde. Der Schritt ruft Daten aus dem origin-Remote-Repository ab. Wenn origin nicht konfiguriert ist, werden die Daten ohne Anmeldedaten von GitHub abgerufen. Das funktioniert nur für öffentliche Repositories. In diesem Fall sind für ein privates Repository Anmeldedaten wie ein SSH-Schlüssel erforderlich. Weitere Informationen finden Sie unter Von einem Build über SSH-Schlüssel auf GitHub zugreifen.
  3. scan führt cm find --diff für den Basis-Branch aus. Nach Abschluss des Scans werden alle Ergebnisse im Build-Log ausgegeben. Wenn Sie _REPORT_BUCKET festlegen, wird der SARIF-Bericht auch in gs://BUCKET/codemender/BUILD_ID.sarif kopiert.

Wenn Sie die Schweregrade ändern möchten, die dazu führen, dass der Build fehlschlägt, bearbeiten Sie --fail-on im Schritt scan. Wenn Sie den Build ohne Pull-Anfrage-Trigger ausführen, schlägt er mit der Meldung Run this build from a pull request trigger. fehl.

Vor jedem Commit scannen

Ein Git-Pre-Commit-Hook kann Ihre bereitgestellten Änderungen scannen und den Commit blockieren, wenn CodeMender eine Sicherheitslücke mit dem Schweregrad CRITICAL oder HIGH findet. Entwickler können den Hook überspringen. Verwenden Sie ihn daher zusätzlich zum Scannen in der CI, nicht anstelle des Scannens.

Jeder Entwickler, der den Hook verwendet, benötigt Folgendes:

  • Die CodeMender-CLI ist wie unter CLI installieren und konfigurieren beschrieben installiert und eingerichtet, einschließlich gcloud auth application-default login und cm init. Der Hook benötigt cm auf dem PATH.
  • Die Rolle „Agent Platform User“ (roles/aiplatform.user) in einem Projekt mit Zugriff auf CodeMender. CodeMender verwendet das Projekt in der Umgebungsvariable GOOGLE_CLOUD_PROJECT. Wenn diese Variable nicht festgelegt ist, verwendet CodeMender das Projekt aus Ihren Standardanmeldedaten für Anwendungen oder Ihr gcloud CLI-Standardprojekt.

Um den Hook hinzuzufügen, speichern Sie das folgende Script als .git/hooks/pre-commit in Ihrem Repository:

#!/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

Machen Sie das Skript ausführbar und fügen Sie dann .cm_project zu Ihrer .gitignore-Datei hinzu, damit die Datei, die CodeMender zum Verfolgen des Repositorys erstellt, nicht committet wird:

chmod +x .git/hooks/pre-commit
echo .cm_project >> .gitignore

Wenn Sie git commit ausführen, werden die Dateien mit bereitgestellten Änderungen gescannt. Der Scan kann einige Minuten dauern. Mit dem Hook wird die CodeMender-Sandbox nicht deaktiviert.

Wenn Sie den Commit ohne den Scan ausführen möchten, führen Sie git commit --no-verify aus.

Scan-Flags

Die folgenden cm find-Flags steuern Pull-Anfrage-Scans. Führen Sie cm find --help aus, um alle Flags aufzurufen:

Flag Standardeinstellung Beschreibung
--diff[=REF] Aus Sucht nach Änderungen im Vergleich zu REF, z. B. origin/main. Ohne REF werden nicht übertragene Änderungen an verfolgten Dateien gescannt (im Vergleich zu HEAD). Kann nicht mit --deep verwendet werden.
--staged Aus Mit --diff werden nur bereitgestellte Änderungen gescannt.
--diff-depth DEPTH 1 Durchlauf-Tiefe für die Wirkungsanalyse (1 bis 3, Standard: 1 Hop).
--diff-workers COUNT 4 Die Anzahl der Dateien, die gleichzeitig gescannt werden sollen. Der Wert kann zwischen 1 und 16 liegen.
--diff-max-neighbors COUNT 10 Die maximale Anzahl der zu scannenden abhängigen Dateien.
--fail-on SEVERITIES CRITICAL,HIGH Mit --diff werden die Schweregrade festgelegt, die dazu führen, dass cm find mit dem Status 1 beendet wird. Bei einem leeren Wert haben Ergebnisse keine Auswirkungen auf den Exit-Status.
--fail-on-truncation Aus Mit --diff wird mit dem Status 1 beendet, wenn CodeMender mehr abhängige Dateien findet, als --diff-max-neighbors zulässt.
--format FORMAT table Das Berichtsformat: table, json oder sarif.
--output FILE Standardausgabe Die Datei, in die der Bericht geschrieben werden soll.

Fehlerbehebung

In diesem Abschnitt wird beschrieben, wie Sie häufige Probleme beheben, die beim Ausführen von CodeMender in CI/CD-Pipelines auftreten.

Berechtigung verweigert

Im Log wird eine Zeile wie die folgende angezeigt:

[1/1] ❌ src/app.py: start session failed: StartSession failed with HTTP 403 Forbidden.

Die Nachricht kann auch Permission 'aiplatform.interactions.create' denied enthalten. Prüfen Sie Folgendes:

  • Das Projekt hat Zugriff auf CodeMender.
  • Das Dienstkonto oder der Nutzer hat die Rolle „Agent Platform User“ (roles/aiplatform.user) im Projekt.
  • Die Agent Platform API ist im Projekt aktiviert.
  • CodeMender verwendet das richtige Projekt. Prüfen Sie in GitHub Actions das Secret GCP_PROJECT_ID. Cloud Build verwendet das Projekt, in dem der Build ausgeführt wird. Prüfen Sie lokal die Umgebungsvariable GOOGLE_CLOUD_PROJECT oder Ihr Standardprojekt, wenn die Variable nicht festgelegt ist.

Ressourceneinrichtung läuft

Wenn im Log Resource setup has just started. Please try again shortly. oder Resource setup is in progress. Please try again shortly. angezeigt wird, richtet CodeMender Ressourcen für Ihr Projekt ein. Das dauert in der Regel einige Minuten. Führen Sie den Job später noch einmal aus.

Unbekanntes Flag: --diff

Wenn cm find mit Error: unknown flag: --diff fehlschlägt, unterstützt Ihre CLI-Version keine Pull-Anfrage-Scans. Führen Sie cm update aus oder laden Sie das aktuelle Release herunter.

Basis-Branch nicht gefunden

Wenn cm find mit einem Fehler wie dem folgenden fehlschlägt, ist der Basis-Branch nicht im Checkout enthalten:

Error: retrieving VCS diff: git diff failed: exit status 128: fatal: ambiguous argument 'origin/main': unknown revision or path not in the working tree.

Rufen Sie den Basis-Branch und seinen Verlauf ab, bevor Sie cm find ausführen. Legen Sie in GitHub Actions fetch-depth: 0 in actions/checkout fest.

Dateien nicht gescannt

Eine Zeile mit ❌, z. B. [1/1] ❌ src/app.py: start session failed, bedeutet, dass CodeMender diese Datei nicht scannen konnte. Prüfen Sie den Fehler in der Zeile und führen Sie den Job dann noch einmal aus.

Keine Pull-Anfrage für Fehlerbehebung

Wenn durch den Workflow kein Pull-Anfrage für die Korrektur geöffnet wird, prüfen Sie Folgendes:

  • Wenn der Autofix-Job beim Erstellen der Pull-Anfrage fehlschlägt, aktivieren Sie Allow GitHub Actions to create and approve pull requests (GitHub Actions das Erstellen und Genehmigen von Pull-Anfragen erlauben). Weitere Informationen finden Sie unter Repository-Einstellungen konfigurieren.
  • Wenn der Autofix-Job erfolgreich ist, ohne dass ein Pull-Anfrage geöffnet wird, hat CodeMender keine Ergebnisse behoben. Im Job-Log wird für jedes Ergebnis, das CodeMender nicht behoben hat, eine Warnung angezeigt.

Fehler beim Hochladen des Code-Scans

Wenn der Uploadschritt mit GitHub Code Security or GitHub Advanced Security must be enabled for this repository to use code scanning fehlschlägt, aktivieren Sie GitHub Code Security für das Repository oder löschen Sie den Uploadschritt. Weitere Informationen finden Sie unter Repository-Einstellungen konfigurieren.

Warnung nicht bestätigt

Wenn cm mit warning not acknowledged. Please run interactively once to acknowledge or pass --bypass-warning fehlschlägt, benötigt CodeMender eine Bestätigung, die in einer nicht interaktiven Umgebung nicht angefordert werden kann. Fügen Sie dem Befehl --bypass-warning hinzu. Lesen Sie dazu die Vorabversionsbedingungen oben auf dieser Seite.

Wenn Sie weitere Hilfe benötigen, wenden Sie sich an Ihr Vertriebsteam.