Configura l'integrazione CI/CD

L'integrazione CI/CD connette le tue pipeline CI/CD a protezione artefatti per rilevare le vulnerabilità dei container durante la fase di build.

Lo scanner supporta GitHub Actions, Cloud Build e Jenkins. Quando viene integrato in una pipeline, valuta le immagini container in base alle policy di protezione artefatti prima che le immagini vengano inviate a un registro.

Funzionalità dello scanner

L'integrazione CI/CD viene eseguita come binario all'interno del flusso di lavoro CI/CD per svolgere le seguenti attività:

  • Valutazione delle policy in fase di compilazione: esegue la scansione delle immagini container appena create in base alle policy di protezione degli artefatti configurate.
  • Blocco delle build: restituisce codici di uscita al runner CI/CD (GitHub Actions, Cloud Build o Jenkins) per bloccare le build che violano le tue norme di sicurezza.
  • Report di scansione: invia i risultati della scansione delle vulnerabilità a Security Command Center e genera report locali in formato JSON o SARIF.

Ruoli e responsabilità target

L'integrazione CI/CD è progettata per i seguenti team:

  • Team DevOps o di ingegneria della piattaforma: crea connettori di pipeline e aggiungi passaggi di esecuzione dello scanner alle configurazioni del flusso di lavoro CI/CD.
  • Amministratori della sicurezza: definiscono i criteri per le vulnerabilità in fase di compilazione che lo scanner applica.
  • Sviluppatori di applicazioni: esamina i log di esecuzione della scansione negli output della build CI/CD per identificare e correggere le violazioni delle norme.

Termini e concetti chiave

  • Vulnerabilità ed esposizioni comuni (CVE): una vulnerabilità di sicurezza informatica divulgata pubblicamente a cui viene assegnato un identificatore univoco.
  • Software Bill of Materials (SBOM): una distinta base leggibile da macchina dei componenti software e delle dipendenze utilizzati per identificare CVE e altri rischi per la sicurezza.
  • Artefatto: nel contesto di protezione artefatti, un'immagine container creata da una pipeline CI/CD.
  • Connettore: una risorsa che collega la pipeline CI/CD a protezione artefatti. Se passato dalla pipeline CI durante una scansione, l'ID connettore determina quali policy valutano l'immagine.
  • Policy CI: una policy sulle vulnerabilità che definisce le regole specifiche per CVE, gravità e pacchetti applicate durante le build CI/CD.

Workflow di alto livello

Per configurare ed eseguire le scansioni delle vulnerabilità CI/CD, completa il seguente flusso di lavoro:

  1. Crea un connettore CI per la tua piattaforma CI/CD di destinazione.
  2. Crea un criterio di protezione degli artefatti che includa l'ID connettore nell'ambito della pipeline.
  3. Configura la pipeline CI/CD per l'autenticazione a Google Cloud, crea l'immagine container ed esegui il container scanner.

Quando la pipeline viene eseguita, lo scanner valuta l'immagine container in base alla tua policy. Se l'immagine viola le norme, lo scanner restituisce un codice di uscita di errore per impedire la creazione. Gli sviluppatori possono quindi esaminare i log di build, aggiornare le dipendenze vulnerabili ed eseguire nuovamente la build.

Prima di iniziare

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

Crea connettore

Console

Per creare un connettore nella console Google Cloud :

  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.
    • Description (Descrizione): inserisci una descrizione del connettore.
    • Piattaforma CI/CD: seleziona la piattaforma CI/CD corrispondente dall'elenco. Utilizza questo connettore solo nelle pipeline create con la piattaforma CI/CD selezionata.
  4. Fai clic su Crea.

Una notifica conferma la creazione del connettore. La tabella Connettori elenca i connettori disponibili.

gcloud CLI

Per creare un connettore utilizzando gcloud CLI, esegui questo 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]

Sostituisci quanto segue:

  • CONNECTOR_ID: un identificatore per il connettore (ad esempio, my-connector).
  • LOCATION: la posizione di Security Command Center in cui sono archiviati i dati. È supportato solo global.
  • ORGANIZATION_ID: l'ID organizzazione.
  • PROJECT_NUMBER: il numero di progetto numerico.
  • 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.

Aggiorna un connettore

Console

Per collegare una policy a un connettore nella console Google Cloud :

  1. Nella console Google Cloud , vai a Sicurezza > Impostazioni.
  2. Nella scheda protezione artefatti, fai clic su Gestisci impostazioni.
  3. Nella tabella Connettori, fai clic su accanto al connettore e seleziona Aggiungi criterio.
  4. Procedi con i passaggi per creare o aggiornare una policy di protezione artefatti. Per saperne di più, consulta Creare una policy.

gcloud CLI

Per visualizzare i connettori esistenti e aggiornare le relative associazioni di policy utilizzando gcloud CLI, utilizza i seguenti comandi:

Elenco connettori

gcloud alpha scc artifact-guard connectors list PARENT

Sostituisci quanto segue:

  • PARENT: Un'organizzazione o un progetto. I formati accettabili per la risorsa padre includono:
    • organizations/ORGANIZATION_ID/locations/LOCATION
    • projects/PROJECT_NUMBER/locations/LOCATION

Descrivere un connettore

gcloud alpha scc artifact-guard connectors describe CONNECTOR_ID \
    --location=LOCATION \
    (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)

Aggiorna l'associazione dei criteri del connettore

Per collegare un connettore a una policy, includi l'ID connettore nell'ambito della pipeline del file di definizione della policy e aggiorna la policy utilizzando il comando gcloud alpha scc artifact-guard policies update. Per saperne di più, consulta Creare una policy.

Elimina un connettore

Console

Per eliminare un connettore nella console Google Cloud :

  1. Nella console Google Cloud , vai a Sicurezza > Impostazioni.
  2. Nella scheda protezione artefatti, fai clic su Gestisci impostazioni.
  3. Nella tabella Connettori, fai clic su accanto al connettore e seleziona Elimina connettore.
  4. Segui le istruzioni di conferma per eliminare il connettore. Fai clic su Annulla per interrompere l'operazione.

gcloud CLI

Per eliminare un connettore utilizzando gcloud CLI, esegui questo comando:

gcloud alpha scc artifact-guard connectors delete CONNECTOR_ID \
    --location=LOCATION \
    (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)

Esegui una valutazione

Le pipeline GitHub Actions e Jenkins supportano l'analisi delle vulnerabilità. 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 service account

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

Devi aggiungere i secret al tuo ambiente CI/CD utilizzando uno dei seguenti metodi:

Metodo della chiave del service account

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 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@"
    
    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 su 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 secret GitHub (GCP_WORKLOAD_IDENTITY_PROVIDER).
  • Aggiungi il tuo account di servizio nel segreto GitHub (GCP_SERVICE_ACCOUNT).
  • Per informazioni su 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 su 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 delle 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 la pipeline pubblica l'immagine 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 viene superata o meno.

    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à (superata o non superata).
  • Il flag di verbosità può essere impostato su LOW o HIGH. Se non viene fornito, il valore predefinito è LOW.

Preferenze di lettura: basse (concise)

Conformità di ArtifactGuard: superata

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

Conformità di ArtifactGuard: errore

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

Preferenze di lettura: elevate (dettagliate)

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.

Conformità di ArtifactGuard: errore

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

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.

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.