Belajar SELinux - Policy-as-Code & Automation
Episode 20 of 23

Belajar SELinux - Policy-as-Code & Automation

Mengelola SELinux seperti kode: policy module tersimpan di git, didistribusikan lewat Ansible, templating boolean dan fcontext, pengujian di CI, hingga pipeline build ber-version dengan rollback terstruktur.

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

Pendahuluan

Setelah di episode 19 kalian mengisolasi aplikasi yang tidak tepercaya dengan sandbox, sekarang kita menjawab pertanyaan yang jauh lebih strategis: bagaimana mengelola SELinux di infrastruktur yang bukan satu server? Di episode 18 kita sudah menyentuh pentingnya policy yang seragam. Episode 20 ini mengubah itu menjadi praktik nyata dengan policy-as-code: seluruh policy SELinux — module, boolean, fcontext — diperlakukan seperti kode aplikasi, dengan git, review, CI, dan rilis ber-version.

Pembahasan Utama

Policy-as-Code: Satu Sumber Kebenaran

Pernah melihat server yang konfigurasi SELinux-nya cuma ada di kepala admin yang sudah resign? Itu kebalikan dari policy-as-code. Bayangkan kalau source code aplikasi kalian disimpan hanya di ingatan orang — tidak ada yang bisa memverifikasi, menguji, atau mengembalikan versi. Policy SELinux yang dijalankan lewat semanage dan semodule -l langsung di shell mengalami nasib yang sama: tidak terdokumentasi, tidak bisa diaudit, dan mudah drift.

Solusinya: jadikan tree source module sebagai repositori git. Struktur tipikalnya:

LinuxStruktur tree source module policy
myapp/
├── myapp.te   # type enforcement rules
├── myapp.fc   # file context
├── myapp.if   # interface (opsional)
└── Makefile

Dengan ini, setiap perubahan adalah commit, setiap commit bisa di-review, dan setiap rilis bisa di-tag.

Module yang pernah kalian tulis di episode-episode sebelumnya bisa dibuat ulang kapan pun dari source tree. File .te misalnya:

Linuxmyapp.te — aturan type enforcement
policy_module(myapp, 1.0.0)
 
type myapp_t;
type myapp_exec_t;
domain_type(myapp_t)
domain_entry_file(myapp_t, myapp_exec_t)
 
allow myapp_t self:tcp_socket create_socket_perms;
allow myapp_t myapp_conf_t:file read_file_perms;
allow myapp_t myapp_log_t:file { create append_file_perms };
allow myapp_t myapp_log_t:dir { create read search add_name };

File context untuk memberi label path:

Linuxmyapp.fc — file context
/opt/myapp(/.*)?	gen_context(system_u:object_r:myapp_exec_t,s0)
/etc/myapp(/.*)?	gen_context(system_u:object_r:myapp_conf_t,s0)
/var/log/myapp(/.*)?	gen_context(system_u:object_r:myapp_log_t,s0)

Catatan penting: kolom pada .fc dipisahkan dengan tab, dan kolom kedua harus diperlakukan sebagai satu field — jangan mengganti tab dengan spasi. Membangun module dari tree source memakai Makefile standar:

Bangun myapp.pp dari source tree
make -f /usr/share/selinux/devel/Makefile
Pasang module yang sudah dibangun
semodule -i myapp.pp
Verifikasi module terpasang
semodule -l | grep myapp

Yang menarik: perintah make ini bekerja juga di CI — sebuah pipeline bisa menolak module yang tidak lolos kompilasi tanpa pernah menyentuh server produksi.

Mendistribusikan dengan Ansible

Distribusi policy ke banyak host adalah pekerjaan yang membosankan dan rawan salah kalau dikerjakan manual. Ansible menjawabnya dengan idempotensi: playbook yang sama dijalankan berkali-kali memberikan hasil yang sama. Untuk SELinux ada tiga module utama yang perlu kalian kenal:

  • ansible.posix.selinux — mengatur state (enforcing/permissive) dan boolean.
  • community.general.selinux_fcontext — mengelola file context.
  • community.general.selinux_permissive — mengelola domain permissive.

Contoh playbook untuk menerapkan boolean dan fcontext secara seragam:

site.yml — terapkan policy SELinux
- name: Terapkan policy SELinux seragam
  hosts: webservers
  become: true
  vars:
    httpd_booleans:
      - name: httpd_can_network_connect
        state: true
    fcontexts:
      - target: /var/www/myapp(/.*)?
        setype: httpd_sys_content_t
        state: present
  tasks:
    - name: Setel mode SELinux
      ansible.posix.selinux:
        policy: targeted
        state: enforcing
    - name: Atur boolean httpd
      ansible.posix.selinux:
        name: "{{ item.name }}"
        state: "{{ 'on' if item.state else 'off' }}"
        persistent: true
      loop: "{{ httpd_booleans }}"
    - name: Terapkan file context
      community.general.selinux_fcontext:
        target: "{{ item.target }}"
        setype: "{{ item.setype }}"
        state: "{{ item.state }}"
      loop: "{{ fcontexts }}"

Perhatikan dua hal. Pertama, persistent: true pada boolean memastikan nilainya bertahan setelah reboot — tanpa itu, perubahan boolean hanya berlaku sampai restart. Kedua, module fcontext tidak menjalankan restorecon otomatis; kalian tetap perlu memanggil restorecon untuk file yang sudah ada agar labelnya diperbarui:

Terapkan label setelah fcontext diubah
restorecon -Rv /var/www/myapp

Tip

Gabungkan playbook di atas dengan verifikasi baseline dari episode 18: setelah menjalankan restorecon, playbook yang sama bisa mengecek semodule -l dan membandingkan daftar module terhadap yang diharapkan. Ansible bukan hanya alat menerapkan, tapi juga alat memastikan — dan itulah yang membuat policy tetap seragam di seluruh fleet.

Menguji Policy di CI

Build yang sukses belum berarti policy itu aman. Di CI, tambahkan lapisan pengujian:

.github/workflows/policy.yml — pipeline policy SELinux
name: Policy SELinux
on:
  push:
    paths: ["policy/**"]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Bangun module
        run: make -f /usr/share/selinux/devel/Makefile
      - name: Analisis dengan SETools
        run: |
          seinfo -x myapp.pp
          sesearch --allow -t shell_exec_t myapp.pp || true
      - name: Instalasi percobaan di container
        run: ./tests/install-and-smoke-test.sh

Dua lapis di atas layak diperhatikan:

  • Analisis statis. seinfo dan sesearch dari SETools membacai .pp tanpa perlu booting — misalnya untuk memastikan tidak ada aturan yang mengizinkan domain aplikasi mengeksekusi shell (shell_exec_t).
  • Smoke test. tests/install-and-smoke-test.sh memuat module di container atau mesin uji, menjalankan aplikasi sebentar, lalu menegaskan bahwa ausearch -m avc tidak berisi deny yang tidak diharapkan. Ini membuat deny baru ketahuan di CI, bukan di produksi.

Pipeline Build Ber-version dan Rollback Terstruktur

Artifak module yang dihasilkan CI harus punya versi yang jelas — misalnya myapp-v1.2.0.pp — dan setiap versi tersimpan (Nexus, GitHub Release, atau bucket storage). Perintah semodule -l menampilkan daftar module aktif untuk mencocokkan versi yang terpasang. Mengapa? Karena rollback harus dilakukan ke versi yang diketahui, bukan menebak.

Rollback terstruktur ke versi sebelumnya
semodule -r myapp
semodule -i myapp-v1.1.0.pp
restorecon -Rv /opt/myapp /etc/myapp

Warning

Jangan pernah menghapus module lama tanpa menyimpan versi sebelumnya. Rollback yang "rebuild dari ingatan" adalah kontra-rollback: di saat genting kalian justru berimprovisasi. Simpan .pp ber-version sebagai artefak CI, catat versi mana yang terpasang di host mana, dan jadikan semodule -r yang diikuti pemasangan versi lama sebagai prosedur standar — bukan satu langkah dramatis yang dihapal.

Checklist Operasional untuk Policy-as-Code

Ringkasan praktik yang membuat pendekatan ini bertahan lama:

  1. Seluruh .te, .fc, .if di git — satu repositori per aplikasi atau per layanan.
  2. Build di CI dengan Makefile devel; kegagalan kompilasi = pipeline merah.
  3. Analisis statis dengan SETools (seinfo, sesearch) sebelum deploy.
  4. Smoke test deny (ausearch -m avc) pada mesin uji.
  5. Artefak .pp ber-version; rollback adalah prosedur tertulis.
  6. Distribusi seragam dengan Ansible; verifikasi baseline rutin.

Penutup

Pada episode 20 ini kalian telah belajar memperlakukan SELinux sebagai kode sungguhan: source module di git, build dan uji di CI, distribusi idempoten dengan Ansible (boolean, fcontext, dan permissive lewat module ansible.posix.selinux, community.general.selinux_fcontext, dan community.general.selinux_permissive), serta pipeline ber-version dengan rollback terstruktur. Dengan pola ini, "SELinux sulit dikelola di skala besar" bukan lagi alasan — karena semua keputusan terdokumentasi, dapat diaudit, dan bisa dikembalikan.

Di episode 21 berikutnya kita melihat ke depan: rilis SELinux userspace 3.11 (Juli 2026) dengan secilcheck, restorecon -F, setfiles -A dan -U, perbaikan keamanan libselinux dan dbus, serta peta jalan rilis 3.12 pada 2027. Sampai jumpa!

Belajar SELinux - Policy-as-Code & Automation | Belajar SELinux