CodeMender puede analizar cada solicitud de extracción en tu canalización de integración continua y entrega continua (CI/CD). La verificación falla cuando CodeMender encuentra una vulnerabilidad con gravedad CRITICAL o HIGH en el código que cambia la solicitud de extracción. Los hallazgos en el código que no se modificaron en la solicitud de extracción aparecen en el informe, pero no fallan en la verificación.
Este documento te muestra cómo hacer lo siguiente:
- Analiza las solicitudes de extracción con Acciones de GitHub y haz que CodeMender abra una solicitud de extracción con correcciones.
- Analiza solicitudes de extracción con Cloud Build.
- Analiza tus cambios antes de cada confirmación con un hook de confirmación previa de Git.
Cómo funcionan los análisis de solicitud de extracción
Para analizar una solicitud de extracción, ejecuta cm find con la marca --diff y la rama base de la solicitud de extracción:
cm find . --diff=origin/main
En respuesta a este comando, CodeMender hace lo siguiente:
- Compara la rama de la solicitud de extracción con la rama base y analiza los archivos fuente modificados, además de los archivos que dependen directamente de ellos, como los llamadores y los importadores.
- Distingue las vulnerabilidades nuevas que introduce o expone la solicitud de extracción de los hallazgos preexistentes, que se etiquetan como
[LEGACY / UNTOUCHED]. La verificación de CI solo bloquea las vulnerabilidades causadas por la solicitud de extracción. - Sale con el estado 1 cuando un hallazgo causado por la solicitud de extracción coincide con una gravedad en
--fail-on. El valor predeterminado esCRITICAL,HIGH.
Para obtener más información sobre cómo se compara --diff con otros modos de análisis, consulta Modos de búsqueda de CodeMender.
Antes de comenzar
CodeMender está disponible para un conjunto limitado de clientes en la versión preliminar pública. Comunícate con tu equipo de ventas para obtener acceso.
- Accede a tu cuenta de Google Cloud . Si es la primera vez que usas Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
-
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 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 Google Cloud 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.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init -
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 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 Google Cloud 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.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init
Asegúrate de que la versión de la CLI de CodeMender admita los análisis de solicitud de extracción. Las canalizaciones de este documento descargan la versión estable más reciente cada vez que se ejecutan. Para verificar una instalación local, ejecuta cm find --help y busca la marca --diff. Para actualizar la CLI, ejecuta cm update. Para obtener más información, consulta Instala y configura la CLI.
Roles obligatorios
Para obtener los permisos que necesitas para configurar las integraciones de CI/CD para CodeMender, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:
- Administrador de cuenta de servicio (
roles/iam.serviceAccountAdmin) - Administrador de IAM de proyecto (
roles/resourcemanager.projectIamAdmin) -
Configura la federación de identidades para cargas de trabajo para las acciones de GitHub:
Administrador de grupos de identidades para cargas de trabajo (
roles/iam.workloadIdentityPoolAdmin) -
Crea activadores de Cloud Build:
- Editor de Cloud Build (
roles/cloudbuild.builds.editor) - Usuario de la cuenta de servicio (
roles/iam.serviceAccountUser)
- Editor de Cloud Build (
-
Ejecuta el hook de confirmación previa de Git de forma local:
Usuario de Agent Platform (
roles/aiplatform.user)
Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.
También puedes obtener los permisos necesarios a través de roles personalizados o cualquier otro rol predefinido.
Para garantizar que la cuenta de servicio de CI/CD tenga los permisos necesarios para ejecutar CodeMender en una canalización de CI/CD, pídele a tu administrador que otorgue los siguientes roles de IAM a la cuenta de servicio de CI/CD:
- Usuario de Agent Platform (
roles/aiplatform.user) en tu proyecto -
Escribe registros de compilación de Cloud Build:
Escritor de registros (
roles/logging.logWriter) en tu proyecto -
Guardar informes SARIF en un bucket de Cloud Storage:
Usuario de objetos de almacenamiento (
roles/storage.objectUser) en el bucket
Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.
Es posible que tu administrador también pueda otorgar a la cuenta de servicio de CI/CD los permisos necesarios a través de roles personalizados o de otros roles predefinidos.
Consideraciones de seguridad
Cuando ejecutas CodeMender en un flujo de trabajo de GitHub Actions, un activador de compilación de Cloud Build o un gancho previo a la confirmación de Git, CodeMender se ejecuta sin pedir confirmación. Antes de configurar estas integraciones, ten en cuenta lo siguiente:
- Mensajes de confirmación: La marca
--yesdesactiva los mensajes que te piden que confirmes los comandos del agente y las escrituras de archivos. La marca--bypass-warningomite la advertencia de que el agente puede modificar archivos y ejecutar comandos en tu sistema. Antes de usar estas marcas, lee las Condiciones de la versión preliminar que se encuentran al comienzo de este documento, incluidas las condiciones sobre la inhabilitación de la confirmación humana. - Zona de pruebas: Las canalizaciones desactivan la zona de pruebas de CodeMender con
--sandbox=false. Los comandos que ejecuta el agente, como las compilaciones y las pruebas cuando corrige un hallazgo, tienen el mismo acceso que el trabajo, incluidas sus credenciales deGoogle Cloud y el acceso a la red. El sandbox de Linux usa espacios de nombres de usuarios, que algunos entornos de CI, como los contenedores sin privilegios, no admiten. Desactiva la zona de pruebas solo en entornos aislados y desechables. Si tu entorno de CI admite la zona de pruebas, quita--sandbox=false. - Ejecutores: Ejecutan el flujo de trabajo de GitHub Actions en ejecutores alojados en GitHub, como
ubuntu-24.04, que ejecutan cada trabajo en una máquina virtual nueva. No uses ejecutores autohospedados que se reutilicen entre trabajos. - Código no confiable: El código de una solicitud de extracción puede contener texto que intente dirigir al agente. El flujo de trabajo de GitHub Actions solo analiza las solicitudes de extracción de ramas en el mismo repositorio, que solo los usuarios con acceso de escritura pueden crear. En el caso de Cloud Build, usa el control de comentarios para que un propietario o colaborador deba aprobar las compilaciones de las solicitudes de extracción de otros colaboradores.
- Acceso: Concede a cada cuenta de servicio solo los roles de Identity and Access Management (IAM) necesarios para su canalización.
Analiza solicitudes de extracción con GitHub Actions
El flujo de trabajo de esta sección analiza cada solicitud de extracción en un repositorio de GitHub.com. Cuando CodeMender encuentra una vulnerabilidad con gravedad CRITICAL o HIGH en los cambios de la solicitud de extracción, el flujo de trabajo hace lo siguiente:
- No pasa la verificación de análisis de CodeMender.
- Ejecuta
cm fixpara cada hallazgo y abre una solicitud de extracción con las correcciones en la rama de la solicitud de extracción.
El flujo de trabajo también sube los resultados al análisis de código de GitHub.
Configura la federación de identidades para cargas de trabajo
El flujo de trabajo se autentica en Google Cloud con la federación de identidades para cargas de trabajo, por lo que no almacenas una clave de cuenta de servicio en GitHub. Ejecuta los siguientes comandos con Google Cloud CLI:
Establece variables de shell para tu proyecto y repositorio:
PROJECT_ID="PROJECT_ID" GITHUB_ORG="GITHUB_ORG" REPO="GITHUB_ORG/REPOSITORY"Reemplaza lo siguiente:
PROJECT_ID: Es el ID del proyecto de Google Cloud .GITHUB_ORG: Es el nombre de tu organización de GitHub o tu nombre de usuario de GitHub para un repositorio en una cuenta personal.REPOSITORY: Es el nombre de tu repositorio de GitHub.
Habilita las APIs que usa la federación de identidades para cargas de trabajo:
gcloud services enable iam.googleapis.com \ cloudresourcemanager.googleapis.com iamcredentials.googleapis.com \ sts.googleapis.com --project="${PROJECT_ID}"Crea una cuenta de servicio para el flujo de trabajo y otórgale el rol de IAM de usuario de Agent Platform (
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}.iam.gserviceaccount.com" \ --role="roles/aiplatform.user"Crea un grupo de identidades para cargas de trabajo. Si ya tienes un grupo para GitHub Actions, omite este paso y usa el ID de tu grupo en lugar de
githuben los siguientes pasos.gcloud iam workload-identity-pools create github \ --project="${PROJECT_ID}" \ --location="global" \ --display-name="GitHub Actions"Crea un proveedor para GitHub en el grupo. La condición del atributo solo acepta tokens de los repositorios que son propiedad de
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"Permite que los flujos de trabajo de tu repositorio usen la cuenta de servicio:
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}"Obtén el nombre completo del proveedor. La necesitarás en la siguiente sección.
gcloud iam workload-identity-pools providers describe codemender \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github" \ --format="value(name)"El resultado luce de la siguiente manera:
projects/123456789/locations/global/workloadIdentityPools/github/providers/codemender
Los cambios en la federación de identidades para cargas de trabajo y en IAM pueden tardar hasta 5 minutos en aplicarse. Para obtener más información, consulta Configura la federación de Workload Identity con canalizaciones de implementación.
Agrega secretos al repositorio
En tu repositorio, ve a Configuración > Secretos y variables > Acciones y agrega los siguientes secretos del repositorio:
| Secret | Valor |
|---|---|
GCP_PROJECT_ID |
Es el ID de tu proyecto. |
GCP_WIF_PROVIDER |
Nombre completo del proveedor de la sección anterior. |
GCP_WIF_SERVICE_ACCOUNT |
codemender-ci@PROJECT_ID.iam.gserviceaccount.com,
donde PROJECT_ID es el ID de tu proyecto.
|
Para obtener más información, consulta Cómo usar secretos en GitHub Actions.
Configura los parámetros del repositorio
- Para permitir que el trabajo de corrección automática abra solicitudes de extracción, ve a Configuración > Acciones > General. En Permisos del flujo de trabajo, selecciona Permitir que GitHub Actions cree y apruebe solicitudes de extracción y, luego, haz clic en Guardar. Un repositorio de una organización hereda este parámetro de configuración de la organización. Si no puedes cambiarlo, pídele a un propietario de la organización que lo haga. Si no usas la corrección automática, omite este paso. Para obtener más información, consulta Cómo administrar la configuración de GitHub Actions para un repositorio.
- Asegúrate de que el análisis de código de GitHub esté disponible para el repositorio. En el caso de los repositorios privados e internos, el análisis de código requiere la función de seguridad del código de GitHub. Si el análisis de código no está disponible, borra el paso Subir resultados al análisis de código y los permisos
security-eventsyactionsdel trabajo de análisis. De lo contrario, la carga fallará, al igual que el trabajo de análisis. Para obtener más información, consulta Cómo subir un archivo SARIF a GitHub.
Agrega el flujo de trabajo
Confirma el siguiente flujo de trabajo en tu repositorio como .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 }}`.
Detalles del flujo de trabajo
En el siguiente diagrama, se muestra cómo interactúan los trabajos de análisis y corrección automática de solicitud de extracción:
El trabajo de análisis de CodeMender hace lo siguiente:
- Confirma la solicitud de extracción con su historial completo. En el caso de las solicitudes de extracción, GitHub extrae una confirmación de combinación de la rama de la solicitud de extracción en la rama base.
- Se autentica en Google Cloud y descarga la versión estable más reciente de la CLI de CodeMender.
- Ejecuta
cm find --diffen la rama base. El trabajo falla si CodeMender encuentra una vulnerabilidad con un nivel de gravedad que se indica enFAIL_ONen los cambios de la solicitud de extracción. - Sube el informe al análisis de código de GitHub, incluso cuando el análisis falla en el trabajo. El informe incluye hallazgos etiquetados como
[LEGACY / UNTOUCHED]. El análisis de código también muestra un hallazgo en las verificaciones de la solicitud de extracción cuando todas las líneas del hallazgo están en el diff de la solicitud de extracción. - Guarda los hallazgos que hicieron que fallara el trabajo de corrección automática.
El trabajo de análisis no se ejecuta para las solicitudes de extracción de bifurcaciones ni de Dependabot, ya que los flujos de trabajo de esas solicitudes de extracción no pueden leer los secretos del repositorio.
GitHub informa que un trabajo omitido se completó correctamente, por lo que la verificación no bloquea estas solicitudes de extracción, incluso si la conviertes en una verificación obligatoria. Revisa estas solicitudes de extracción por tu cuenta o escanéalas de forma local con cm find --diff.
El trabajo de corrección automática de CodeMender se ejecuta cuando el trabajo de análisis guarda los hallazgos. Hace lo siguiente:
- Confirma la rama de la solicitud de extracción.
- Ejecuta
cm fixpara cada hallazgo y confirma cada corrección por separado. Si CodeMender no corrige un hallazgo, el trabajo registra una advertencia. El trabajo solo confirma los cambios en los archivos que ya están en el repositorio y descarta los archivos que crea el agente de corrección, como el resultado de la prueba. - Abre una solicitud de extracción desde la rama
codemender/fix-pr-NUMBERa la rama de la solicitud de extracción, dondeNUMBERes el número de la solicitud de extracción. Si ya existe la solicitud de extracción de corrección, el trabajo la actualiza. Si CodeMender no corrige ningún problema o si el trabajo alcanza el tiempo de espera de 60 minutos, no se abrirá una solicitud de extracción.
Revisa y combina las correcciones
GitHub no ejecuta automáticamente los flujos de trabajo para las solicitudes de extracción que crea un flujo de trabajo con GITHUB_TOKEN. Para analizar la solicitud de extracción de corrección, un usuario con acceso de escritura al repositorio hace clic en Aprobar flujos de trabajo para ejecutar en la solicitud de extracción de corrección.
Cuando combinas la solicitud de extracción de corrección, la rama de la solicitud de extracción cambia y el flujo de trabajo vuelve a analizar la solicitud de extracción original.
Personaliza el flujo de trabajo
Puedes personalizar el flujo de trabajo de las siguientes maneras:
- Para cambiar los niveles de gravedad que fallan en la verificación, en el paso Analiza la solicitud de extracción, establece
FAIL_ONen una lista de niveles de gravedad separados por comas y sin espacios, comoCRITICAL,HIGH,MEDIUM. Los valores válidos sonCRITICAL,HIGH,MEDIUMyLOW. - Para informar los resultados sin que falle la verificación, establece
FAIL_ON: "". El flujo de trabajo sigue subiendo los resultados al análisis de código, pero no ejecuta el trabajo de corrección automática. Para analizar las solicitudes de extracción solo en algunas ramas, agrega un filtro
branchesal activadorpull_request. Luego, el flujo de trabajo no analiza las solicitudes de extracción de correcciones, ya que su base es una rama de solicitud de extracción:on: pull_request: branches: [main]Para desactivar la corrección automática, borra el trabajo
autofixy el paso Save findings for autofix.
Analiza solicitudes de extracción con Cloud Build
La compilación de esta sección analiza cada solicitud de extracción en un repositorio de GitHub conectado a Cloud Build. La compilación y su verificación de GitHub fallan cuando CodeMender encuentra una vulnerabilidad con gravedad CRITICAL o HIGH en los cambios de la solicitud de extracción. La compilación no corrige los hallazgos.
Antes de comenzar, haz lo siguiente:
- Conecta tu repositorio a Cloud Build como un repositorio de segunda generación. Para obtener más información, consulta Cómo conectarse a un repositorio de GitHub.
Habilita la API de Cloud Build y la API de IAM en el proyecto que tiene acceso a CodeMender. La compilación usa CodeMender en el proyecto que ejecuta la compilación.
PROJECT_ID="PROJECT_ID" gcloud services enable cloudbuild.googleapis.com iam.googleapis.com \ --project="${PROJECT_ID}"Reemplaza
PROJECT_IDpor el ID del proyecto de Google Cloud.
Crea una cuenta de servicio
Crea una cuenta de servicio para la compilación. Otorga el rol de IAM de usuario de Agent Platform (roles/aiplatform.user) para usar CodeMender y el rol de escritor de registros (roles/logging.logWriter) para escribir registros de compilación:
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"
Para guardar los informes SARIF en un bucket de Cloud Storage, también debes otorgar acceso a la cuenta de servicio al bucket:
BUCKET="BUCKET"
gcloud storage buckets add-iam-policy-binding "gs://${BUCKET}" \
--member="serviceAccount:${SA}" \
--role="roles/storage.objectUser"
Reemplaza BUCKET por el nombre de tu bucket de Cloud Storage.
Agrega la configuración de compilación
Confirma la siguiente configuración de compilación en la raíz de tu repositorio como 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
Crea el activador
Crea un activador que ejecute la compilación para cada solicitud de extracción en 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}"
Reemplaza lo siguiente:
REGION: Es la región de la conexión de tu repositorio de Cloud Build.CONNECTION: Es el nombre de la conexión de tu repositorio de Cloud Build.REPOSITORY: Es el nombre del repositorio conectado en Cloud Build.
Ten en cuenta las siguientes opciones:
--pull-request-patternes una expresión regular para la rama base de la solicitud de extracción. Usa^y$para que coincida con todo el nombre de la rama.- Con
--comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY, la compilación se ejecuta automáticamente para las solicitudes de extracción de los propietarios y colaboradores del repositorio. En el caso de las solicitudes de extracción de otros colaboradores, la compilación se ejecuta después de que un propietario o colaborador comenta/gcbrunen la solicitud de extracción. - Para guardar los informes SARIF en un bucket, agrega
--substitutions=_REPORT_BUCKET="${BUCKET}".
También puedes crear el activador en la consola de Google Cloud . Para obtener más información, consulta Cómo compilar repositorios desde GitHub.
Para mostrar los registros de compilación en GitHub, agrega --include-logs-with-status cuando crees el activador y otorga a la cuenta de servicio el rol de visualizador de registros (roles/logging.viewer). Cualquier persona que pueda ver la verificación en GitHub podrá leer los registros de compilación, incluidos los hallazgos.
Cómo funciona la compilación
La compilación tiene tres pasos:
install-codemenderdescarga la versión estable más reciente de la CLI de CodeMender.fetch-historyrecupera la rama base y el historial que necesita CodeMender. Cloud Build solo extrae el commit que inició la compilación. El paso recupera datos del elementooriginremoto. Sioriginno está configurado, el paso recupera datos de GitHub sin credenciales, lo que solo funciona para repositorios públicos. En ese caso, un repositorio privado necesita credenciales, como una clave SSH. Para obtener más información, consulta Cómo acceder a GitHub desde una compilación con claves SSH.scanejecutacm find --diffen la rama base. Cuando finaliza el análisis, el paso imprime todos los resultados en el registro de compilación. Si configuras_REPORT_BUCKET, el paso también copiará el informe SARIF engs://BUCKET/codemender/BUILD_ID.sarif.
Para cambiar las gravedades que hacen que falle la compilación, edita --fail-on en el paso scan. Si ejecutas la compilación sin un activador de solicitud de extracción, fallará con el mensaje Run this build from a pull request trigger..
Analiza el código antes de cada confirmación
Un hook de confirmación previa de Git puede analizar los cambios que se agregaron a la etapa de pruebas y bloquear la confirmación cuando CodeMender encuentra una vulnerabilidad con gravedad CRITICAL o HIGH. Los desarrolladores pueden omitir el gancho, por lo que se debe usar junto con el análisis en la CI, no en lugar de él.
Cada desarrollador que use el hook necesita lo siguiente:
- La CLI de CodeMender, instalada y configurada como se describe en Instala y configura la CLI, incluidos
gcloud auth application-default loginycm init. El gancho necesitacmen elPATH. - El rol de usuario de Agent Platform (
roles/aiplatform.user) en un proyecto con acceso a CodeMender CodeMender usa el proyecto en la variable de entornoGOOGLE_CLOUD_PROJECT. Si esa variable no está configurada, CodeMender usa el proyecto de tus credenciales predeterminadas de la aplicación o tu proyecto predeterminado de gcloud CLI.
Para agregar el hook, guarda la siguiente secuencia de comandos como .git/hooks/pre-commit en tu repositorio:
#!/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
Haz que la secuencia de comandos sea ejecutable y, luego, agrega .cm_project a tu archivo .gitignore para no confirmar el archivo que crea CodeMender para hacer un seguimiento del repositorio:
chmod +x .git/hooks/pre-commit
echo .cm_project >> .gitignore
Cuando ejecutas git commit, el gancho analiza los archivos con cambios en etapa de espera. El análisis puede tardar unos minutos. El gancho no desactiva la zona de pruebas de CodeMender.
Para confirmar sin el análisis, ejecuta git commit --no-verify.
Marcas de análisis
Las siguientes marcas cm find controlan los análisis de solicitud de extracción. Para todas las marcas, ejecuta cm
find --help:
| Marca | Valor predeterminado | Descripción |
|---|---|---|
--diff[=REF] |
Desactivado |
Analiza los cambios en comparación con REF, como origin/main. Sin REF, analiza los cambios no confirmados en los archivos rastreados (en comparación con HEAD). No se puede usar con --deep.
|
--staged |
Desactivado | Con --diff, solo se analizan los cambios almacenados en etapa intermedia. |
--diff-depth DEPTH |
1 |
Profundidad de la exploración para el análisis de impacto (de 1 a 3, valor predeterminado: 1 salto). |
--diff-workers COUNT |
4 |
Cantidad de archivos que se analizarán al mismo tiempo, de 1 a 16. |
--diff-max-neighbors COUNT |
10 |
Es la cantidad máxima de archivos dependientes que se pueden analizar. |
--fail-on SEVERITIES |
CRITICAL,HIGH |
Con --diff, las gravedades que hacen que cm find
salga con el estado 1. Si el valor está vacío, los hallazgos no afectan el estado de salida.
|
--fail-on-truncation |
Desactivado |
Con --diff, se sale con el estado 1 si CodeMender encuentra más archivos dependientes de los que permite --diff-max-neighbors.
|
--format FORMAT |
table |
Formato del informe: table, json o
sarif.
|
--output FILE |
Salida estándar | Es el archivo en el que se escribirá el informe. |
Soluciona problemas
En esta sección, se describe cómo resolver problemas habituales cuando se ejecuta CodeMender en canalizaciones de CI/CD.
Permiso denegado
En el registro, se muestra una línea como la siguiente:
[1/1] ❌ src/app.py: start session failed: StartSession failed with HTTP 403 Forbidden.
El mensaje también puede incluir Permission 'aiplatform.interactions.create'
denied. Verifica lo siguiente:
- El proyecto tiene acceso a CodeMender.
- La cuenta de servicio o el usuario tienen el rol de usuario de Agent Platform (
roles/aiplatform.user) en el proyecto. - La API de Agent Platform está habilitada en el proyecto.
- CodeMender usa el proyecto correcto. En GitHub Actions, verifica el secreto
GCP_PROJECT_ID. Cloud Build usa el proyecto que ejecuta la compilación. De forma local, verifica la variable de entornoGOOGLE_CLOUD_PROJECTo tu proyecto predeterminado si la variable no está configurada.
Configuración de recursos en curso
Si el registro muestra Resource setup has just started. Please try again shortly. o Resource setup is in progress. Please try again shortly., CodeMender está configurando recursos para tu proyecto, lo que suele tardar unos minutos. Vuelve a ejecutar el trabajo más tarde.
Marca desconocida: --diff
Si cm find falla con Error: unknown flag: --diff, la versión de la CLI no admite análisis de solicitud de extracción. Ejecuta cm update o descarga la versión más reciente.
No se encontró la rama base
Si cm find falla con un error como el siguiente, la rama base no está en la confirmación:
Error: retrieving VCS diff: git diff failed: exit status 128: fatal: ambiguous argument 'origin/main': unknown revision or path not in the working tree.
Recupera la rama base y su historial antes de ejecutar cm find. En GitHub Actions, configura fetch-depth: 0 en actions/checkout.
No se analizaron los archivos
Una línea con una ❌, como [1/1] ❌ src/app.py: start session failed, significa que CodeMender no pudo analizar ese archivo. Verifica el error en la línea y, luego, vuelve a ejecutar el trabajo.
Solicitud de extracción sin corrección
Si el flujo de trabajo no abre una solicitud de extracción de corrección, verifica lo siguiente:
- Si el trabajo de corrección automática falla cuando crea la solicitud de extracción, activa Permitir que las acciones de GitHub creen y aprueben solicitudes de extracción. Para obtener más información, consulta Cómo configurar los parámetros del repositorio.
- Si el trabajo de corrección automática se realiza correctamente sin abrir una solicitud de extracción, CodeMender no corrigió ningún problema. En el registro de trabajo, se muestra una advertencia para cada hallazgo que CodeMender no corrigió.
Falla la carga del análisis de código
Si el paso de carga falla con GitHub Code Security or GitHub Advanced Security
must be enabled for this repository to use code scanning, habilita la seguridad del código de GitHub para el repositorio o borra el paso de carga. Para obtener más información, consulta Cómo configurar los parámetros del repositorio.
No se confirmó la advertencia
Si cm falla con warning not acknowledged. Please run interactively once to
acknowledge or pass --bypass-warning, CodeMender necesita confirmación, que no puede solicitar en un entorno no interactivo. Agrega --bypass-warning al comando. Antes de hacerlo, lee las Condiciones de la versión preliminar que se encuentran en la parte superior de esta página.
Si necesitas más ayuda, comunícate con tu equipo de ventas.