Integrasi CI/CD menghubungkan pipeline CI/CD Anda ke perlindungan artefak untuk mendeteksi kerentanan container selama tahap build.
Pemindai mendukung GitHub Actions, Cloud Build, dan Jenkins. Jika diintegrasikan ke dalam pipeline, alat ini akan mengevaluasi image container berdasarkan kebijakan perlindungan artefak Anda sebelum image dikirim ke registry.
Kemampuan pemindai
Integrasi CI/CD berjalan sebagai program biner dalam alur kerja CI/CD Anda untuk melakukan tugas-tugas berikut:
- Evaluasi kebijakan waktu build: Memindai image container yang baru dibuat berdasarkan kebijakan perlindungan artefak yang Anda konfigurasi.
- Pemblokiran build: Menampilkan kode keluar ke runner CI/CD Anda (GitHub Actions, Cloud Build, atau Jenkins) untuk memblokir build yang melanggar kebijakan keamanan Anda.
- Pelaporan pemindaian: Mengirimkan hasil pemindaian kerentanan ke Security Command Center dan menghasilkan laporan lokal dalam format JSON atau SARIF.
Peran dan tanggung jawab target
Integrasi CI/CD dirancang untuk tim berikut:
- Tim DevOps atau Platform Engineering: Buat konektor pipeline dan tambahkan langkah-langkah eksekusi pemindai ke konfigurasi alur kerja CI/CD.
- Administrator Keamanan: Menentukan kebijakan kerentanan waktu build yang diterapkan oleh pemindai.
- Developer Aplikasi: Tinjau log eksekusi pemindaian di output build CI/CD untuk mengidentifikasi dan memperbaiki pelanggaran kebijakan.
Istilah dan konsep utama
- Common Vulnerabilities and Exposures (CVE): Kerentanan keamanan komputer yang diungkapkan secara publik dan diberi ID unik.
- Software Bill of Materials (SBOM): Inventaris komponen dan dependensi software yang dapat dibaca mesin yang digunakan untuk mengidentifikasi CVE dan risiko keamanan lainnya.
- Artefak: Dalam konteks perlindungan artefak, image container yang dibangun oleh pipeline CI/CD.
- Konektor: Resource yang menautkan pipeline CI/CD Anda ke artifact guard. Saat diteruskan dari pipeline CI selama pemindaian, ID konektor menentukan kebijakan mana yang mengevaluasi gambar.
- Kebijakan CI: Kebijakan kerentanan yang menentukan CVE, tingkat keparahan, dan aturan paket tertentu yang diterapkan selama build CI/CD.
Alur kerja tingkat tinggi
Untuk mengonfigurasi dan menjalankan pemindaian kerentanan CI/CD, selesaikan alur kerja berikut:
- Buat konektor CI untuk platform CI/CD target Anda.
- Buat kebijakan penjaga artefak yang menyertakan ID konektor dalam cakupan pipeline-nya.
- Konfigurasi pipeline CI/CD untuk melakukan autentikasi ke Google Cloud, membangun image container, dan menjalankan container pemindai.
Saat pipeline berjalan, pemindai akan mengevaluasi image container berdasarkan kebijakan Anda. Jika gambar melanggar kebijakan, pemindai akan menampilkan kode keluar kegagalan untuk membuat build gagal. Developer kemudian dapat memeriksa log build, memperbarui dependensi yang rentan, dan menjalankan kembali build.
Sebelum memulai
Untuk menggunakan integrasi CI/CD, Anda harus mengaktifkan perlindungan artefak. Untuk mengetahui petunjuknya, lihat Sebelum Anda memulai dalam dokumentasi penjaga artefak.
Buat konektor
Konsol
Untuk membuat konektor di konsol Google Cloud , ikuti langkah-langkah berikut:
- Di konsol Google Cloud , buka Security > Settings.
- Di kartu Artifact guard, klik Kelola setelan.
- Klik Create connector dan masukkan detail berikut untuk konektor:
- ID Konektor: Tambahkan ID untuk konektor.
- Deskripsi: Masukkan deskripsi konektor.
- Platform CI/CD: Pilih platform CI/CD yang sesuai dari daftar. Gunakan konektor ini hanya di pipeline yang dibuat dengan platform CI/CD yang dipilih.
- Klik Create.
Notifikasi akan mengonfirmasi keberhasilan pembuatan konektor. Tabel Konektor mencantumkan konektor yang tersedia.
gcloud CLI
Untuk membuat konektor menggunakan gcloud CLI, jalankan perintah berikut:
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]
Ganti kode berikut:
- CONNECTOR_ID: ID untuk konektor (misalnya,
my-connector). - LOCATION: Lokasi Security Command Center tempat data Anda
disimpan. Hanya
globalyang didukung. - ORGANIZATION_ID: ID organisasi.
- PROJECT_NUMBER: Nomor project numerik.
- PIPELINE_TYPE: Jenis pipeline CI/CD. Harus berupa salah satu dari berikut:
GOOGLE_CLOUD_BUILDGITHUB_ACTIONSJENKINS_PIPELINE
- DESCRIPTION: Deskripsi teks untuk konektor.
- DISPLAY_NAME: Nama tampilan yang mudah digunakan untuk konektor.
Mengupdate konektor
Konsol
Untuk menautkan kebijakan ke konektor di konsol Google Cloud , ikuti langkah-langkah berikut:
- Di konsol Google Cloud , buka Security > Settings.
- Di kartu Artifact guard, klik Kelola setelan.
- Di tabel Konektor, klik di samping konektor, lalu pilih Tambahkan kebijakan.
- Lanjutkan langkah-langkah untuk membuat atau memperbarui kebijakan perlindungan artefak. Untuk mengetahui informasi selengkapnya, lihat Membuat kebijakan.
gcloud CLI
Untuk melihat konektor yang ada dan memperbarui asosiasi kebijakan menggunakan gcloud CLI, gunakan perintah berikut:
Mencantumkan konektor
gcloud alpha scc artifact-guard connectors list PARENT
Ganti kode berikut:
- PARENT: Organisasi atau project. Format yang dapat diterima untuk resource induk meliputi:
organizations/ORGANIZATION_ID/locations/LOCATIONprojects/PROJECT_NUMBER/locations/LOCATION
Menjelaskan konektor
gcloud alpha scc artifact-guard connectors describe CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
Memperbarui asosiasi kebijakan konektor
Untuk menautkan konektor ke kebijakan, sertakan ID konektor dalam cakupan pipeline file definisi kebijakan Anda dan perbarui kebijakan menggunakan perintah gcloud alpha scc artifact-guard policies update. Untuk mengetahui informasi selengkapnya, lihat Membuat kebijakan.
Menghapus konektor
Konsol
Untuk menghapus konektor di konsol Google Cloud , ikuti langkah-langkah berikut:
- Di konsol Google Cloud , buka Security > Settings.
- Di kartu Artifact guard, klik Kelola setelan.
- Di tabel Konektor, klik di samping konektor, lalu pilih Hapus konektor.
- Ikuti perintah konfirmasi untuk menghapus konektor. Klik Batal untuk membatalkan.
gcloud CLI
Untuk menghapus konektor menggunakan gcloud CLI, jalankan perintah berikut:
gcloud alpha scc artifact-guard connectors delete CONNECTOR_ID \ --location=LOCATION \ (--organization=ORGANIZATION_ID | --project=PROJECT_NUMBER)
Jalankan evaluasi
Pipeline GitHub Actions dan Jenkins mendukung pemindaian kerentanan. Untuk melakukan evaluasi, Anda harus melakukan hal berikut:
- Buat secret untuk autentikasi.
- Buat file template integrasi khusus untuk pipeline Anda.
- Mulai evaluasi.
Konfigurasi secret
Pipeline CI/CD yang berjalan di luar Google Cloud dapat melakukan autentikasi menggunakan kunci akun layanan atau Workload Identity Federation. Untuk mengetahui petunjuk mendetail tentang cara membuat secret, lihat artikel berikut:
Kunci akun layanan
Workload Identity Federation (untuk GitHub Actions)
Anda harus menambahkan secret ke lingkungan CI/CD menggunakan salah satu metode berikut:
Metode kunci akun layanan
Satu rahasia:
GCP_CREDENTIALS: Isi file kunci JSON akun layanan yang Anda download.
Metode Workload Identity Federation
Dua rahasia:
GCP_WORKLOAD_IDENTITY_PROVIDER: Nama lengkap resource Penyedia Workload Identity Anda. Contoh,projects/12345/locations/global/workloadIdentityPools/my-pool/providers/my-provider.GCP_SERVICE_ACCOUNT: Alamat email akun layanan yang akan di-impersonate.
Template integrasi pipeline
Untuk memicu evaluasi, Anda harus membuat file khusus untuk pipeline (Cloud Build, GitHub Actions, atau Jenkins) menggunakan contoh template berikut:
Cloud Build
Lihat Definisi variabel untuk mengetahui informasi tentang setiap kolom.
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)
Template ini ditujukan untuk GitHub Actions yang menggunakan kunci rahasia.
- Tambahkan kunci rahasia akun layanan Anda (
GCP_CREDENTIALS). Lihat Definisi variabel untuk mengetahui informasi tentang kolom tambahan.
# 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)
Template ini ditujukan untuk GitHub Actions yang menggunakan Workload Identity Federation.
- Tambahkan Penyedia Identitas Workload Anda di secret GitHub (
GCP_WORKLOAD_IDENTITY_PROVIDER). - Tambahkan Akun Layanan Anda di secret GitHub (
GCP_SERVICE_ACCOUNT). Lihat Definisi variabel untuk mengetahui informasi tentang kolom tambahan.
# 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 (rahasia)
- Tambahkan kunci rahasia akun layanan (
GCP_CREDENTIALS). Lihat Definisi variabel untuk mengetahui informasi tentang kolom tambahan.
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}" } } } }
Definisi variabel
Bagian ini memberikan informasi tentang kolom variabel yang digunakan dalam Template integrasi pipeline.
IMAGE_NAME_TO_SCAN (Wajib)
- Menentukan tag image aplikasi yang akan dibuat.
GCP_PROJECT_ID (Wajib)
- Menentukan Google Cloud Project ID yang digunakan untuk autentikasi dan konfigurasi.
AR_REPOSITORY (Opsional)
- Menentukan nama repositori Artifact Registry tempat pipeline memublikasikan image jika build berhasil.
ORGANIZATION_ID (Wajib)
- ID organisasi Google Cloud .
CONNECTOR_ID (Wajib)
- Menentukan ID konektor pipeline yang akan digunakan.
SCANNER_IMAGE (Wajib)
Image pemindai bawaan menganalisis kode, mengidentifikasi kerentanan dengan mengevaluasi image terhadap kebijakan selama build, dan menghasilkan hasil kepatuhan untuk menentukan apakah pipeline CI/CD lulus atau gagal.
Detail gambar:
us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest
VERBOSITY (Opsional)
- Pemindai mendukung tanda
VERBOSITYopsional yang mengontrol tingkat detail yang ditampilkan dalam output pemindaian. Output pemindai bervariasi berdasarkan tingkat kejelasan dan hasil kepatuhan (Lulus atau Gagal). Flag kejelasan dapat disetel ke
LOWatauHIGH. Nilai defaultnya adalahLOWjika tidak diberikan.
Panjang respons rendah (ringkas)
Kepatuhan ArtifactGuard: Lulus
- Mencantumkan nama kebijakan.
- Hanya memberikan jumlah CVE yang diringkas menurut tingkat keparahan.
Kesesuaian ArtifactGuard: Gagal
- Menjelaskan alasan kegagalan.
- Hanya mencantumkan CVE spesifik yang menyebabkan kegagalan.
- Menyediakan jumlah CVE yang diringkas dan dikategorikan berdasarkan tingkat keparahan.
Panjang respons tinggi (mendetail)
Memberikan daftar komprehensif semua kerentanan yang ditemukan.
Kepatuhan ArtifactGuard: Lulus
- Memberikan daftar semua CVE yang terdeteksi untuk kebijakan.
- Menyediakan jumlah ringkasan CVE yang dikelompokkan berdasarkan tingkat keparahan.
- Memberikan daftar lengkap semua kerentanan yang terdeteksi.
Kesesuaian ArtifactGuard: Gagal
- Mencakup alasan kegagalan.
- Mencantumkan CVE yang menyebabkan kegagalan.
- Memberikan daftar semua CVE yang terdeteksi untuk kebijakan.
- Menyediakan jumlah ringkasan CVE yang dikelompokkan berdasarkan tingkat keparahan.
- Memberikan daftar lengkap semua kerentanan yang terdeteksi.
IGNORE_SERVER_ERRORS (Opsional)
- Flag boolean opsional. Jika
true, pipeline akan berlanjut meskipun terjadi error server. Nilai defaultnya adalahfalse.
Mulai evaluasi
Selama proses build, strategi berbasis Docker mengevaluasi image berdasarkan kebijakan yang telah ditentukan sebelumnya. Logika pemindaian kerentanan terdapat dalam
us-central1-docker.pkg.dev/ci-plugin/ci-images/scc-artifactguard-scan-image:latest
image.
Untuk memulai pemindaian kerentanan di pipeline CI/CD, jalankan perintah berikut:
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=$?
Integrasi CI/CD menyebarkan kode keluar penampung Docker ke runtime Jenkins atau GitHub Actions, yang kemudian menentukan status lulus atau gagal pipeline.
Pemecahan masalah
Bagian ini menguraikan error umum beserta cara menyelesaikannya.
Kegagalan CreateConnector
| Kolom | Wajib/Opsional | Batasan |
|---|---|---|
name |
Wajib | Format: Harus cocok dengan ekspresi reguler
[a-zA-Z0-9\\-\\s_]+$ Cocokkan satu atau beberapa hal berikut:
Panjang Maksimum: 64 karakter. |
pipeline_type |
Wajib | Harus berupa salah satu nilai enum berikut:
|
description |
Opsional | Tidak boleh melebihi 256 karakter. |
display_name |
Opsional | Tidak boleh melebihi 256 karakter. |
Error lainnya
Tabel berikut menguraikan beberapa error umum dan cara mengatasinya.
| Pesan Error | Penyebab | Tindakan/Penyelesaian |
|---|---|---|
Izin artifactscanguard.connectors.create
ditolak pada resource |
Pengguna atau akun layanan tidak memiliki izin IAM artifactscanguard.connectors.create
pada resource (project, folder, atau
organisasi). |
Memberi pemanggil peran IAM yang mencakup izin artifactscanguard.connectors.create. |
status.ErrFailedPrecondition |
Proses aktivasi mungkin sedang berlangsung meskipun Google Cloud konsol menampilkan layanan sebagai diaktifkan. | Laporkan masalah kepada tim dukungan. |
status.ErrInvalidArgument |
Kegagalan validasi kolom | Pastikan permintaan CreateConnector memenuhi batasan yang ditentukan. |