La integración de CI/CD conecta tus canalizaciones de CI/CD a la protección de artefactos para detectar vulnerabilidades de contenedores durante la etapa de compilación.
El escáner admite GitHub Actions, Cloud Build y Jenkins. Cuando se integra en una canalización, evalúa las imágenes de contenedores según tus políticas de protección de artefactos antes de que las imágenes se envíen a un registro.
Capacidades del escáner
La integración de CI/CD se ejecuta como un objeto binario dentro de tu flujo de trabajo de CI/CD para realizar las siguientes tareas:
- Evaluación de políticas durante la compilación: Analiza las imágenes de contenedor recién compiladas en función de las políticas de protección de artefactos configuradas.
- Bloqueo de compilaciones: Devuelve códigos de salida a tu ejecutor de CI/CD (GitHub Actions, Cloud Build o Jenkins) para bloquear las compilaciones que incumplen tus políticas de seguridad.
- Informes de análisis: Envía los resultados del análisis de vulnerabilidades a Security Command Center y genera informes locales en formatos JSON o SARIF.
Roles y responsabilidades objetivo
La integración de CI/CD está diseñada para los siguientes equipos:
- Equipos de DevOps o ingeniería de plataformas: Crea conectores de canalización y agrega pasos de ejecución del analizador a la configuración del flujo de trabajo de CI/CD.
- Administradores de seguridad: Definen las políticas de vulnerabilidades previas a la compilación que aplica el scanner.
- Desarrolladores de aplicaciones: Revisen los registros de ejecución del análisis en los resultados de la compilación de CI/CD para identificar y corregir los incumplimientos de políticas.
Términos y conceptos clave
- Vulnerabilidades y exposiciones comunes (CVE): Es una vulnerabilidad de seguridad informática divulgada públicamente a la que se le asigna un identificador único.
- Lista de materiales de software (SBOM): Es un inventario legible por máquina de los componentes y las dependencias de software que se usa para identificar CVE y otros riesgos de seguridad.
- Artefacto: En el contexto de protección de artefactos, una imagen de contenedor compilada por una canalización de CI/CD.
- Conector: Es un recurso que vincula tu canalización de CI/CD a la protección de artefactos. Cuando se pasa desde la canalización de CI durante una exploración, el ID del conector determina qué políticas evalúan la imagen.
- Política de CI: Es una política de vulnerabilidades que define las reglas específicas de CVE, gravedad y paquetes que se aplican durante las compilaciones de CI/CD.
Flujo de trabajo de alto nivel
Para configurar y ejecutar análisis de vulnerabilidades de CI/CD, completa el siguiente flujo de trabajo:
- Crea un conector de CI para tu plataforma de CI/CD de destino.
- Crea una política de Artifact Guard que incluya el ID del conector en su alcance de canalización.
- Configura tu canalización de CI/CD para autenticarte enGoogle Cloud, compilar la imagen del contenedor y ejecutar el contenedor del analizador.
Cuando se ejecuta la canalización, el escáner evalúa la imagen de contenedor en función de tu política. Si la imagen incumple la política, el verificador muestra un código de salida de falla para que la compilación falle. Luego, los desarrolladores pueden inspeccionar los registros de compilación, actualizar las dependencias vulnerables y volver a ejecutar la compilación.
Antes de comenzar
Para usar la integración de CI/CD, debes habilitar la protección de artefactos. Para obtener instrucciones, consulta Antes de comenzar en la documentación de protección de artefactos.
Crear un conector
Console
Para crear un conector en la consola de Google Cloud , sigue estos pasos:
- En la consola de Google Cloud , ve a Seguridad > Configuración.
- En la tarjeta protección de artefactos, haz clic en Administrar configuración.
- Haz clic en Crear conector y, luego, ingresa los siguientes detalles del conector:
- ID del conector: Agrega un ID para el conector.
- Descripción: Ingresa una descripción del conector.
- Plataforma de CI/CD: Selecciona la plataforma de CI/CD correspondiente en la lista. Usa este conector solo en las canalizaciones creadas con la plataforma de CI/CD seleccionada.
- Haz clic en Crear.
Una notificación confirma que se creó el conector correctamente. En la tabla Connectors, se enumeran los conectores disponibles.
gcloud CLI
Para crear un conector con gcloud CLI, ejecuta el siguiente comando:
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]
Reemplaza lo siguiente:
- CONNECTOR_ID: Es un identificador del conector (por ejemplo,
my-connector). - LOCATION: Es la ubicación de Security Command Center en la que se almacenan tus datos. Solo se admite
global. - ORGANIZATION_ID: Es el ID de organización.
- PROJECT_NUMBER: Es el número de proyecto numérico.
- PIPELINE_TYPE: Es el tipo de canalización de CI/CD. Debe ser una de las siguientes opciones:
GOOGLE_CLOUD_BUILDGITHUB_ACTIONSJENKINS_PIPELINE
- DESCRIPTION: Es una descripción de texto para el conector.
- DISPLAY_NAME: Es un nombre visible descriptivo para el conector.
Actualiza un conector
Console
Para vincular una política a un conector en la consola de Google Cloud , sigue estos pasos:
- En la consola de Google Cloud , ve a Seguridad > Configuración.
- En la tarjeta protección de artefactos, haz clic en Administrar configuración.
- En la tabla Conectores, haz clic en junto al conector y selecciona Agregar política.
- Sigue los pasos para crear o actualizar una política de protección de artefactos. Para obtener más información, consulta Crea una política.
gcloud CLI
Para ver los conectores existentes y actualizar sus asociaciones de políticas con gcloud CLI, usa los siguientes comandos:
Enumerar conectores
gcloud alpha scc artifact-guard connectors list PARENT
Reemplaza lo siguiente:
- PARENT: Es una organización o un proyecto. Entre los formatos aceptables para el recurso principal, se incluyen los siguientes:
organizations/ORGANIZATION_ID/locations/LOCATIONprojects/PROJECT_NUMBER/locations/LOCATION
Describe un conector
gcloud alpha scc artifact-guard connectors describe CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
Actualiza la asociación de la política del conector
Para vincular un conector a una política, incluye el ID del conector en el alcance de la canalización de tu archivo de definición de políticas y actualiza la política con el comando gcloud alpha scc artifact-guard policies update. Para obtener más información, consulta Crea una política.
Borra un conector
Console
Para borrar un conector en la consola de Google Cloud , sigue estos pasos:
- En la consola de Google Cloud , ve a Seguridad > Configuración.
- En la tarjeta protección de artefactos, haz clic en Administrar configuración.
- En la tabla Connectors, haz clic en junto al conector y selecciona Delete connector.
- Sigue las indicaciones de confirmación para borrar el conector. Haz clic en Cancelar para anular la acción.
gcloud CLI
Para borrar un conector con gcloud CLI, ejecuta el siguiente comando:
gcloud alpha scc artifact-guard connectors delete CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
Ejecutar una evaluación
Las canalizaciones de GitHub Actions y Jenkins admiten el análisis de vulnerabilidades. Para realizar una evaluación, debes hacer lo siguiente:
- Crea secretos para la autenticación.
- Crea un archivo de plantilla de integración específico para tu canalización.
- Inicia una evaluación.
Configuración de Secret
Las canalizaciones de CI/CD que se ejecutan fuera de Google Cloud pueden autenticarse con claves de cuentas de servicio o con la federación de identidades para cargas de trabajo. Para obtener instrucciones detalladas sobre cómo crear secretos, consulta lo siguiente:
Claves de cuenta de servicio
Federación de identidades para cargas de trabajo (para acciones de GitHub)
Debes agregar secretos a tu entorno de CI/CD con uno de los siguientes métodos:
Método de clave de cuenta de servicio
Un secreto:
GCP_CREDENTIALS: Es el contenido del archivo de clave JSON de la cuenta de servicio que descargaste.
Método de federación de identidades para cargas de trabajo
Dos secretos:
GCP_WORKLOAD_IDENTITY_PROVIDER: Es el nombre completo del recurso de tu proveedor de identidades para cargas de trabajo. Por ejemplo,projects/12345/locations/global/workloadIdentityPools/my-pool/providers/my-providerGCP_SERVICE_ACCOUNT: Es la dirección de correo electrónico de la cuenta de servicio que se representará.
Plantillas de integración de canalizaciones
Para activar una evaluación, debes crear un archivo específico para tu canalización (Cloud Build, GitHub Actions o Jenkins) con los siguientes ejemplos de plantillas:
Cloud Build
Consulta Definiciones de variables para obtener información sobre cada campo.
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@developer.gserviceaccount.com" options: logging: CLOUD_LOGGING_ONLY
Acciones de GitHub (secreto)
Esta plantilla es para las acciones de GitHub que usan una clave secreta.
- Agrega la clave secreta de tu cuenta de servicio (
GCP_CREDENTIALS). Consulta Definiciones de variables para obtener información sobre los campos adicionales.
# 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}"
Acciones de GitHub (WIF)
Esta plantilla es para las acciones de GitHub que usan la federación de identidades para cargas de trabajo.
- Agrega tu proveedor de identidades para cargas de trabajo en el secreto de GitHub (
GCP_WORKLOAD_IDENTITY_PROVIDER). - Agrega tu cuenta de servicio en el secreto de GitHub (
GCP_SERVICE_ACCOUNT). Consulta Definiciones de variables para obtener información sobre los campos adicionales.
# 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 (secreto)
- Agrega la clave secreta de la cuenta de servicio (
GCP_CREDENTIALS). Consulta Definiciones de variables para obtener información sobre los campos adicionales.
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}" } } } }
Definiciones de variables
En esta sección, se proporciona información sobre los campos de variables que se usan en las plantillas de integración de canalizaciones.
IMAGE_NAME_TO_SCAN (obligatorio)
- Especifica la etiqueta de la imagen de la aplicación que se compilará.
GCP_PROJECT_ID (obligatorio)
- Especifica el Google Cloud ID del proyecto que se usa para la autenticación y la configuración.
AR_REPOSITORY (opcional)
- Especifica el nombre del repositorio de Artifact Registry en el que la canalización publica la imagen si la compilación se realiza correctamente.
ORGANIZATION_ID (obligatorio)
- ID de organización Google Cloud .
CONNECTOR_ID (obligatorio)
- Especifica el ID del conector de la canalización que se usará.
SCANNER_IMAGE (obligatorio)
La imagen del analizador prediseñado analiza el código, identifica vulnerabilidades evaluando imágenes en función de las políticas durante la compilación y produce un resultado de cumplimiento para determinar si la canalización de CI/CD pasa o falla.
Detalles de la imagen:
us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest
VERBOSITY (opcional)
- El escáner admite una marca
VERBOSITYopcional que controla el nivel de detalle que se muestra en el resultado del análisis. El resultado del escáner varía según el nivel de detalle y el resultado de cumplimiento (Aprobado o No aprobado). La marca de verbosidad se puede establecer en
LOWoHIGH. Si no se proporciona, el valor predeterminado esLOW.
Poca verbosidad (conciso)
Cumplimiento de ArtifactGuard: Aprobado
- Detalla los nombres de las políticas.
- Solo proporciona el recuento resumido de CVE por gravedad.
ArtifactGuard Conformance: Fail
- Detalla el motivo del error.
- Solo enumera los CVE específicos que causaron la falla.
- Proporciona un recuento resumido de los CVE categorizados por gravedad.
Verbosidad alta (detallada)
Proporciona una lista completa de todas las vulnerabilidades encontradas.
Cumplimiento de ArtifactGuard: Aprobado
- Proporciona una lista de todos los CVE detectados para la política.
- Proporciona un recuento resumido de los CVE desglosados por gravedad.
- Proporciona una lista completa de todas las vulnerabilidades detectadas.
ArtifactGuard Conformance: Fail
- Incluye el motivo del error.
- Enumera los CVE que causan la falla.
- Proporciona una lista de todos los CVE detectados para la política.
- Proporciona un recuento resumido de los CVE desglosados por gravedad.
- Proporciona una lista completa de todas las vulnerabilidades detectadas.
IGNORE_SERVER_ERRORS (opcional)
- Es una marca booleana opcional. Si es
true, la canalización continúa a pesar de los errores del servidor. La configuración predeterminada esfalse.
Cómo iniciar una evaluación
Durante el proceso de compilación, una estrategia basada en Docker evalúa la imagen según políticas predefinidas. La lógica del análisis de vulnerabilidades se encuentra dentro de la imagen us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest.
Para iniciar un análisis de vulnerabilidades en tu canalización de CI/CD, ejecuta el siguiente comando:
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=$?
La integración de CI/CD propaga los códigos de salida del contenedor de Docker al tiempo de ejecución de Jenkins o GitHub Actions, que luego determina el estado de aprobación o falla de la canalización.
Soluciona problemas
En esta sección, se describen los errores comunes y cómo resolverlos.
Fallas de CreateConnector
| Campo | Obligatorio/Opcional | Limitaciones |
|---|---|---|
name |
Obligatorio | Formato: Debe coincidir con la expresión regular [a-zA-Z0-9\\-\\s_]+$ . Debe coincidir con uno o más de los siguientes elementos:
Longitud máxima: 64 caracteres. |
pipeline_type |
Obligatorio | Debe ser uno de los siguientes valores de enumeración:
|
description |
Opcional | No debe superar los 256 caracteres. |
display_name |
Opcional | No debe superar los 256 caracteres. |
Otros errores
En la siguiente tabla, se describen algunos errores comunes y cómo resolverlos.
| Mensaje de error | Causa | Acción/Resolución |
|---|---|---|
Permiso artifactscanguard.connectors.create
denegado en el recurso |
El usuario o la cuenta de servicio no tienen el permiso de IAM artifactscanguard.connectors.create en el recurso (proyecto, carpeta u organización). |
Otorga al llamador un rol de IAM que incluya el permiso
artifactscanguard.connectors.create. |
status.ErrFailedPrecondition |
Es posible que la incorporación esté en curso, incluso si la Google Cloud consola muestra el servicio como habilitado. | Informa un problema al equipo de asistencia al cliente. |
status.ErrInvalidArgument |
Errores de validación de campos | Asegúrate de que la solicitud CreateConnector cumpla con las restricciones especificadas. |