Episode ini membahas privilege minimisasi lewat lxc.cap.drop dan lxc.cap.keep, konfigurasi lxc.aa_profile, pembatasan akses device dengan cgroup devices, serta passthrough GPU dan USB ke container.

Di episode 13 kita memasang pagar MAC dan seccomp. Sekarang kita menyempitkan lagi: capabilities — kemampuan spesifik yang dimiliki proses root di dalam container — dan control device — perangkat apa saja yang boleh diakses. Prinsipnya satu: least privilege. Semakin sedikit yang dimiliki proses, semakin kecil kerusakan yang bisa dilakukannya saat dikompromi.
Di Linux modern, "root" tidak lagi segalanya-atau-tidak-sama-sekali. Hak root dipecah menjadi capabilities individual: CAP_NET_ADMIN (mengelola network), CAP_SYS_ADMIN (operasi mount/namespace), CAP_DAC_OVERRIDE (mengabaikan permission file), dan puluhan lainnya. Container bisa diberi subset capabilities ini — root di dalam container hanya sekuat daftar capabilities yang diizinkan.
Pendekatan default yang aman: drop semua capabilities yang tidak dibutuhkan workload.
lxc.cap.drop = sys_admin
lxc.cap.drop = mknod
lxc.cap.drop = sys_moduleSetiap baris menghapus satu capability dari set yang diizinkan di dalam container. Untuk workload sederhana (web server, database, app server), sebagian besar capabilities bisa di-drop.
Pendekatan berlawanan dan lebih tegas: tentukan secara eksplisit apa saja yang di-keep, sisanya otomatis dihapus.
lxc.cap.keep = net_bind_service
lxc.cap.keep = net_raw
lxc.cap.keep = dac_overrideDengan keep, daftar akhir adalah persis yang tertulis — tidak ada yang tersisa diam-diam. Ini pola yang paling mudah diaudit.
Tip
Workflow yang disarankan: mulai dari container yang jalan, audit capabilities yang dipakai proses (lxc-attach -n c1 -- capsh --print), lalu drop semua yang tidak terpakai. Menggunakan drop lebih ramah untuk workload yang tidak diketahui; menggunakan keep lebih aman untuk workload yang sudah pasti.
Dari dalam container, lihat set capabilities proses saat ini:
lxc-attach -n c1 -- capsh --print | grep CurrentBandingkan dengan set default (yang luas) untuk melihat efek drop/keep.
Config lxc.aa_profile menentukan profil AppArmor yang menaungi proses container — melengkapi capabilities. Ini cara kalian memilih profil per-container dari episode 13:
lxc.aa_profile = generatedKombinasi lxc.cap.drop/keep (capabilities) + lxc.aa_profile (MAC) + seccomp (syscall) adalah tiga lapis yang saling mengunci. Capabilities membatasi hak, AppArmor membatasi akses file, seccomp membatasi syscall.
Meski container unprivileged sudah dibatasi, masih ada baiknya mengontrol device secara eksplisit lewat cgroup devices — daftar device yang boleh diakses proses container. LXC memberi kunci lxc.cgroup2.devices.allow dan lxc.cgroup2.devices.deny.
# Format: <type> <major>:<minor> <perm>
lxc.cgroup2.devices.deny = a
lxc.cgroup2.devices.allow = c 10:200 rwmdeny a — tolak semua device (atur ulang izin menjadi kosong).allow c 10:200 rwm — izinkan device char major 10 minor 200 (contoh /dev/net/tun) dengan permission read/write/mknod.Setelah deny a, container hanya bisa mengakses device yang eksplisit di-allow. Ini mencegah container menciptakan atau memakai device yang tidak diinginkan.
Bayangkan container yang dibajak: tanpa device control, ia bisa mencoba mengakses /dev/mem atau device disk. Dengan deny a + daftar allow yang sempit, upaya itu gagal di lapisan kernel — bahkan sebelum AppArmor bicara.
Untuk workload yang butuh GPU (rendering, inference), akses device GPU host perlu di-mount ke container. Untuk NVIDIA, pendekatan umumnya:
lxc.mount.entry = /dev/nvidia0 c1/dev/nvidia0 none bind,create=file 0 0
lxc.mount.entry = /usr/lib/nvidia c1/usr/lib/nvidia none bind,ro 0 0Passthrough USB: temukan device di host, lalu bind-mount node-nya ke container.
lsusb
ls -l /dev/bus/usb/001/002lxc.mount.entry = /dev/bus/usb/001/002 c1/dev/bus/usb/001/002 none bind,create=file 0 0Warning
Passthrough GPU/USB melemahkan isolasi secara sengaja — proses di dalam container kini bisa memprogram hardware host. Pastikan container tersebut bukan milik tenant tak tepercaya, dan pertahankan semua lapis lain (unprivileged, MAC, seccomp) tetap aktif. Passthrough adalah keputusan arsitektur, bukan trik.
lxc.cap.drop untuk yang pasti tak terpakai, lxc.cap.keep untuk yang harus diaudit.lxc.cgroup2.devices.deny = a lalu allow hanya yang dibutuhkan.Inti yang harus dibawa pulang:
drop menghapus, keep menyisakan.lxc.aa_profile menghubungkan container ke profil AppArmor.lxc.cgroup2.devices.allow/deny) membatasi akses perangkat.Di episode 15 selanjutnya kita akan membahas user namespaces & ID mapping — /etc/subuid dan /etc/subgid, lxc.idmap untuk pemetaan UID/GID, lxc-usernet untuk kuota network unprivileged, dan best practice pemetaan 0-65536.