AizuDemy

Tutorial Amankan CI/CD Pipeline: Sign Image Docker Pakai Cosign & Trivy

Tutorial Amankan CI/CD Pipeline: Sign Image Docker Pakai Cosign & Trivy
๐ŸŽง
Dengarkan Artikel Ini
Suara AI Otomatis โ€ข 5 mnt baca baca
โšก TL;DR

Poin Kunci Artikel Ini:

  • Ancaman Supply Chain Attack pada Container RegistrySupply chain attack targetkan proses build dan distribusi container.
  • Penyerang sisipkan malware ke image sebelum masuk produksi.
  • Trivy jalankan audit kerentanan dan buat SBOM.
๐Ÿ“‹ Daftar Isi Materi Tutup โ–ด

Ancaman Supply Chain Attack pada Container Registry

Supply chain attack targetkan proses build dan distribusi container. Penyerang sisipkan malware ke image sebelum masuk produksi. Kode sumber di repositori tetap bersih, eksploitasi terjadi di artifact registry.

Vektor serangan utama:

  • Image Tag Mutation: Penyerang timpa isi image di registry pakai tag mutabel (latest, v1.0.0). Kode jahat masuk tanpa ubah manifes deployment.
  • Compromised Dependency & Base Image: Base image tidak terverifikasi bawa kerentanan High/Critical atau backdoor.
  • CI/CD Pipeline Tampering: Kredensial runner bocor. Penyerang unggah artifact buatan langsung ke registry tanpa lewat tahap uji.

Pencegahan butuh dua langkah: validasi komponen lewat Software Bill of Materials (SBOM) dan pembuktian integritas artifact pakai tanda tangan digital. Trivy jalankan audit kerentanan dan buat SBOM. Cosign jamin integritas image lewat tanda tangan cryptographic hash sha256.

Praktek Audit SBOM Trivy dan Signing Cosign di GitHub Actions

Pengamanan pipeline butuh alur terintegrasi: pemindaian dependensi, pembuatan manifest SBOM, push image ke registry, dan penandatanganan artifact.

1. Audit Kerentanan dan Generasi SBOM dengan Trivy

Trivy memindai layer Dockerfile dan package manager (npm, pip, gomod, apk, apt). Jalankan pemindaian lokal atau CI:

# Pemindaian kerentanan image dengan threshold CRITICAL
trivy image --severity HIGH,CRITICAL --exit-code 1 my-registry.com/app:v1.0.0

# Generasi SBOM format CycloneDX JSON
trivy image --format cyclonedx --output sbom.json my-registry.com/app:v1.0.0

Opsi --exit-code 1 paksa CI/CD berhenti jika Trivy temukan kerentanan sesuai threshold.

2. Generasi Kunci dan Signing Image dengan Cosign

Cosign dukung dua metode: pasang kunci (private/public key) atau keyless (Sigstore Fulcio/Rekor OIDC). Pembuatan pasang kunci mandiri:

# Generate keypair (menghasilkan cosign.key dan cosign.pub)
cosign generate-key-pair

# Sign image container menggunakan private key
cosign sign --key cosign.key my-registry.com/app:v1.0.0@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Penandatanganan wajib pakai immutable digest SHA256, bukan tag mutabel. Mencegah race condition mutasi image.

3. Otomatisasi Pipeline Lengkap di GitHub Actions

Simpan workflow pada .github/workflows/build-secure.yml. Tambah COSIGN_PRIVATE_KEY dan COSIGN_PASSWORD di GitHub Repository Secrets.

name: Secure Build and Sign

on:
  push:
    tags:
      - 'v*'

jobs:
  build-scan-sign:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build Local Image for Scanning
        uses: docker/build-push-action@v5
        with:
          context: .
          load: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}

      - name: Run Trivy Vulnerability Scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
          format: 'table'
          exit-code: '1'
          ignore-unfixed: true
          vuln-type: 'os,library'
          severity: 'CRITICAL'

      - name: Generate SBOM with Trivy
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
          format: 'cyclonedx'
          output: 'sbom.json'

      - name: Build and Push Docker Image
        id: build-publish
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}

      - name: Install Cosign
        uses: sigstore/cosign-installer@v3.3.0

      - name: Sign Container Image
        env:
          COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
          COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
        run: |
          cosign sign --yes --key env://COSIGN_PRIVATE_KEY \
            ghcr.io/${{ github.repository }}@${{ steps.build-publish.outputs.digest }}

      - name: Attest SBOM to Image
        env:
          COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
          COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
        run: |
          cosign attest --yes --key env://COSIGN_PRIVATE_KEY \
            --type cyclonedx --predicate sbom.json \
            ghcr.io/${{ github.repository }}@${{ steps.build-publish.outputs.digest }}

Verifikasi Signature Runtime dan Troubleshooting Verification Fail

Penandatanganan tidak berguna jika runtime Kubernetes terima image tanpa validasi signature.

1. Verifikasi Manual dan Policy Enforcement

Verifikasi signature manual sebelum deploy:

cosign verify --key cosign.pub ghcr.io/user/app@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Otomatisasi di Kubernetes gunakan Kyverno Admission Controller. Kebijakan ini menolak Pod jika image tidak memiliki tanda tangan valid dari kunci publik resmi:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: verify-signature
      match:
        any:
        - resources:
            kinds:
              - Pod
      verifyImages:
        - imageReferences:
            - "ghcr.io/user/*"
          key: |
            -----BEGIN PUBLIC KEY-----
            MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
            -----END PUBLIC KEY-----

2. Troubleshooting Kegagalan Verifikasi

Penanganan error umum verifikasi Cosign:

  • Error: NO_MATCHING_SIGNATURE atau entity not found in registry
    Penyebab: Image di-push ulang tanpa signing baru, atau verifikasi pakai nama tag (:latest) yang beda digest.
    Solusi: Gunakan digest SHA256 (@sha256:...). Pastikan step signing jalan setelah step push selesai di CI/CD.
  • Error: verifying artifact: claim validation failed
    Penyebab: Kunci publik untuk verifikasi tidak cocok dengan kunci privat penanda tangan.
    Solusi: Cek pasangan kunci. Pastikan `COSIGN_PUBLIC_KEY` di target deployment cocok dengan `COSIGN_PRIVATE_KEY` di CI/CD.
  • Error: trivy exit code 1 pada Pipeline
    Penyebab: Ditemukan kerentanan CRITICAL pada base image atau package OS.
    Solusi: Update base image ke versi distroless/minimal terbaru (alpine:3.19 atau gcr.io/distroless/static-debian12). Gunakan .trivyignore hanya untuk kerentanan false-positive terverifikasi.

Ringkasan Best Practice Keamanan Pipeline Production

Terapkan 8 poin panduan praktis berikut untuk mengamankan rantai pasokan perangkat lunak container:

  1. Gunakan Immutable Digest: Selalu deploy image menggunakan image@sha256:... alih-alih tag mutabel seperti :latest.
  2. Prinsip Least Privilege CI/CD: Batasi scope GITHUB_TOKEN hanya ke packages: write dan contents: read.
  3. Keyless Signing jika Memungkinkan: Manfaatkan OIDC Cosign (Fulcio & Rekor) untuk mengeliminasi manajemen kunci privat jangka panjang.
  4. Scan Multi-Layer: Pemindaian Trivy dilakukan pada dua tahap: kode sumber/dependensi saat komit dan image akhir hasil build.
  5. Attestation SBOM Terintegrasi: Lampirkan (attest) berkas SBOM langsung ke image registry menggunakan Cosign agar audit compliance mudah dilakukan.
  6. Gunakan Base Image Minimal: Ganti base image besar (Ubuntu/Debian full) dengan Distroless atau Alpine untuk memperkecil attack surface dan jumlah CVE.
  7. Enforce Runtime Protection: Pasang admission controller (Kyverno/OPA Gatekeeper) di kluster Kubernetes untuk memblokir deployment image tanpa signature valid.
  8. Pin Action Dependencies: Kunci versi GitHub Actions menggunakan SHA commit hash, bukan versi tag (misal: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11).

Integrasi Trivy dan Cosign dalam CI/CD pipeline jadikan keamanan standar otomatis yang wajib lolos. Amankan supply chain sejak dini cegah insiden produksi. Terapkan validasi SBOM dan digital signature pada tiap proses build.

๐Ÿ“– Artikel Terkait