Configura l'integrazione CI/CD

Per i clienti di Security Command Center può essere difficile ottenere una visualizzazione centralizzata e completa dei risultati della scansione dai loro ambienti di integrazione continua/deployment continuo (CI/CD). Questa mancanza di una visualizzazione unificata complica la gestione delle vulnerabilità. L'integrazione CI/CD è un componente di protezione artefatti (anteprima) che ti consente di connettere più pipeline CI/CD per rilevare le vulnerabilità durante l'intero ciclo di vita dello sviluppo software.

L'integrazione CI/CD supporta GitHub Actions, Cloud Build e Jenkins. Una volta connesso, puoi utilizzare una qualsiasi di queste piattaforme CI/CD per configurare le policy di protezione artefatti, fornendo visibilità e controllo proattivo sul tuo security posture.

Panoramica

L'integrazione CI/CD offre quanto segue:

  • Applicazione end-to-end delle policy: aiuta la protezione artefatti ad applicare policy di sicurezza coerenti dal codice al cloud.
  • Rilevamento completo delle minacce: esegue la scansione per rilevare vulnerabilità, segreti esposti, licenze problematiche e pacchetti dannosi.
  • Ampia compatibilità CI/CD: funziona con Jenkins e GitHub Actions.
  • Ottimizzato per CI/CD: un file binario leggero garantisce un funzionamento efficiente negli ambienti locali.
  • Output flessibile: fornisce i risultati nei formati JSON e SARIF standard del settore.
  • Approfondimenti centralizzati sulla sicurezza: fornisce visualizzazioni chiare della conformità alle norme direttamente nella dashboard per la sicurezza.

Questo scanner compila in modo nativo Security Command Center, fornendo una visualizzazione unificata e incentrata sugli asset dei risultati di sicurezza dalla creazione degli artefatti.

L'integrazione CI/CD ti aiuta a applicare le norme di protezione artefatti durante tutto il ciclo di vita del software. In questo modo, gli artefatti vengono convalidati per la conformità dalla build al deployment.

Pubblico

L'integrazione CI/CD può aiutarti con le seguenti attività degli stakeholder:

  • Utenti principali: team DevOps e di progettazione di piattaforme
    • Gestione e integrazione: responsabile della gestione dello strumento di scansione e della sua integrazione diretta nelle pipeline CI/CD.
    • Configura le policy: configura i passaggi di scansione.
    • Monitorare la conformità: monitora la conformità delle build e collabora con gli amministratori della sicurezza per perfezionare i criteri.
  • Utenti secondari: amministratori della sicurezza
    • Autori delle policy: definiscono e applicano le policy di sicurezza in base alla criticità aziendale.
    • Automatizza l'applicazione: automatizza la sicurezza all'interno di CI/CD per ridurre il rumore delle vulnerabilità e impostare i criteri di gating.
    • Fornire supervisione: collabora con DevOps e offri una dashboard per consentire al management di monitorare le vulnerabilità controllate.
  • Utenti secondari: sviluppatori di applicazioni
    • Esamina e correggi: interagisci con i risultati della valutazione delle norme, esamina i risultati della build e correggi i problemi di sicurezza segnalati.
    • Valuta: avvia la valutazione dei criteri indirettamente tramite il processo di compilazione della pipeline CI.
    • Mantieni la conformità: garantisci la conformità ai requisiti di sicurezza senza interrompere i workflow di sviluppo.

Termini e concetti chiave

  • Vulnerabilità ed esposizioni comuni (CVE): una vulnerabilità di sicurezza informatica divulgata pubblicamente a cui viene assegnato un identificatore univoco. Questi identificatori aiutano a monitorare le vulnerabilità per la correzione.
  • Software Bill of Materials (SBOM): una distinta base leggibile da una macchina di componenti software e dipendenze. Una SBOM include informazioni su versione, origine e altri dettagli pertinenti di ogni componente. Le SBOM possono essere utilizzate per identificare CVE e altri rischi per la sicurezza.
  • Artefatto: un output con controllo delle versioni e convalidato dello sviluppo software, ad esempio dati o un elemento creato durante il processo di compilazione.
  • Connettore: un tag per le immagini. Quando viene passato dalla pipeline CI al servizio Protezione artefatti, un connettore determina quali criteri eseguire sull'immagine in fase di creazione.
  • Policy CI: una policy sulle vulnerabilità che definisce regole o criteri per controllare quali vulnerabilità e pacchetti sono consentiti nel tuo ambiente.

Workflow di alto livello

  1. Crea connettori CI.
  2. Crea policy di protezione artefatti utilizzando i connettori configurati nel passaggio precedente per definire l'ambito della policy.
  3. Avviare le valutazioni degli artefatti.

Durante una valutazione, un'immagine viene creata e valutata in base a criteri predefiniti. Se le policy non vengono rispettate, la build non viene creata. Gli ingegneri DevOps o delle applicazioni devono quindi esaminare i dettagli dell'errore per trovare la vulnerabilità specifica, aggiornare la dipendenza in base ai dettagli della CVE e rieseguire la pipeline.

Prima di iniziare

Per utilizzare l'integrazione CI/CD, devi abilitare la protezione artefatti. Per istruzioni, vedi Prima di iniziare nella documentazione di Protezione artefatti.

Dopodiché, puoi creare connettori nella consoleGoogle Cloud o utilizzando Google Cloud CLI.

Crea un connettore nella console Google Cloud

Per creare un connettore:

  1. Nella console Google Cloud , vai a Sicurezza > Impostazioni.

  2. Nella scheda protezione artefatti, fai clic su Gestisci impostazioni.

  3. Fai clic su Crea connettore e inserisci i seguenti dettagli per il connettore:

    • ID connettore: aggiungi un ID per il connettore.
    • Descrizione: inserisci una descrizione del connettore.
    • Piattaforma CI/CD: seleziona la piattaforma CI/CD corrispondente dall'elenco. Questo connettore deve essere utilizzato solo nelle pipeline create con la piattaforma CI/CD fornita.
  4. Fai clic su Crea.

Una notifica conferma la creazione del connettore. I connettori disponibili sono elencati nella tabella Connettori.

Per rimuovere un connettore, fai clic su accanto al connettore e seleziona Elimina connettore, poi segui le istruzioni. Fai clic su Annulla per interrompere.

Per collegare una policy a un connettore, fai clic su accanto al connettore e seleziona Aggiungi policy. Procedi con i passaggi per creare una policy di protezione artefatti. Per saperne di più, consulta Creare una policy.

Crea un connettore utilizzando Google Cloud CLI

Questa sezione descrive i comandi gcloud CLI disponibili per la scansione degli artefatti CI/CD e come utilizzarli.

Prerequisiti di Google Cloud CLI

  • Assicurati che la versione di gcloud CLI sia 559.0.0 o successive.
  • Imposta il progetto come progetto di configurazione.

Per farlo, esegui i seguenti comandi gcloud CLI:

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

Comandi 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: l'ID del connettore da creare.
  • PIPELINE_TYPE: il tipo di pipeline CI/CD. Deve essere uno dei seguenti:
    • GOOGLE_CLOUD_BUILD
    • GITHUB_ACTIONS
    • JENKINS_PIPELINE
  • DESCRIPTION: una descrizione testuale del connettore.
  • DISPLAY_NAME: un nome visualizzato facile da usare per il connettore.

get

gcloud alpha scc artifact-guard connectors describe CONNECTOR_ID \
    --location=LOCATION \
    (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
  • CONNECTOR_ID: l'ID del connettore da descrivere.

list

gcloud alpha scc artifact-guard connectors list PARENT
  • PARENT: Un'organizzazione o un progetto. I formati accettati per la risorsa padre includono:
    • {organizations/ORGANIZATION_ID/locations/LOCATION}
    • {projects/PROJECT_NUMBER/locations/LOCATION}

elimina

gcloud alpha scc artifact-guard connectors delete CONNECTOR_ID \
    --location=LOCATION \
    (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
  • CONNECTOR_ID: l'ID del connettore da eliminare.

Esegui una valutazione

L'analisi delle vulnerabilità è supportata per le pipeline GitHub Actions e Jenkins. Per eseguire una valutazione, devi:

  1. Crea secret per l'autenticazione.
  2. Crea un file modello di integrazione specifico per la tua pipeline.
  3. Avvia una valutazione.

Configurazione del secret

Le pipeline CI/CD in esecuzione al di fuori di Google Cloud possono autenticarsi utilizzando le chiavi account di servizio o la federazione delle identità per i workload. Per istruzioni dettagliate sulla creazione dei secret, consulta quanto segue:

Chiavi dell'account di servizio

Federazione delle identità per i workload (per GitHub Actions)

Devi aggiungere i secret all'ambiente CI/CD utilizzando uno dei seguenti metodi:

Metodo della chiave dell'account di servizio

Un segreto:

  • GCP_CREDENTIALS: i contenuti del file della chiave JSON del account di servizio scaricato.

Metodo di federazione delle identità per i workload

Due segreti:

  • GCP_WORKLOAD_IDENTITY_PROVIDER: il nome completo della risorsa del tuo provider di identità del workload. Ad esempio, projects/12345/locations/global/workloadIdentityPools/my-pool/providers/my-provider.

  • GCP_SERVICE_ACCOUNT: l'indirizzo email del service account da rappresentare.

Modelli di integrazione delle pipeline

Per attivare una valutazione, devi creare un file specifico per la tua pipeline (Cloud Build, GitHub Actions o Jenkins) utilizzando i seguenti esempi di modelli:

Cloud Build

  • Per informazioni su ciascun campo, consulta Definizioni delle variabili.

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

Questo modello è per GitHub Actions che utilizza una chiave segreta.

  • Aggiungi la chiave segreta del account di servizio (GCP_CREDENTIALS).
  • Per informazioni sui campi aggiuntivi, consulta Definizioni delle variabili.

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

Questo modello è per GitHub Actions che utilizza la federazione delle identità per i workload.

  • Aggiungi il tuo provider di identità del workload nel segreto GitHub (GCP_WORKLOAD_IDENTITY_PROVIDER).
  • Aggiungi il tuo account di servizio nel segreto GitHub (GCP_SERVICE_ACCOUNT).
  • Per informazioni sui campi aggiuntivi, consulta Definizioni delle variabili.

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

  • Aggiungi la chiave segreta del account di servizio (GCP_CREDENTIALS).
  • Per informazioni sui campi aggiuntivi, consulta Definizioni delle variabili.

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

Definizioni delle variabili

Questa sezione fornisce informazioni sui campi variabili utilizzati nei modelli di integrazione della pipeline.

IMAGE_NAME_TO_SCAN (obbligatorio)

  • Specifica il tag dell'immagine dell'applicazione da creare.

GCP_PROJECT_ID (obbligatorio)

  • Specifica l' Google Cloud ID progetto utilizzato per l'autenticazione e la configurazione.

AR_REPOSITORY (facoltativo)

  • Specifica il nome del repository Artifact Registry in cui l'immagine verrà pubblicata se la build ha esito positivo.

ORGANIZATION_ID (obbligatorio)

  • L'ID organizzazione Google Cloud .

CONNECTOR_ID (obbligatorio)

  • Specifica l'ID connettore della pipeline da utilizzare.

SCANNER_IMAGE (obbligatorio)

  • L'immagine dello scanner predefinita analizza il codice, identifica le vulnerabilità valutando le immagini rispetto ai criteri durante la build e produce un risultato di conformità per determinare se la pipeline CI/CD supera o meno il test.

    Dettagli dell'immagine: us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest

VERBOSITY (facoltativo)

  • Lo scanner supporta un flag VERBOSITY facoltativo che controlla il livello di dettaglio visualizzato nell'output della scansione. L'output dello scanner varia in base al livello di verbosità e al risultato di conformità (superato o non superato).
  • Il flag di verbosità può essere impostato su LOW o HIGH. Se non viene fornito, il valore predefinito è LOW.

Livello di dettaglio basso (conciso)

ArtifactGuard Conformance : False

  • Specifica il motivo dell'errore.
  • Elenca solo le CVE specifiche che hanno causato l'errore.
  • Fornisce un conteggio riepilogativo delle CVE classificate per gravità.

Conformità di ArtifactGuard : superata

  • Specifica i nomi delle policy.
  • Fornisce solo il conteggio riepilogativo delle CVE per gravità.

Livello di dettaglio elevato

Fornisce un elenco completo di tutte le vulnerabilità rilevate.

ArtifactGuard Conformance : False

  • Include il motivo dell'errore.
  • Elenca le CVE che causano l'errore.
  • Fornisce un elenco di tutte le CVE rilevate per la policy.
  • Fornisce un conteggio riepilogativo delle CVE suddivise per gravità.
  • Fornisce un elenco completo di tutte le vulnerabilità rilevate.

Conformità di ArtifactGuard : superata

  • Fornisce un elenco di tutte le CVE rilevate per la policy.
  • Fornisce un conteggio riepilogativo delle CVE suddivise per gravità.
  • Fornisce un elenco completo di tutte le vulnerabilità rilevate.

IGNORE_SERVER_ERRORS (facoltativo)

  • Un flag booleano facoltativo. Se true, la pipeline continua nonostante gli errori del server. Il valore predefinito è false.

Avviare una valutazione

Durante il processo di compilazione, una strategia basata su Docker valuta l'immagine in base a policy predefinite. La logica di analisi delle vulnerabilità è contenuta nell'immagine us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest.

Per avviare una scansione delle vulnerabilità nella pipeline CI/CD, esegui questo 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=$?

L'integrazione CI/CD propaga i codici di uscita del container Docker all'ambiente di runtime Jenkins o GitHub Actions, che determina lo stato di superamento o errore della pipeline.

Prestazioni e limitazioni

  • Valutazione degli artefatti: un'immagine viene valutata solo se soddisfa i seguenti criteri:
    • La dimensione dell'oggetto Package Uniform Resource Locator (pURL) non può superare 100 MB.
    • L'immagine deve contenere al massimo 500 pURL.
  • Fino a 1200 richieste API al minuto (20 QPS) per progetto consumer per tutti i metodi all'interno del servizio Protezione artefatti.
  • SLO: la valutazione dell'artefatto richiede circa due minuti.

Risoluzione dei problemi

Questa sezione descrive gli errori comuni e come risolverli.

Errori CreateConnector

Campo Obbligatorio/Facoltativo Vincoli
name Obbligatorio Formato:deve corrispondere all'espressione regolare [a-zA-Z0-9\\-\\s_]+$
Corrispondere a uno o più dei seguenti elementi:
  • lettere (maiuscole o minuscole)
  • cifre
  • trattino -
  • spazio vuoto (\s)
  • trattino basso _


Lunghezza massima:64 caratteri.
pipeline_type Obbligatorio Deve essere uno dei seguenti valori enum:
  • JENKINS_PIPELINE
  • GITHUB_ACTIONS
  • GOOGLE_CLOUD_BUILD
description Facoltativo Non deve superare i 256 caratteri.
display_name Facoltativo Non deve superare i 256 caratteri.

Altri errori

La seguente tabella descrive alcuni errori comuni e come risolverli.

Messaggio di errore Causa Azione/Risoluzione
Autorizzazione artifactscanguard.connectors.create negata per la risorsa L'utente o il account di servizio non dispone dell'autorizzazione IAM artifactscanguard.connectors.create per la risorsa (progetto, cartella o organizzazione). Concedi al chiamante un ruolo IAM che includa l'autorizzazione artifactscanguard.connectors.create.
status.ErrFailedPrecondition L'onboarding potrebbe essere in corso anche se la Google Cloud console mostra il servizio come abilitato. Segnala un problema al team di assistenza.
status.ErrInvalidArgument Errori di convalida dei campi Assicurati che la richiesta CreateConnector soddisfi i vincoli specificati.