Menerapkan AppArmor pada layanan sungguhan: profile bawaan Nginx, Apache, dan OpenSSH, penyesuaian web root dan sertifikat SSL, profile database MySQL dan PostgreSQL, runtime Node dan Python, serta perangkap log rotation.

Di episode 8, kalian punya peralatan untuk menulis profile yang portabel: variable, tunables, dan abstractions. Sekarang saatnya keluar dari latihan dan mengunci layanan yang benar-benar berjalan di server kalian. Web server dan database adalah target pertama yang hampir selalu diserang ketika sebuah instance di-internet-facing — dan justru keduanya yang paling mudah diamankan karena komunitas sudah menyiapkan profile bawaan.
Ubuntu dan Debian membawa profile AppArmor untuk layanan populer di dalam paketnya. Beberapa langsung aktif saat install, sebagian lain tersedia tapi menunggu diaktifkan. Lihat apa yang ada di sistem kalian:
ls /etc/apparmor.d/ | grep -E "nginx|apache|sshd|mysqld|postgres"Contoh nama file yang muncul:
usr.sbin.apache2
usr.sbin.mysqld
usr.sbin.nginx
usr.sbin.sshd
usr.lib.postgresql.14.bin.postgresPerhatikan polanya: nama file adalah path executable dengan / diganti titik. Saat Nginx dijalankan dari /usr/sbin/nginx, kernel memuat profile usr.sbin.nginx. Hubungan inilah yang menentukan nama file — bukan nama layanan.
Note
Status profile bisa dilihat dengan aa-status: baris dengan (enforce) berarti aktif menolak, (complain) berarti hanya mencatat, dan (attach_disconnected) berarti mode khusus yang sering dipakai profile container. Profile bawaan yang tidak terdaftar di aa-status tidak aktif — kalian perlu mengaktifkannya secara eksplisit.
Profile bawaan biasanya cukup untuk instalasi standar. Masalah muncul saat kalian menyimpang dari default: web root dipindah, sertifikat ditaruh di Let's Encrypt, atau log dialihkan ke direktori kustom. Contoh penyesuaian yang umum:
#include <tunables/global>
/usr/sbin/nginx flags=(enforce) {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/ssl_certs>
network inet tcp,
network inet6 tcp,
/usr/sbin/nginx mr,
/etc/nginx/** r,
/var/www/app/** r,
/var/log/nginx/*.log w,
# sertifikat Let's Encrypt untuk domain kustom
/etc/letsencrypt/live/**.pem r,
/etc/letsencrypt/archive/** r,
}Tiga penyesuaian yang wajib kalian perhatikan:
/var/www/app/** r — web root kalian bukan /var/www/html bawaan./etc/letsencrypt/** — sertifikat dari certbot berada di luar /etc/ssl./var/log/nginx/*.log w — profile harus bisa menulis log yang baru dibuka logrotate.Jangan lupa reload setelah mengedit, seperti pola di episode 7:
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginxusr.sbin.sshd adalah profile paling simpel yang layak kalian aktifkan: SSH adalah pintu masuk utama server, dan memperkecil apa yang bisa dilakukan proses sshd setelah terkompromi sangat berharga. Profile bawaan mengizinkan autentikasi, pembukaan sesi, dan operasi dasar — sementara sebagian besar fungsi sistem lain tetap tertutup. Jika kalian memakai autentikasi berbasis kunci dengan lokasi kunci kustom, pastikan aturan untuk @{HOME}/.ssh/** r tersedia di profile.
Database menyimpan data paling berharga, jadi profile-nya harus benar-benar terkunci. usr.sbin.mysqld mengizinkan akses ke direktori data dan socket lokal:
/var/lib/mysql/** rw,
/var/run/mysqld/** rw,
/var/log/mysql/*.log rw,Perhatian khusus untuk log rotation. Logrotate menutup file log lama dan membuat file baru. Jika profile hanya mengizinkan path file tertentu (misalnya /var/log/mysql/error.log), file baru hasil rotasi akan memicu denial. Gunakan wildcard untuk seluruh direktori, dan pastikan ada aturan untuk direktori itu sendiri:
/var/log/mysql/ rw,
/var/log/mysql/** rw,PostgreSQL punya pola serupa lewat profile usr.lib.postgresql.*.bin.postgres. Jika kalian mengubah data directory atau port, perbarui profile — denial connect ke socket di path kustom adalah gejala yang paling sering muncul.
Runtime seperti Node dan Python adalah tantangan tersendiri: mereka me-load modul secara dinamis, melakukan JIT, dan membuka banyak file kecil saat runtime. Profile yang terlalu ketat akan menghasilkan denial yang beruntun; profile yang terlalu longgar tidak berguna.
Pendekatan yang realistis untuk aplikasi di dalam server:
#include <tunables/global>
/usr/bin/node mr,
/opt/myapp/** r,
/opt/myapp/node_modules/** r,
/opt/myapp/.env r,
/var/log/myapp/*.log rw,
network inet tcp,
capability setgid,
capability setuid,Perhatikan apa yang dimasukkan dan tidak. Path project diawasi lengkap, sementara lokasi internal Node ditangani abstractions/base atau rule eksplisit. Untuk aplikasi dengan ekstensi native, JIT mungkin membutuhkan hak m (memory map) untuk library yang di-load — denial operation="mmap" di log adalah petunjuknya.
Tip
Strategi bertahap paling ampuh di sini: jalankan runtime di mode complain (aa-complain /etc/apparmor.d/...), biarkan aplikasi bekerja beberapa hari, kumpulkan denial yang benar-benar berulang dengan aa-logprof, lalu pindahkan ke enforce. Mode complain mengubah log menjadi daftar kebutuhan tanpa memblokir apa pun.
Pada episode 9 ini kalian sudah menerapkan AppArmor ke layanan produksi: mengenali profile bawaan distribusi untuk Nginx, Apache, dan OpenSSH, menyesuaikan web root dan sertifikat SSL di lokasi kustom, memahami aturan inti MySQL dan PostgreSQL, menghadapi dinamika runtime Node dan Python, serta menghindari perangkap log rotation dengan wildcard yang benar.
Kunci yang harus dibawa pulang:
Semua profile yang kita bahas sejauh ini mengunci proses yang berjalan langsung di host. Tapi sebagian besar workload modern tidak lagi berjalan langsung di host — mereka berjalan di container. Di episode 10, kita masuk ke Containers & Kubernetes: integrasi AppArmor dengan Docker dan containerd, profile docker-default, serta cara mengamankan pod di Kubernetes dengan annotation dan native field.