Configurar a integração de CI/CD

Os clientes do Security Command Center podem ter dificuldade em obter uma visão centralizada e abrangente dos resultados da verificação dos ambientes de integração contínua/entrega contínua (CI/CD). Essa falta de uma visualização unificada complica a gestão de vulnerabilidades. A integração de CI/CD é um componente do artifact guard (prévia) que permite conectar vários pipelines de CI/CD para ajudar a detectar vulnerabilidades em todo o ciclo de vida de desenvolvimento de software.

A integração de CI/CD é compatível com o GitHub Actions, o Cloud Build e o Jenkins. Depois de conectado, você pode usar qualquer uma dessas plataformas de CI/CD para configurar políticas do Artifact Guard, oferecendo visibilidade e controle proativo sobre sua postura de segurança.

Visão geral

A integração de CI/CD oferece o seguinte:

  • Aplicação de políticas de ponta a ponta: ajuda o Artifact Guard a aplicar políticas de segurança consistentes do código à nuvem.
  • Detecção abrangente de ameaças: verifica vulnerabilidades, segredos expostos, licenças problemáticas e pacotes maliciosos.
  • Compatibilidade ampla com CI/CD: funciona com Jenkins e GitHub Actions.
  • Otimizado para CI/CD: um binário leve garante uma operação eficiente em ambientes locais.
  • Saída flexível: fornece resultados em formatos JSON e SARIF padrão do setor.
  • Insights de segurança centralizados: oferece visões claras de conformidade com a política diretamente no painel de segurança.

Esse scanner preenche nativamente o Security Command Center, oferecendo uma visão unificada e centrada em recursos das descobertas de segurança da criação de artefatos.

A integração de CI/CD ajuda a aplicar políticas de proteção de artefatos em todo o ciclo de vida do software. Isso garante que os artefatos sejam validados para conformidade desde a criação até a implantação.

Público-alvo

A integração de CI/CD pode ajudar com as seguintes tarefas das partes interessadas:

  • Usuários principais: equipes de DevOps e engenharia de plataforma
    • Gerenciar e integrar: responsável por gerenciar a ferramenta de verificação e integrá-la diretamente aos pipelines de CI/CD.
    • Configurar políticas: defina as etapas de verificação.
    • Monitorar a conformidade: acompanhe a conformidade da build e trabalhe com administradores de segurança para refinar as políticas.
  • Usuários secundários: administradores de segurança
    • Autores de políticas: definem e aplicam políticas de segurança com base na importância para os negócios.
    • Automatizar a aplicação: automatize a segurança no CI/CD para reduzir o ruído de vulnerabilidade e definir critérios de gating.
    • Supervisione: colabore com o DevOps e ofereça um painel para que a gerência acompanhe as vulnerabilidades controladas.
  • Usuários secundários: desenvolvedores de aplicativos
    • Analisar e corrigir: interaja com os resultados da avaliação de política, analise os resultados da build e corrija os problemas de segurança sinalizados.
    • Avaliar: inicie a avaliação da política indiretamente pelo processo de build do pipeline de CI.
    • Manter a conformidade: garanta a conformidade com os requisitos de segurança sem interromper os fluxos de trabalho de desenvolvimento.

Principais termos e conceitos

  • Vulnerabilidades e exposições comuns (CVE): uma vulnerabilidade de segurança de computador divulgada publicamente que recebe um identificador exclusivo. Esses identificadores ajudam a rastrear vulnerabilidades para correção.
  • Lista de materiais de software (SBOM): um inventário legível por máquina de componentes e dependências de software. Uma lista de materiais de software inclui informações sobre a versão, a origem e outros detalhes relevantes de cada componente. As listas de materiais de software podem ser usadas para identificar CVEs e outros riscos de segurança.
  • Artefato: uma saída versionada e validada do desenvolvimento de software, como dados ou um item criado durante o processo de build.
  • Conector: uma tag para imagens. Quando transmitido do pipeline de CI para o serviço de proteção de artefatos, um conector determina quais políticas executar na imagem que está sendo criada.
  • Política de CI: uma política de vulnerabilidade que define regras ou critérios para controlar quais vulnerabilidades e pacotes são permitidos no seu ambiente.

Fluxo de trabalho de alto nível

  1. Criar conectores de CI.
  2. Crie políticas de proteção de artefatos usando os conectores configurados na etapa anterior para definir o escopo da política.
  3. Iniciar avaliações de artefatos.

Durante uma avaliação, uma imagem é criada e avaliada em relação a políticas predefinidas. Se as políticas falharem, o build vai falhar. Os engenheiros de DevOps ou de aplicativos precisam examinar os detalhes da falha para encontrar a vulnerabilidade específica, atualizar a dependência de acordo com os detalhes do CVE e executar o pipeline novamente.

Antes de começar

Para usar a integração de CI/CD, é necessário ativar a proteção de artefatos. Para instruções, consulte Antes de começar na documentação do Artifact Guard.

Em seguida, crie conectores no console doGoogle Cloud ou usando a Google Cloud CLI.

Criar um conector no console Google Cloud

Para criar um conector, siga estas etapas:

  1. No console do Google Cloud , acesse Segurança > Configurações.

  2. No card Proteção de artefatos, clique em Gerenciar configurações.

  3. Clique em Criar conector e insira os seguintes detalhes:

    • ID do conector: adicione um ID para o conector.
    • Descrição: insira uma descrição do conector.
    • Plataforma de CI/CD: selecione a plataforma de CI/CD correspondente na lista. Ele só pode ser usado nos pipelines criados com a plataforma de CI/CD fornecida.
  4. Clique em Criar.

Uma notificação confirma a criação do conector. Os conectores disponíveis estão listados na tabela "Conectores".

Para remover um conector, clique em ao lado dele e selecione Excluir conector. Depois, siga as instruções. Clique em Cancelar para interromper.

Para vincular uma política a um conector, clique em ao lado do conector e selecione Adicionar política. Siga as etapas para criar uma política de proteção de artefatos. Para mais informações, consulte Criar uma política.

Criar um conector usando a Google Cloud CLI

Esta seção descreve os comandos da CLI gcloud disponíveis para a verificação de artefatos de CI/CD e como usá-los.

Pré-requisitos da Google Cloud CLI

  • Verifique se a versão da CLI gcloud é 559.0.0 ou mais recente.
  • Defina seu projeto como o projeto de configuração.

Para fazer isso, execute os seguintes comandos da CLI gcloud:

   gcloud components update --version=559.0.0
   gcloud config set project PROJECT_ID

Comandos da Google Cloud CLI

create

gcloud alpha scc artifact-guard connectors create CONNECTOR_ID \
    --location=LOCATION \
    (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER) \
    --pipeline-type=PIPELINE_TYPE \
    [--description=DESCRIPTION] \
    [--display-name=DISPLAY_NAME]
  • CONNECTOR_ID: o ID do conector a ser criado.
  • PIPELINE_TYPE: o tipo de pipeline de CI/CD. Deve ser um dos seguintes:
    • GOOGLE_CLOUD_BUILD
    • GITHUB_ACTIONS
    • JENKINS_PIPELINE
  • DESCRIPTION: uma descrição textual do conector.
  • DISPLAY_NAME: um nome de exibição fácil de usar para o conector.

get

gcloud alpha scc artifact-guard connectors describe CONNECTOR_ID \
    --location=LOCATION \
    (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
  • CONNECTOR_ID: o ID do conector a ser descrito.

list

gcloud alpha scc artifact-guard connectors list PARENT
  • PARENT: uma organização ou um projeto. Formatos aceitos para o recurso pai:
    • {organizations/ORGANIZATION_ID/locations/LOCATION}
    • {projects/PROJECT_NUMBER/locations/LOCATION}

excluir

gcloud alpha scc artifact-guard connectors delete CONNECTOR_ID \
    --location=LOCATION \
    (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
  • CONNECTOR_ID: o ID do conector a ser excluído.

Executar uma avaliação

A verificação de vulnerabilidades é compatível com pipelines do GitHub Actions e do Jenkins. Para realizar uma avaliação, faça o seguinte:

  1. Crie secrets para autenticação.
  2. Crie um arquivo de modelo de integração específico para seu pipeline.
  3. Inicie uma avaliação.

Configuração de secrets

Os pipelines de CI/CD executados fora do Google Cloud podem ser autenticados usando chaves de conta de serviço ou a federação de identidade da carga de trabalho. Para instruções detalhadas sobre como criar secrets, consulte:

Chaves da conta de serviço

Federação de identidade da carga de trabalho (para o GitHub Actions)

Adicione secrets ao ambiente de CI/CD usando um dos seguintes métodos:

Método de chave da conta de serviço

Um secret:

  • GCP_CREDENTIALS: o conteúdo do arquivo de chave JSON da conta de serviço baixado.

Método de federação de identidade da carga de trabalho

Dois secrets:

  • GCP_WORKLOAD_IDENTITY_PROVIDER: o nome completo do recurso do provedor de identidade de carga de trabalho. Por exemplo, projects/12345/locations/global/workloadIdentityPools/my-pool/providers/my-provider.

  • GCP_SERVICE_ACCOUNT: o endereço de e-mail da conta de serviço a ser personificada.

Modelos de integração de pipeline

Para acionar uma avaliação, crie um arquivo específico para seu pipeline (Cloud Build, GitHub Actions ou Jenkins) usando os seguintes exemplos de modelos:

Cloud Build

  • Consulte Definições de variáveis para informações 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
    

GitHub Actions (secreto)

Este modelo é para o GitHub Actions usando uma chave secreta.

  • Adicione sua chave secreta da conta de serviço (GCP_CREDENTIALS).
  • Consulte Definições de variáveis para informações sobre campos adicionais.

    # A workflow to BUILD the app image, RUN the scanner, and PUSH to AR if scan passes
    name: Build, Scan and Push
    
    on:
     workflow_dispatch:
       inputs:
          IMAGE_NAME_TO_SCAN:
                description: 'The tag for your application image to be built (e.g., my-app:latest)'
                required: true
                default: 'checkout-image'
          GCP_PROJECT_ID:
                description: 'GCP Project ID for authentication'
                required: true
                default: 'projectId'
          AR_REPOSITORY:
                description: 'Artifact Registry repository name (e.g., app-repo)'
                required: false
                default: 'images'
          ORGANIZATION_ID:
                description: 'Your GCP Organization ID'
                required: true
                default: 'orgId'
          CONNECTOR_ID:
                description: 'The ID for your pipeline connector'
                required: true
                default: 'connectorId'
          SCANNER_IMAGE:
                description: 'The full registry path for your PRE-BUILT scanner tool'
                required: true
                default: 'us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest'
          IMAGE_TAG:
                description: 'The Docker image version (of the app image)'
                required: true
                default: 'latest'
          IGNORE_SERVER_ERRORS:
                description: 'Ignore server errors'
                required: false
                type: boolean
                default: false
          VERBOSITY:
                description: 'Verbosity flag'
                required: false
                default: 'HIGH'
    
    jobs:
     build-and-scan:
       runs-on: ubuntu-latest
       steps:
          # 1. Check out repository (for your app's Dockerfile)
          - name: Check out repository
            uses: actions/checkout@v4
    
          # 2. Authenticate to Google Cloud
          - name: Authenticate to GCP
            id: auth
            uses: 'google-github-actions/auth@v2'
            with:
                credentials_json: '${{ secrets.GCP_CREDENTIALS }}'
    
          # 3. Set up the gcloud CLI
          - name: Set up Cloud SDK
            uses: 'google-github-actions/setup-gcloud@v2'
            with:
                project_id: ${{ inputs.GCP_PROJECT_ID }}
    
           # 4. Configure Docker (needed to pull SCANNER_IMAGE and push app image)
          - name: Configure Docker
            run: gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
    
          # 5. Build Application Image Locally (IMAGE_NAME_TO_SCAN)
          - name: Build Application Image Locally
            uses: docker/build-push-action@v5
            with:
                context: .
                file: ./Dockerfile
                push: false  # <-- Do not push
                load: true   # <-- Load image into the runner's local daemon
                # Tag the image with the name the scanner will look for
                tags: |
                ${{ inputs.IMAGE_NAME_TO_SCAN }}:${{ inputs.IMAGE_TAG }}
    
          # 6. Run Image Scan (Using the SCANNER_IMAGE)
          - name: 'Run Image Analysis Scan'
            if: steps.auth.outcome == 'success'
            run: |
                echo "📦 Pulling scanner image and running scan..."
    
          SCANNER_IMAGE="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.SCANNER_IMAGE || env.SCANNER_IMAGE }}"
          GCP_PROJECT_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.GCP_PROJECT_ID || env.GCP_PROJECT_ID }}"
          ORGANIZATION_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ORGANIZATION_ID || env.ORGANIZATION_ID }}"
          IMAGE_NAME="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IMAGE_NAME_TO_SCAN || env.IMAGE_NAME_TO_SCAN }}"
          IMAGE_TAG="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IMAGE_TAG || env.IMAGE_TAG }}"
          CONNECTOR_ID="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.CONNECTOR_ID || env.CONNECTOR_ID }}"
          VERBOSITY="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.VERBOSITY || env.VERBOSITY }}"
          IGNORE_ERRORS="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.IGNORE_SERVER_ERRORS || (env.IGNORE_SERVER_ERRORS == 'true') }}"
    
          exit_code=0
    
          # This 'docker run' pulls the SCANNER_IMAGE from the registry
          # and passes the name of the locally-built app image (IMAGE_NAME)
          docker run --rm \
                -v /var/run/docker.sock:/var/run/docker.sock \
                -v ${{ steps.auth.outputs.credentials_file_path }}:/tmp/scc-key.json \
                -e GCLOUD_KEY_PATH=/tmp/scc-key.json \
                -e GCP_PROJECT_ID="${GCP_PROJECT_ID}" \
                -e ORGANIZATION_ID="${ORGANIZATION_ID}" \
                -e IMAGE_NAME="${IMAGE_NAME}" \
                -e IMAGE_TAG="${IMAGE_TAG}" \
                -e CONNECTOR_ID="${CONNECTOR_ID}" \
                -e BUILD_TAG="${{ github.workflow }}" \
                -e BUILD_ID="${{ github.run_number }}" \
                -e VERBOSITY="${VERBOSITY}" \
                "${SCANNER_IMAGE}" \
                || exit_code=$?
    
          echo "Docker run finished with exit code: $exit_code"
    
          # --- Replicate Jenkins Exit Code Logic ---
          if [ $exit_code -eq 0 ]; then
            echo "✅ Evaluation succeeded: Conformant image."
          elif [ $exit_code -eq 1 ]; then
            echo "❌ Scan failed: Non-conformant image (vulnerabilities found)."
            exit 1 # Fail the step
          else
           if [ "$IGNORE_ERRORS" = "true" ]; then
                echo "⚠️ Server/internal error occurred (Code: $exit_code), but IGNORE_SERVER_ERRORS=true. Proceeding."
          else
            echo "❌ Server/internal error occurred (Code: $exit_code) during evaluation. Set IGNORE_SERVER_ERRORS=true to override."
            exit 1 # Fail the step
          fi
          fi
    
          # 8. Push Application Image (ONLY if scan succeeded)
          # This step only runs if the 'Run Image Analysis Scan' step above exited with 0
          - name: Push Application Image to Artifact Registry
            run: |
            # Define the local and remote tags
            LOCAL_IMAGE_NAME="${{ inputs.IMAGE_NAME_TO_SCAN }}:${{ inputs.IMAGE_TAG }}"
    
            # This path is based on your 'Configure Docker' step (us-central1)
            # and the new AR_REPOSITORY input.
            FULL_AR_TAG="us-central1-docker.pkg.dev/${{ inputs.GCP_PROJECT_ID }}/${{ inputs.AR_REPOSITORY }}/${{ inputs.IMAGE_NAME_TO_SCAN }}:${{ inputs.IMAGE_TAG }}"
    
            echo "Tagging local image ${LOCAL_IMAGE_NAME} as ${FULL_AR_TAG}"
            docker tag "${LOCAL_IMAGE_NAME}" "${FULL_AR_TAG}"
    
            echo "Pushing ${FULL_AR_TAG} to Artifact Registry..."
            docker push "${FULL_AR_TAG}"
    

GitHub Actions (WIF)

Este modelo é para o GitHub Actions usando a federação de identidade da carga de trabalho.

  • Adicione seu provedor de identidade de carga de trabalho no segredo do GitHub (GCP_WORKLOAD_IDENTITY_PROVIDER).
  • Adicione sua conta de serviço ao segredo do GitHub (GCP_SERVICE_ACCOUNT).
  • Consulte Definições de variáveis para informações sobre campos adicionais.

    # 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 (secret)

  • Adicione a chave secreta da conta de serviço (GCP_CREDENTIALS).
  • Consulte Definições de variáveis para informações sobre campos adicionais.

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

Definições de variáveis

Esta seção fornece informações sobre os campos de variáveis usados nos modelos de integração de pipeline.

IMAGE_NAME_TO_SCAN (obrigatório)

  • Especifica a tag da imagem do aplicativo a ser criada.

GCP_PROJECT_ID (obrigatório)

  • Especifica o ID do projeto Google Cloud usado para autenticação e configuração.

AR_REPOSITORY (opcional)

  • Especifica o nome do repositório do Artifact Registry em que a imagem será publicada se o build for bem-sucedido.

ORGANIZATION_ID (obrigatório)

  • O ID da organização Google Cloud .

CONNECTOR_ID (obrigatório)

  • Especifica o ID do conector do pipeline a ser usado.

SCANNER_IMAGE (obrigatório)

  • A imagem do scanner pré-criado analisa o código, identifica vulnerabilidades avaliando imagens em relação às políticas durante o build e produz um resultado de conformidade para determinar se o pipeline de CI/CD é aprovado ou reprovado.

    Detalhes da imagem: us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest

VERBOSITY (opcional)

  • O scanner é compatível com uma flag VERBOSITY opcional que controla o nível de detalhes mostrado na saída da verificação. A saída do scanner varia de acordo com o nível de detalhamento e o resultado de conformidade (Aprovado ou Reprovado).
  • A flag de verbosidade pode ser definida como LOW ou HIGH. O padrão é LOW se não for fornecido.

Baixa verbosidade (conciso)

Conformidade do ArtifactGuard : False

  • Detalha o motivo da falha.
  • Lista apenas os CVEs específicos que causaram a falha.
  • Fornece uma contagem resumida de CVEs categorizadas por gravidade.

Conformidade do ArtifactGuard : aprovado

  • Detalha os nomes das políticas.
  • Fornece apenas a contagem resumida de CVEs por gravidade.

Alto nível de detalhes (detalhado)

Fornece uma lista completa de todas as vulnerabilidades encontradas.

Conformidade do ArtifactGuard : False

  • Inclui o motivo da falha.
  • Lista as CVEs que causam a falha.
  • Fornece uma lista de todas as CVEs detectadas para a política.
  • Fornece uma contagem resumida de CVEs detalhadas por gravidade.
  • Fornece uma lista abrangente de todas as vulnerabilidades detectadas.

Conformidade do ArtifactGuard : aprovado

  • Fornece uma lista de todas as CVEs detectadas para a política.
  • Fornece uma contagem resumida de CVEs detalhadas por gravidade.
  • Fornece uma lista abrangente de todas as vulnerabilidades detectadas.

IGNORE_SERVER_ERRORS (opcional)

  • Uma flag booleana opcional. Se true, o pipeline vai continuar apesar dos erros do servidor. O padrão é false.

Iniciar uma avaliação

Durante o processo de build, uma estratégia baseada no Docker avalia a imagem em relação a políticas predefinidas. A lógica de verificação de vulnerabilidades está contida na imagem us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest.

Para iniciar uma verificação de vulnerabilidades no pipeline de CI/CD, execute o seguinte 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=$?

A integração de CI/CD propaga os códigos de saída do contêiner do Docker para o tempo de execução do Jenkins ou das ações do GitHub, que então determina o estado de aprovação ou falha do pipeline.

Desempenho e limitações

  • Avaliação de artefatos: uma imagem só é avaliada se atender aos seguintes critérios:
    • O tamanho do objeto do localizador uniforme de recursos do pacote (pURL) não pode exceder 100 MB.
    • A imagem precisa ter até 500 pURLs.
  • Até 1.200 solicitações de API por minuto (20 QPS) por projeto do consumidor para todos os métodos no serviço de proteção de artefatos.
  • SLO: a avaliação de artefatos leva cerca de dois minutos.

Solução de problemas

Esta seção descreve erros comuns e como resolvê-los.

Falhas de CreateConnector

Campo Obrigatório/opcional Restrições
name Obrigatório Formato:precisa corresponder à expressão regular [a-zA-Z0-9\\-\\s_]+$
Corresponda a um ou mais dos seguintes:
  • letras (maiúsculas e minúsculas)
  • dígitos
  • hífen -
  • espaço em branco (\s)
  • sublinhado _


Comprimento máximo:64 caracteres.
pipeline_type Obrigatório Precisa ser um dos seguintes valores de enumeração:
  • JENKINS_PIPELINE
  • GITHUB_ACTIONS
  • GOOGLE_CLOUD_BUILD
description Opcional Não pode exceder 256 caracteres.
display_name Opcional Não pode exceder 256 caracteres.

Outros erros

A tabela a seguir descreve alguns erros comuns e como resolvê-los.

Mensagem de erro Causa Ação/Resolução
Permissão artifactscanguard.connectors.create negada no recurso O usuário ou a conta de serviço não tem a permissão do IAM artifactscanguard.connectors.create no recurso (projeto, pasta ou organização). Conceda ao autor da chamada um papel do IAM que inclua a permissão artifactscanguard.connectors.create.
status.ErrFailedPrecondition A integração pode estar em andamento mesmo que o console Google Cloud mostre o serviço como ativado. Informe um problema à equipe de suporte.
status.ErrInvalidArgument Falhas na validação de campo Verifique se a solicitação CreateConnector atende às restrições especificadas.