Belajar Seccomp - Seccomp & Policy-as-Code
Episode 20 of 23

Belajar Seccomp - Seccomp & Policy-as-Code

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.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

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.

Profile Seccomp sebagai Artefak yang Dikelola

Mulailah dengan struktur direktori yang jelas di repository:

text
profiles/seccomp/
  nginx/
    v1.0.0.json
    v1.1.0.json
  postgres/
    v1.0.0.json
  common/
    base.json

Setiap 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.

Generator Berbasis strace

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.

  • oci-seccomp-bpf-hook — menjalankan container dalam mode trace dan menghasilkan profile JSON dari syscall yang diamati. Dipicu lewat annotation pada runtime yang mendukung OCI hooks:
Generate profile dari trace container
podman run --annotation io.containers.trace-syscall=./nginx-v2.json \
    --security-opt seccomp=unconfined nginx:latest
  • seccomp-generators dari Red Hat — kumpulan generator khusus per aplikasi, misalnya untuk web server, yang menghasilkan profile fokus tanpa perlu men-trace sendiri.
  • strace manual — untuk workload khusus yang tidak punya generator, rekam syscall dengan strace -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.

Struktur Profile dan Dua Mode Rollout

Sebuah profile JSON berisi defaultAction, archMap, dan daftar syscall beserta aksinya. Perbedaan antara mode LOG dan ENFORCE hanya pada defaultAction:

Profile dalam mode LOG
{
  "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 di CI

Validasi otomatis di CI menjaga agar profile yang tidak sehat tidak pernah sampai ke produksi. Lapisan validasinya:

  • Struktur JSON validjq memastikan berkas bisa dibaca dan memenuhi skema.
  • Syscall dikenal — setiap nama syscall harus dikenali oleh tabel libseccomp, dicek dengan scmp_sys_resolver'.
  • Tidak ada kejutan — deny-list dipertahankan; daftar syscall yang diizinkan tidak bertambah tanpa persetujuan.
  • Smoke test — container dijalankan dengan profile dan health check aplikasi tetap lulus.

Berikut contoh pipeline GitHub Actions yang menjalankan validasi tersebut:

.github/workflows/seccomp.yml — validasi profile
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; }
          done

Rollout Bertahap: LOG, Canary, Rollback

Mengubah 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.

Penutup

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:

  • Profile adalah kode: versikan, review, dan catat perubahannya.
  • Generator berbasis strace mencegah daftar syscall yang ketinggalan zaman.
  • CI memvalidasi struktur, keabsahan syscall, dan keberadaan deny-list.
  • Mode LOG adalah periode observasi, bukan kondisi permanen.
  • Canary dan 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!

Belajar Seccomp - Seccomp & Policy-as-Code | Belajar Seccomp