L'intégration CI/CD connecte vos pipelines CI/CD à Artifact Guard pour détecter les failles des conteneurs lors de la phase de compilation.
Le scanner est compatible avec GitHub Actions, Cloud Build et Jenkins. Lorsqu'il est intégré à un pipeline, il évalue les images de conteneurs par rapport à vos règles Artifact Guard avant que les images ne soient transférées vers un registre.
Fonctionnalités du scanner
L'intégration CI/CD s'exécute en tant que binaire dans votre workflow CI/CD pour effectuer les tâches suivantes :
- Évaluation des règles au moment de la compilation : analyse les images de conteneurs nouvellement créées par rapport aux règles Artifact Guard que vous avez configurées.
- Blocage de la compilation : renvoie des codes de sortie à votre runner CI/CD (GitHub Actions, Cloud Build ou Jenkins) pour bloquer les compilations qui enfreignent vos règles de sécurité.
- Rapports d'analyse : envoie les résultats de l'analyse des failles à Security Command Center et génère des rapports locaux aux formats JSON ou SARIF.
Rôles et responsabilités cibles
L'intégration CI/CD est conçue pour les équipes suivantes :
- Équipes DevOps ou d'ingénierie de plate-forme : créez des connecteurs de pipeline et ajoutez des étapes d'exécution du scanner aux configurations de workflow CI/CD.
- Administrateurs de la sécurité : définissez les règles de failles au moment de la compilation que l'outil d'analyse applique.
- Développeurs d'applications : examinez les journaux d'exécution des analyses dans les sorties de compilation CI/CD pour identifier et corriger les cas de non-respect des règles.
Termes et concepts clés
- CVE (Common Vulnerabilities and Exposures) : faille de sécurité informatique divulguée publiquement et à laquelle est attribué un identifiant unique.
- Nomenclature logicielle (SBOM, software bill of materials) : inventaire lisible par machine des composants logiciels et des dépendances utilisés pour identifier les CVE et autres risques de sécurité.
- Artefact : dans le contexte d'Artifact Guard, il s'agit d'une image de conteneur créée par un pipeline CI/CD.
- Connecteur : ressource qui associe votre pipeline CI/CD à Artifact Guard. Lorsqu'il est transmis par le pipeline CI lors d'une analyse, l'ID du connecteur détermine les règles qui évaluent l'image.
- Règle CI : règle de sécurité définissant les règles spécifiques aux CVE, à la gravité et aux packages appliquées lors des compilations CI/CD.
Workflow général
Pour configurer et exécuter des analyses des failles CI/CD, suivez le workflow suivant :
- Créez un connecteur CI pour votre plate-forme CI/CD cible.
- Créez une règle Artifact Guard qui inclut l'ID du connecteur dans son champ d'application de pipeline.
- Configurez votre pipeline CI/CD pour qu'il s'authentifie auprès deGoogle Cloud, crée l'image de conteneur et exécute le conteneur du scanner.
Lorsque le pipeline s'exécute, le scanner évalue l'image de conteneur par rapport à votre règle. Si l'image ne respecte pas les règles, le scanner renvoie un code de sortie d'échec pour faire échouer la compilation. Les développeurs peuvent ensuite inspecter les journaux de compilation, mettre à jour les dépendances vulnérables et relancer la compilation.
Avant de commencer
Pour utiliser l'intégration CI/CD, vous devez activer Artifact Guard. Pour obtenir des instructions, consultez la section Avant de commencer de la documentation Artifact Guard.
Créer un connecteur
Console
Pour créer un connecteur dans la console Google Cloud , procédez comme suit :
- Dans la console Google Cloud , accédez à Sécurité > Paramètres.
- Sur la fiche Protection contre les artefacts, cliquez sur Gérer les paramètres.
- Cliquez sur Créer un connecteur et saisissez les informations suivantes pour le connecteur :
- ID du connecteur : ajoutez un ID pour le connecteur.
- Description : saisissez une description du connecteur.
- Plate-forme CI/CD : sélectionnez la plate-forme CI/CD correspondante dans la liste. Utilisez ce connecteur uniquement dans les pipelines créés avec la plate-forme CI/CD sélectionnée.
- Cliquez sur Créer.
Une notification confirme que le connecteur a bien été créé. Le tableau Connecteurs liste les connecteurs disponibles.
gcloud CLI
Pour créer un connecteur à l'aide de gcloud CLI, exécutez la commande suivante :
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]
Remplacez les éléments suivants :
- CONNECTOR_ID : identifiant du connecteur (par exemple,
my-connector). - LOCATION : emplacement Security Command Center où vos données sont stockées. Seule la région
globalest compatible. - ORGANIZATION_ID : ID de l'organisation.
- PROJECT_NUMBER : numéro du projet.
- PIPELINE_TYPE : type de pipeline CI/CD. Il doit s'agir de l'une des options suivantes :
GOOGLE_CLOUD_BUILDGITHUB_ACTIONSJENKINS_PIPELINE
- DESCRIPTION : description textuelle du connecteur.
- DISPLAY_NAME : nom à afficher convivial pour le connecteur.
Mettre à jour un connecteur
Console
Pour associer une règle à un connecteur dans la console Google Cloud , procédez comme suit :
- Dans la console Google Cloud , accédez à Sécurité > Paramètres.
- Sur la fiche Protection contre les artefacts, cliquez sur Gérer les paramètres.
- Dans le tableau Connecteurs, cliquez sur à côté du connecteur, puis sélectionnez Ajouter une règle.
- Suivez les étapes pour créer ou mettre à jour une règle Artifact Guard. Pour en savoir plus, consultez Créer une règle.
gcloud CLI
Pour afficher les connecteurs existants et mettre à jour leurs associations de règles à l'aide de la gcloud CLI, utilisez les commandes suivantes :
Répertorier les connecteurs
gcloud alpha scc artifact-guard connectors list PARENT
Remplacez les éléments suivants :
- PARENT : une organisation ou un projet. Voici les formats acceptés pour la ressource parente :
organizations/ORGANIZATION_ID/locations/LOCATIONprojects/PROJECT_NUMBER/locations/LOCATION
Décrire un connecteur
gcloud alpha scc artifact-guard connectors describe CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
Mettre à jour l'association de règles de connecteur
Pour associer un connecteur à une règle, incluez l'ID du connecteur dans le champ d'application du pipeline de votre fichier de définition de règle, puis mettez à jour la règle à l'aide de la commande gcloud alpha scc artifact-guard policies update. Pour en savoir plus, consultez Créer une règle.
Supprimer un connecteur
Console
Pour supprimer un connecteur dans la console Google Cloud , procédez comme suit :
- Dans la console Google Cloud , accédez à Sécurité > Paramètres.
- Sur la fiche Protection contre les artefacts, cliquez sur Gérer les paramètres.
- Dans le tableau Connecteurs, cliquez sur à côté du connecteur, puis sélectionnez Supprimer le connecteur.
- Suivez les instructions de confirmation pour supprimer le connecteur. Cliquez sur Annuler pour annuler.
gcloud CLI
Pour supprimer un connecteur à l'aide de la gcloud CLI, exécutez la commande suivante :
gcloud alpha scc artifact-guard connectors delete CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
Exécuter une évaluation
Les pipelines GitHub Actions et Jenkins sont compatibles avec l'analyse des failles. Pour effectuer une évaluation, vous devez procéder comme suit :
- Créez des secrets pour l'authentification.
- Créez un fichier de modèle d'intégration spécifique à votre pipeline.
- Lancez une évaluation.
Configuration des secrets
Les pipelines CI/CD exécutés en dehors de Google Cloud peuvent s'authentifier à l'aide de clés de compte de service ou de la fédération d'identité de charge de travail. Pour obtenir des instructions détaillées sur la création de secrets, consultez les pages suivantes :
Clés de compte de service
Fédération d'identité de charge de travail (pour GitHub Actions)
Vous devez ajouter des secrets à votre environnement CI/CD à l'aide de l'une des méthodes suivantes :
Méthode de la clé de compte de service
Un secret :
GCP_CREDENTIALS: contenu du fichier JSON de clé de compte de service que vous avez téléchargé.
Méthode de fédération d'identité de charge de travail
Deux secrets :
GCP_WORKLOAD_IDENTITY_PROVIDER: nom complet de la ressource de votre fournisseur d'identité de charge de travail. Exemple :projects/12345/locations/global/workloadIdentityPools/my-pool/providers/my-providerGCP_SERVICE_ACCOUNT: adresse e-mail du compte de service dont l'identité doit être empruntée.
Modèles d'intégration de pipeline
Pour déclencher une évaluation, vous devez créer un fichier spécifique à votre pipeline (Cloud Build, GitHub Actions ou Jenkins) à l'aide des exemples de modèles suivants :
Cloud Build
Pour en savoir plus sur chaque champ, consultez Définitions des variables.
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)
Ce modèle est destiné aux actions GitHub utilisant une clé secrète.
- Ajoutez la clé secrète de votre compte de service (
GCP_CREDENTIALS). Pour en savoir plus sur les autres champs, consultez Définitions des variables.
# 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)
Ce modèle est destiné aux actions GitHub utilisant la fédération d'identité de charge de travail.
- Ajoutez votre fournisseur d'identité de charge de travail au secret GitHub (
GCP_WORKLOAD_IDENTITY_PROVIDER). - Ajoutez votre compte de service au secret GitHub (
GCP_SERVICE_ACCOUNT). Pour en savoir plus sur les autres champs, consultez Définitions des variables.
# 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)
- Ajoutez la clé secrète du compte de service (
GCP_CREDENTIALS). Pour en savoir plus sur les autres champs, consultez Définitions des variables.
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}" } } } }
Définitions des variables
Cette section fournit des informations sur les champs de variables utilisés dans les modèles d'intégration de pipelines.
IMAGE_NAME_TO_SCAN (obligatoire)
- Spécifie le tag de l'image d'application à créer.
GCP_PROJECT_ID (obligatoire)
- Spécifie l'ID du projet Google Cloud utilisé pour l'authentification et la configuration.
AR_REPOSITORY (facultatif)
- Indique le nom du dépôt Artifact Registry dans lequel le pipeline publie l'image si la compilation réussit.
ORGANIZATION_ID (obligatoire)
- ID de l'organisation Google Cloud .
CONNECTOR_ID (obligatoire)
- Spécifie l'ID de connecteur du pipeline à utiliser.
SCANNER_IMAGE (obligatoire)
L'image du scanner prédéfini analyse le code, identifie les failles en évaluant les images par rapport aux règles lors de la compilation et produit un résultat de conformité pour déterminer si le pipeline CI/CD réussit ou échoue.
Détails de l'image :
us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest
VERBOSITY (facultatif)
- Le scanner est compatible avec un indicateur
VERBOSITYfacultatif qui contrôle le niveau de détail affiché dans le résultat de l'analyse. La sortie du scanner varie en fonction du niveau de détail et du résultat de conformité (réussite ou échec). L'option de verbosité peut être définie sur
LOWouHIGH. Si aucune valeur n'est indiquée, la valeur par défaut estLOW.
Niveau de détail faible (concis)
Conformité ArtifactGuard : réussite
- Détaille les noms des règles.
- Fournit uniquement le nombre récapitulatif de CVE par niveau de gravité.
Conformité ArtifactGuard : échec
- Indique la raison de l'échec.
- Liste uniquement les CVE spécifiques qui ont provoqué l'échec.
- Fournit un récapitulatif du nombre de CVE classées par niveau de gravité.
Niveau de détail élevé
Fournit une liste complète de toutes les failles détectées.
Conformité ArtifactGuard : réussite
- Fournit la liste de toutes les CVE détectées pour la règle.
- Fournit un récapitulatif du nombre de CVE par niveau de gravité.
- Fournit une liste complète de toutes les failles détectées.
Conformité ArtifactGuard : échec
- Indique la raison de l'échec.
- Liste les CVE à l'origine de l'échec.
- Fournit la liste de toutes les CVE détectées pour la règle.
- Fournit un récapitulatif du nombre de CVE par niveau de gravité.
- Fournit une liste complète de toutes les failles détectées.
IGNORE_SERVER_ERRORS (facultatif)
- Option booléenne facultative. Si la valeur est
true, le pipeline se poursuit malgré les erreurs de serveur. La valeur par défaut estfalse.
Lancer une évaluation
Lors du processus de compilation, une stratégie basée sur Docker évalue l'image par rapport à des règles prédéfinies. La logique d'analyse des failles est contenue dans l'image us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest.
Pour lancer une analyse des failles dans votre pipeline CI/CD, exécutez la commande suivante :
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'intégration CI/CD propage les codes de sortie du conteneur Docker à l'environnement d'exécution Jenkins ou GitHub Actions, qui détermine ensuite l'état de réussite ou d'échec du pipeline.
Dépannage
Cette section décrit les erreurs courantes et explique comment les résoudre.
Échecs CreateConnector
| Champ | Obligatoire/Facultatif | Contraintes |
|---|---|---|
name |
Obligatoire | Format : doit correspondre à l'expression régulière
[a-zA-Z0-9\\-\\s_]+$ Correspond à un ou plusieurs des éléments suivants :
Longueur maximale : 64 caractères. |
pipeline_type |
Obligatoire | Doit correspondre à l'une des valeurs d'énumération suivantes :
|
description |
Facultatif | Ne doit pas dépasser 256 caractères. |
display_name |
Facultatif | Ne doit pas dépasser 256 caractères. |
Autres erreurs
Le tableau suivant présente certaines erreurs courantes et explique comment les résoudre.
| Message d'erreur | Cause | Action/Résolution |
|---|---|---|
Autorisation artifactscanguard.connectors.create refusée pour la ressource |
L'utilisateur ou le compte de service ne dispose pas de l'autorisation IAM artifactscanguard.connectors.create sur la ressource (projet, dossier ou organisation). |
Attribuez à l'appelant un rôle IAM qui inclut l'autorisation artifactscanguard.connectors.create. |
status.ErrFailedPrecondition |
L'intégration peut être en cours même si la console Google Cloud indique que le service est activé. | Signalez un problème à l'équipe d'assistance. |
status.ErrInvalidArgument |
Échecs de validation des champs | Assurez-vous que la requête CreateConnector respecte les contraintes spécifiées. |