Supply Chain Security #

Serangan supply chain terhadap container image semakin umum — mulai dari library yang terkompromi, base image yang mengandung malware, hingga image yang dipalsukan di registry publik. Sebelum image berjalan di cluster production, ada beberapa lapisan verifikasi yang perlu dilakukan: scan vulnerability, verifikasi signature, dan policy enforcement yang mencegah image tidak dikenal masuk ke cluster.

Ancaman Supply Chain #

Vektor serangan supply chain yang umum:

1. Vulnerable base image
   FROM ubuntu:20.04  ← mungkin mengandung CVE yang belum di-patch
   → Semua image turunannya mewarisi vulnerability

2. Dependency yang dikompromis
   RUN pip install malicious-package-renamed-as-legit==1.0.0
   → Typosquatting atau compromised package di PyPI/npm/etc

3. Image yang dipalsukan di registry publik
   my-app:latest ← mungkin bukan dari source yang kamu kira
   → Tanpa signature verification, tidak ada yang bisa dipercaya

4. Build pipeline yang dikompromis
   CI/CD yang di-compromise bisa inject kode berbahaya
   sebelum atau saat image di-build

5. Registry credentials yang bocor
   → Penyerang push image berbahaya ke registry private

Image Scanning dengan Trivy #

Trivy adalah scanner vulnerability yang bisa di-integrate ke CI/CD pipeline:

# Scan image sebelum push ke registry
trivy image my-api:v2

# Output:
# my-api:v2 (debian 12.4)
# ===========================
# Total: 12 (CRITICAL: 2, HIGH: 5, MEDIUM: 3, LOW: 2)
#
# ┌──────────────────┬────────────┬──────────┬──────────────────────┐
# │    Library       │    CVE     │ Severity │     Fixed Version    │
# ├──────────────────┼────────────┼──────────┼──────────────────────┤
# │ libssl1.1        │ CVE-2023-X │ CRITICAL │ 1.1.1w               │
# │ openssl          │ CVE-2023-Y │ CRITICAL │ 3.0.8                │

# Fail build jika ada CRITICAL vulnerability
trivy image --exit-code 1 --severity CRITICAL my-api:v2

# Scan di GitHub Actions
- name: Scan image
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: my-api:${{ github.sha }}
    format: sarif
    exit-code: '1'
    severity: 'CRITICAL,HIGH'

Image Signing dengan Cosign #

Cosign memungkinkan kamu menandatangani container image sehingga cluster bisa memverifikasi bahwa image benar-benar dari pipeline yang tepercaya.

# Generate keypair
cosign generate-key-pair
# Menghasilkan: cosign.key (private) dan cosign.pub (public)

# Sign image setelah di-push ke registry (di CI/CD)
cosign sign --key cosign.key my-registry.io/my-api:v2@sha256:abc123...

# Verify signature sebelum deploy
cosign verify --key cosign.pub my-registry.io/my-api:v2

# Keyless signing dengan OIDC (GitHub Actions, tidak perlu manage key)
cosign sign --yes my-registry.io/my-api:v2
# Signature tersimpan di transparency log (Rekor)

Policy Enforcement dengan Kyverno #

Kyverno adalah admission controller yang bisa enforce berbagai policy keamanan, termasuk memastikan semua image sudah di-sign:

# Policy: tolak image dari registry tidak dikenal
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: restrict-image-registries
spec:
  validationFailureAction: Enforce     # Enforce = tolak, Audit = hanya log
  background: true
  rules:
  - name: validate-registries
    match:
      any:
      - resources:
          kinds: ["Pod"]
    validate:
      message: "Image harus dari registry resmi perusahaan"
      pattern:
        spec:
          containers:
          - image: "registry.company.com/*"
          # atau gunakan =(containers) untuk all containers including initContainers
# Policy: verifikasi image signature dengan Cosign
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  rules:
  - name: verify-cosign-signature
    match:
      any:
      - resources:
          kinds: ["Pod"]
    verifyImages:
    - imageReferences:
      - "registry.company.com/*"
      attestors:
      - count: 1
        entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
              -----END PUBLIC KEY-----              

Software Bill of Materials (SBOM) #

SBOM adalah daftar lengkap semua komponen yang ada dalam sebuah image — library, framework, dan dependencies. Ini memungkinkan audit cepat saat vulnerability baru ditemukan.

# Generate SBOM untuk image
syft my-api:v2 -o cyclonedx-json > sbom.json
# atau:
trivy image --format cyclonedx my-api:v2 > sbom.json

# Attach SBOM ke image sebagai attestation
cosign attest --key cosign.key \
  --predicate sbom.json \
  --type cyclonedx \
  my-registry.io/my-api:v2

# Cek SBOM library tertentu dari image
syft packages my-api:v2 | grep "openssl"

Private Registry dan Pull Secret #

Selalu gunakan private registry untuk image production. Jangan andalkan public registry tanpa kontrol:

# Buat pull secret
kubectl create secret docker-registry registry-credentials \
  --docker-server=registry.company.com \
  --docker-username=ci-user \
  --docker-password=<token> \
  -n production

# Gunakan di Deployment
spec:
  imagePullSecrets:
  - name: registry-credentials
  containers:
  - name: api
    image: registry.company.com/my-api:v2
# Best practice: attach pull secret ke ServiceAccount
# Semua Pod yang pakai ServiceAccount ini otomatis bisa pull
apiVersion: v1
kind: ServiceAccount
metadata:
  name: api-service-account
  namespace: production
imagePullSecrets:
- name: registry-credentials

Praktik Registry yang Aman #

1. Immutable tags
   Aktifkan immutable tag di registry (ECR, GCR, Harbor)
   → Tag yang sudah di-push tidak bisa di-overwrite
   → my-api:v2.1.0 selalu menunjuk ke image yang sama

2. Content trust dan DCR
   Enable Docker Content Trust di registry
   Atau gunakan Cosign untuk signing yang lebih modern

3. Scan otomatis di registry
   ECR, GCR, Harbor punya scan vulnerability bawaan
   Aktifkan dan set alert untuk CRITICAL findings

4. Retain policy
   Hapus image lama secara otomatis
   Hanya simpan N versi terakhir
   Image lama = surface area untuk vulnerability lama

5. Minimal base image
   Gunakan distroless atau alpine sebagai base
   FROM gcr.io/distroless/python3-debian12
   → Tidak ada shell, tidak ada package manager di image final
   → Sangat sulit bagi penyerang untuk install tools setelah masuk

Ringkasan #

  • Scan setiap image di CI sebelum push — Trivy terintegrasi dengan GitHub Actions, GitLab CI, dan semua CI/CD populer; fail build jika ada CRITICAL CVE.
  • Sign image dengan Cosign setelah build — signature membuktikan image dari pipeline yang tepercaya; cluster bisa verify sebelum menjalankan.
  • Kyverno untuk enforce image policy — blokir image dari registry tidak dikenal dan pastikan semua image sudah di-sign sebelum masuk ke cluster.
  • SBOM untuk audit dependency — daftar lengkap komponen memungkinkan identifikasi cepat saat zero-day vulnerability baru ditemukan.
  • Immutable tags di registry — tag yang tidak bisa di-overwrite memastikan my-api:v2.1.0 selalu merujuk ke image yang sama.
  • Distroless atau Alpine sebagai base image — minimal base image mengurangi attack surface; tidak ada shell dan package manager = sangat sulit dieksploitasi.

← Sebelumnya: Network Security   Berikutnya: Audit Logging →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact