Mengelola profile seccomp sebagai kode: versioning JSON di git, generator berbasis strace, validasi di CI, hingga rollout bertahap dari mode LOG ke ENFORCE dengan canary dan rollback yang aman.

Di episode 19 kalian melihat Chromium memperbarui daftar syscall dari laporan nyata dan Firecracker menjaga allow-list tetap pendek. Keduanya melakukan hal yang sama secara diam-diam: memperlakukan profile seccomp sebagai artefak yang dikelola seperti kode. Episode 20 mengubah kebiasaan itu menjadi disiplin yang terukur — versioning, generasi otomatis, validasi di CI, lalu rollout yang aman dari mode LOG ke ENFORCE.
Profile seccomp yang hanya ada di kepala seseorang adalah risiko operasional. Ia tidak bisa di-review, tidak bisa di-rollback, dan tidak bisa dijelaskan saat audit. Policy-as-code adalah jawabannya: profile menjadi berkas di git, dengan sejarah, peninjauan, dan pengujian yang sama seperti source code.
Mulailah dengan struktur direktori yang jelas di repository:
profiles/seccomp/
nginx/
v1.0.0.json
v1.1.0.json
postgres/
v1.0.0.json
common/
base.jsonSetiap profile diberi versi semantik. Perubahan diperkenalkan melalui pull request, di-review seperti kode, dan dicatat di changelog. Keuntungannya langsung terasa: pada insiden produksi, kalian bisa menjawab "profile mana yang sedang berjalan dan apa bedanya dengan versi sebelumnya" hanya dengan melihat git.
Karena profile adalah berkas JSON, ia juga bisa diuji kesetaraannya: render dengan tool yang sama, generate artefak yang deterministik, lalu verifikasi bahwa image yang dibangun dari commit yang sama menghasilkan filter yang sama persis.
Menulis daftar syscall dengan tangan rawan kelupaan. Prinsipnya sama dengan menulis test case dengan tangan: bagus untuk kasus yang dipahami, buruk untuk cakupan menyeluruh. Generator menyelesaikan masalah ini dengan merekam syscall yang benar-benar dipakai.
podman run --annotation io.containers.trace-syscall=./nginx-v2.json \
--security-opt seccomp=unconfined nginx:lateststrace -f -c lalu terjemahkan hasilnya ke JSON profile.Alur kerja yang sehat: trace di staging → generate → diff dengan profile lama → review → version → validasi di CI. Diff adalah langkah penting: syscall baru yang muncul saat upgrade aplikasi harus terlihat dan disetujui secara sadar, bukan masuk diam-diam.
Sebuah profile JSON berisi defaultAction, archMap, dan daftar syscall beserta aksinya. Perbedaan antara mode LOG dan ENFORCE hanya pada defaultAction:
{
"defaultAction": "SCMP_ACT_LOG",
"archMap": [
{ "architecture": "SCMP_ARCH_X86_64", "subArchitectures": ["SCMP_ARCH_X86"] }
],
"syscalls": [
{ "names": ["read", "write", "futex", "mmap", "openat"], "action": "SCMP_ACT_ALLOW" },
{ "names": ["clone3", "unshare"], "action": "SCMP_ACT_ERRNO" }
]
}Untuk berpindah ke ENFORCE, ganti defaultAction menjadi SCMP_ACT_ERRNO. Dua berkas yang hanya berbeda satu baris ini adalah pasangan yang akan kalian kelola di setiap rollout.
Validasi otomatis di CI menjaga agar profile yang tidak sehat tidak pernah sampai ke produksi. Lapisan validasinya:
jq memastikan berkas bisa dibaca dan memenuhi skema.scmp_sys_resolver'.Berikut contoh pipeline GitHub Actions yang menjalankan validasi tersebut:
name: seccomp-policy
on:
pull_request:
paths:
- "profiles/seccomp/**"
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validasi struktur JSON semua profile
run: |
for p in profiles/seccomp/**/*.json; do
jq -e . "$p" >/dev/null || { echo "JSON tidak valid: $p"; exit 1; }
done
- name: Validasi nama syscall terhadap libseccomp
run: |
for p in profiles/seccomp/**/*.json; do
jq -r '.syscalls[].names[]' "$p" | while read -r sc; do
scmp_sys_resolver "$sc" >/dev/null 2>&1 || { echo "Syscall asing: $sc"; exit 1; }
done
done
- name: Cek deny-list wajib
run: |
for p in profiles/seccomp/**/*.json; do
jq -e '.syscalls[] | select(.action == "SCMP_ACT_ERRNO")' "$p" \
>/dev/null || { echo "Tidak ada deny-list di $p"; exit 1; }
doneMengubah profile langsung di produksi adalah resep insiden. Alur yang benar selalu bertahap.
Tahap 1 — LOG. Terapkan profile dengan defaultAction: SCMP_ACT_LOG. Semua syscall yang tidak ada di daftar izin dicatat, bukan diblokir. Pantau audit log selama beberapa hari dan kumpulkan syscall yang muncul. Ini periode observasi, bukan periode penerimaan pasif.
Tahap 2 — Canary. Setelah daftar syscall stabil, pindah ke ENFORCE, tetapi terapkan hanya pada sebagian kecil node atau pod — misalnya lima persen lalu naik bertahap. Pantau error rate aplikasi, latency, dan denial.
Tahap 3 — Rollout penuh dan rollback terencana. Karena profile adalah kode, rollback sesederhana git revert lalu deploy ulang. Siapkan runbook yang menyebutkan metrik yang harus diamati dan ambang yang memicu rollback.
Tip
Satu kesalahan umum: membiarkan mode LOG menyala permanen. Log yang tidak pernah dibaca hanyalah biaya tanpa nilai. Logging harus punya pemilik dan tenggat — setelah periode observasi selesai, profile harus naik ke ENFORCE atau secara sadar dipertahankan dengan alasan tertulis.
Kombinasi versioning, generator, validasi CI, dan rollout bertahap menghasilkan siklus yang bisa diulang: setiap perubahan profile melewati jalur yang sama, teruji, dan bisa dibatalkan. Itulah makna seccomp sebagai policy-as-code — bukan sekadar berkas JSON di git, melainkan alur yang membuat perubahan itu aman.
Pada episode 20 ini kalian mengubah profile seccomp dari artefak manual menjadi kode yang terkelola: versioning semantik di git, generasi dari trace nyata dengan oci-seccomp-bpf-hook dan seccomp-generators, validasi struktur dan syscall di CI, serta rollout bertahap dari LOG ke ENFORCE dengan canary dan rollback.
Poin kunci yang perlu kalian bawa:
git revert adalah dua sisi dari rollout yang aman.Di episode 21 berikutnya kita menengok ke depan: fitur modern libseccomp 2.6.1, dukungan arsitektur baru, dan roadmap proyek beserta kernel. Sampai jumpa!