Mengamankan rantai pasok software secara formal dengan SLSA: memahami level build L0-L3, menghasilkan provenance dan attestation, menandatangani artifact dengan cosign/Sigstore, serta memverifikasi di deployment bahwa image production benar-benar dibangun dari source code kalian oleh pipeline yang tepercaya

Episode 9 mengamankan dependency yang kalian konsumsi; episode ini mengamankan artifact yang kalian produksi. Pertanyaan intinya sederhana namun jarang bisa dijawab organisasi: "image yang jalan di production — benarkah dibangun dari source code di repo kita, oleh pipeline kita?" Jika build system dikompromi (SolarWinds, Codecov, event-stream), penyerang menyuntikkan kode pada jalur antara source dan deploy — tempat scanner dependency tak melihat apa pun.
Kerangkanya adalah SLSA (Supply-chain Levels for Software Artifacts): spesifikasi tingkat ketahanan build dari tampering, plus standar metadata (provenance) untuk membuktikan asal-usul artifact. Kita bedah levelnya, lalu praktik signing & verification dengan Sigstore/cosign.
Sebelum level-level, pahami titik serangannya pada jalur source → build → distribute → deploy:
| Vektor | Contoh Nyata |
|---|---|
| Dependency compromise | event-stream npm, XZ Utils backdoor (2024) |
| Build system compromise | SolarWinds build server; injection saat CI |
| Tag/repo hijack | Action GitHub berubah isi setelah tag dipinjam |
| Artifact tampering | Image di registry diganti diam-diam |
| Bypass review | Deploy langsung dari laptop developer |
Perhatikan pola: semuanya menyerang kepercayaan antar tahap. SLSA merespons persis itu — memastikan tiap transisi ada bukti kriptografi dan proses yang sulit dimanipulasi.
SLSA v1.0 menyederhanakan fokus ke Build Track — ketahanan proses build:
| Level | Jaminan | Prasyarat Kunci |
|---|---|---|
| L0 | Tidak ada jaminan | Build manual, tanpa provenance |
| L1 | Provenance ada | Hosted build (GitHub Actions) menghasilkan provenance otomatis |
| L2 | Provenance terautentikasi | Provenance ditandatangani; hosted platform terkontrol |
| L3 | Hardened builds | Build terisolasi per-job, tidak bisa saling memengaruhi; parameter tidak bisa dipalsukan |
Poin penting untuk komunikasi ke manajemen: mayoritas organisasi pakai GitHub Actions sudah otomatis mendekati L1–L2, karena platform menerbitkan provenance bertanda tangan via Sigstore. Lonjakan kerja nyata adalah L3 (runner hardened, isolasi ketat) — biasanya hanya relevan untuk target regulasi tinggi atau vendor software.
Yang praktis dari SLSA bukan sekadar klaim level, tapi tiga kontrol konkret: provenance (dibangun dari commit apa, oleh siapa), signed artifact, dan verification gate saat deploy.
Sigstore memberi signing gratis tanpa mengelola PKI sendiri: key ephemeral, identitas OIDC, transparency log (Rekor). Praktik menandai image di CI:
jobs:
sign:
permissions:
id-token: write # keyless signing butuh OIDC
packages: write
runs-on: ubuntu-latest
steps:
- uses: step-security/harden-runner@<sha> # pin SHA
- name: Login GHCR
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Install cosign
uses: sigstore/cosign-installer@<sha> # pin SHA
- name: Sign image
run: cosign sign --yes ghcr.io/org/app:${{ github.sha }}
- name: Attest provenance SLSA
run: |
cosign attest --yes --predicate provenance.json \
--type slsaprovenance ghcr.io/org/app:${{ github.sha }}Dua artefak yang lahir: signature (siapa yang menandai, kapan) dan attestation (klaim terstruktur: builder apa, source commit apa). Verifikasinya:
cosign verify ghcr.io/org/app:9f86d081... \
--certificate-identity-regexp "^https://github.com/org/.+" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
# Cek attestation provenance
cosign verify-attestation ghcr.io/org/app:9f86d081... \
--type slsaprovenancePerhatikan verifikasi mengikat ke identitas workflow (certificate-identity) — artinya hanya build dari repo organisasi yang sah, bukan sekadar "ada signature".
Signing tanpa enforcement = tinta di air. Nilainya muncul saat cluster/deployer menolak artifact tanpa signature valid. Di Kubernetes, policy controller (Kyverno atau Cosign-based admission):
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signature
spec:
validationFailureAction: Enforce
webhookTimeoutSeconds: 30
rules:
- name: check-signature
match:
resources: { kinds: [Pod], namespaces: [production] }
verifyImages:
- imageReferences: ["ghcr.io/org/*"]
attestors:
- entries:
- keyless:
subjectRegExp: "^https://github.com/org/.+"
issuer: https://token.actions.githubusercontent.comEfek operasionalnya: penyerang yang berhasil mendorong image palsu ke registry tetap gagal karena cluster menolak pod tanpa signature dari identity workflow yang benar. Ini pertahanan terakhir yang bekerja meski semua lapis sebelumnya bolong — semangat defense in depth episode 0.
Tip
Urutan rollout yang aman: audit mode dulu (laporkan pod unsigned selama dua minggu), perbaiki semua pipeline yang belum sign, baru Enforce di namespace production. Enforce langsung = outage pagi Senin.
SLSA juga menuntut input build tak bisa dimanipulasi — rekap dan tambahan dari episode 11:
.github/workflows/** — perubahan pipeline butuh review seperti kode produksi.Inti yang harus dibawa pulang:
Di episode 24 kita masuk sisi organisasional yang menentukan skala program kalian: Security Champions Program — membangun jaringan champion di tiap tim product engineering, merancang training path mereka, dan menjadikan security sebagai tanggung jawab bersama tanpa menambah headcount security. Sampai jumpa di episode 24!