SBOM memberi daftar isi, tapi siapa yang menjamin artefak itu benar-benar hasil build kalian?; di episode ini kalian memahami level SLSA v1.0, menandatangani image dengan cosign keyless via sigstore, memanfaatkan artifact attestation GitHub, dan memverifikasi signature sampai ke admission cluster dengan Kyverno

Episode lalu kita membuat setiap build punya SBOM — daftar isinya. Tapi ada pertanyaan yang lebih fundamental: bagaimana memastikan artefak yang berjalan di production benar-benar dibuat oleh pipeline kalian? Registry bisa dicompromise, tag bisa diganti, image bisa di-push manual oleh developer yang buru-buru.
Jawabannya dua hal yang saling melengkapi: SLSA (framework untuk menilai integritas proses build) dan artifact signing (jaminan kriptografi asal-usul artefak). Keduanya adalah standar de facto supply chain security 2026, dan keduanya sudah bisa dipraktikkan gratis dengan sigstore/cosign.
SLSA (Supply-chain Levels for Software Artifacts, dibaca "salsa") mendefinisikan tingkat jaminan integritas build:
| Level | Nama | Jaminan |
|---|---|---|
| Build L0 | Tidak ada jaminan | Build lokal laptop, tanpa provenance |
| Build L1 | Provenance ada | Build terdokumentasi asalnya (CI), belum tamper-proof |
| Build L2 | Hosted build platform | CI hosted + provenance ditandatangani platform |
| Build L3 | Hardened builds | Build service terisolasi, tak bisa dimodifikasi bahkan oleh maintainer repo |
Poin praktis: jika kalian build di GitHub Actions dan mengaktifkan artifact attestations, kalian sudah berada di Build L2 — provenance ditandatangani GitHub, terikat pada workflow yang menjalankannya. L3 butuh build platform hardened (misal isolated builder); jarang menjadi syarat wajib, bagus sebagai target maturity.
Perhatikan bahwa SLSA bukan sekadar "signing": intinya adalah provenance — metadata terverifikasi tentang siapa yang build, dari commit mana, pakai workflow apa. Signature tanpa provenance hanya bilang "ini ditandatangani X"; provenance membuktikan "artefak ini lahir dari pipeline yang benar".
cosign (bagian ekosistem sigstore) menandatangani container image dan menyimpan signature langsung di registry. Mode modernnya adalah keyless: identitas berasal dari OIDC (workflow kalian), sertifikat diterbitkan Fulcio, dan semua signature dicatat di transparency log Rekor — tanpa private key untuk dijaga:
cosign sign --yes myapp:${{ github.sha }}Verifikasinya dari sisi konsumen:
cosign verify \
--certificate-identity-regexp "^https://github.com/org/myapp/" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
myapp@sha256:<digest>Ini memastikan image itu ditandatangani oleh workflow repo org/myapp — bukan sekadar "ditandatangani seseorang". Perhatikan verifikasi memakai digest, bukan tag: tag adalah pointer yang bisa bergerak; digest adalah isi kriptografisnya.
Alternatif key-based tetap valid untuk lingkungan air-gapped/private — simpan key di KMS/HSM dan rotasi berkala. Trade-off utamanya: kalian kini bertanggung jawab atas lifecycle key tersebut.
GitHub menyederhanakan seluruh pola ini dengan satu action — ia menghasilkan provenance SLSA L2 + SBOM attestation sekaligus:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # kunci keyless signing
packages: write
attestations: write # izin publish attestation
steps:
- uses: actions/checkout@v4
- name: Build & push
run: |
docker build -t myapp:${{ github.sha }} .
docker push myapp:${{ github.sha }}
- uses: actions/attest-build-provenance@v1
with:
subject-name: myapp
subject-digest: sha256:${{ steps.digest.outputs.hash }}Attestation bisa diverifikasi dari CLI:
gh attestation verify oci://myapp:sha256-<digest> -R org/myappSigning tidak berguna kalau tidak ada yang memverifikasi. Titik paling kuat: admission controller cluster — tolak image tanpa signature valid sebelum pod dibuat. Dengan Kyverno:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signature
spec:
validationFailureAction: Enforce
rules:
- name: check-signature
match:
any:
- resources:
kinds: [Pod]
verifyImages:
- imageReferences:
- "registry.internal.example/*"
attestors:
- entries:
- keyless:
subject: "*@org.example.com"
issuer: "https://token.actions.githubusercontent.com"
rekor:
url: https://rekor.sigstore.devDengan policy ini aktif, image yang tidak ditandatangani oleh pipeline resmi tidak bisa berjalan di cluster sama sekali — attacker yang berhasil push image palsu ke registry tetap mentok di admission.
Warning
Aktifkan verifikasi dalam mode Audit dulu (validationFailureAction: Audit): pantau beberapa minggu apakah semua workload legit lolos, baru pindah ke Enforce. Langsung Enforce pada cluster hidup adalah cara tercepat merusak deployment massal.
Inti yang harus dibawa pulang:
Di episode 14 selanjutnya kita mundur sedikit ke awal siklus pengembangan: Threat Modeling in DevSecOps — cara menemukan desain cacat sebelum kode ditulis, framework STRIDE, diagram data flow yang bisa direview tim, dan bagaimana menjadikan threat modeling bagian hidup dari pipeline, bukan rapat tahunan. Sampai jumpa!