Otomasi security hardening dan compliance: implementasi CIS benchmark dengan collection ansible-lockdown, hardening SSH dan firewall, patch management dengan reboot otomatis, compliance as code (STIG, audit logging, AIDE), hingga integrasi scanner keamanan OpenSCAP dan Lynis.

Setelah di episode 26 sebelumnya kita membahas provisioning infrastruktur cloud — membuat EC2, VM GCP, hingga instance Azure secara deklaratif — pada episode kali ini kita akan membahas sisi yang paling sering diabaikan setelah infrastruktur berdiri: security hardening dan compliance automation.
Bayangkan kalian baru saja membangun rumah yang megah. Listrik terpasang, jaringan internet lancar, perabotan lengkap. Tapi pintunya masih pakai kunci gembok murah, jendela tidak berkunci, dan tidak ada alarm kebakaran. Siapa pun bisa masuk, dan ketika terjadi sesuatu, kalian tidak punya bukti apa pun tentang apa yang terjadi. Itulah gambaran server yang berjalan di production tanpa hardening: infrastruktur tersedia, tetapi keamanannya lemah dan tidak ada jejak audit.
Masalahnya, melakukan hardening secara manual di puluhan atau ratusan server adalah pekerjaan yang membosankan, rawan lupa, dan hasilnya tidak konsisten — persis masalah yang ingin Ansible selesaikan. Lebih dari itu, banyak industri (perbankan, kesehatan, pemerintahan, e-commerce) kini diwajibkan memenuhi standar compliance seperti CIS Benchmark, STIG, PCI-DSS, atau ISO 27001. Mengelola kepatuhan ini "as code" — bukan dengan checklist Excel — adalah cara satu-satunya yang scalable.
Pada episode ini kita akan membahas implementasi CIS benchmark menggunakan collection ansible-lockdown, hardening SSH dan firewall (UFW, firewalld), otomasi patch management lengkap dengan manajemen reboot, compliance as code untuk STIG dan file integrity monitoring (AIDE), serta integrasi scanner keamanan seperti OpenSCAP dan Lynis.
Hardening adalah proses memperkecil attack surface (permukaan serangan) sebuah sistem: menutup service yang tidak perlu, memperkuat autentikasi, menerapkan prinsip least privilege, dan mengunci konfigurasi default yang lemah. Default instalasi Linux biasanya "nyaman tapi rapuh": SSH dengan password, root login diizinkan, banyak port terbuka, dan update keamanan tidak otomatis.
Kuncinya: Ansible membuat hardening menjadi repeatable dan verifiable. Playbook yang sama bisa dijalankan ke server baru dalam hitungan menit, hasilnya identik, dan idempotent — dijalankan ulang tidak mengubah apa-apa yang sudah benar. Inilah yang membedakan hardening as code dari checklist manual.
CIS (Center for Internet Security) Benchmark adalah kumpulan rekomendasi hardening berbasis konsensus industri untuk berbagai sistem operasi — mulai dari konfigurasi kernel, file permission, sshd, hingga policy audit. Setiap rekomendasi diberi level: Level 1 (praktik dasar yang disarankan) dan Level 2 (defense-in-depth untuk environment yang sangat sensitif).
Menulis ribuan kontrol CIS secara manual adalah pekerjaan besar. Di sinilah komunitas ansible-lockdown berperan. Collection ini menyediakan role hardening siap pakai yang sudah mengimplementasikan CIS Benchmark untuk berbagai sistem operasi:
| Collection Role | Target OS | Benchmark |
|---|---|---|
ansible-lockdown.redhatcis_rhel9 | RHEL 9 / Rocky 9 / AlmaLinux 9 | CIS RHEL 9 Benchmark |
ansible-lockdown.redhatcis_rhel8 | RHEL 8 / Rocky 8 / AlmaLinux 8 | CIS RHEL 8 Benchmark |
ansible-lockdown.ubuntu_cis | Ubuntu 22.04 / 24.04 | CIS Ubuntu Benchmark |
ansible-lockdown.windows_cis | Windows Server 2019 / 2022 | CIS Windows Server Benchmark |
ansible-lockdown.stig_rhel9 | RHEL 9 | DISA STIG for RHEL 9 |
Cara kerjanya: role mendaftarkan daftar rule CIS sebagai variabel boolean, lalu kalian mengaktifkan/menonaktifkan rule sesuai kebutuhan. Role membaca variabel tersebut dan menyesuaikan konfigurasi sistem secara idempotent.
Install collection-nya:
ansible-galaxy collection install ansible-lockdown.ubuntu_cis
ansible-galaxy collection install ansible-lockdown.redhatcis_rhel9Setelah itu, gunakan role dalam playbook. Contoh berikut meng-hardening server Ubuntu 24.04 terhadap CIS Level 2:
- name: Hardening Ubuntu dengan CIS Benchmark
hosts: ubuntu_servers
become: true
vars:
ubtu20cis_rule_6_1_2: false
ubtu20cis_auditd_enabled: true
ubtu20cis_system_audit_rules:
- "-w /etc/passwd -p wa -k identity"
- "-w /etc/shadow -p wa -k identity"
ubtu20cis_sysctl_rules:
net.ipv4.ip_forward: 0
net.ipv4.conf.all.send_redirects: 0
roles:
- ansible-lockdown.ubuntu_cisImportant
Role dari ansible-lockdown sangat agresif — beberapa rule mengubah permission, mematikan service, atau mengunci user. Selalu jalankan dengan mode --check terlebih dahulu, uji di staging environment, dan pastikan kalian memahami setiap rule yang diaktifkan. Menjalankan CIS role penuh di production tanpa testing adalah cara tercepat membuat production down. Nama prefix variabel mengikuti versi role (misalnya ubtu20cis_* untuk Ubuntu 20.04/22.04), jadi periksa dokumentasi role untuk versi yang kalian pakai.
Untuk role hardening SSH yang lebih ringan dan terkontrol, kita bisa menulisnya sendiri. Contoh berikut memanfaatkan modul ansible.builtin.lineinfile dan template sshd_config:
- name: Hardening konfigurasi SSH server
hosts: all
become: true
tasks:
- name: Template sshd_config yang aman
ansible.builtin.template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config
owner: root
group: root
mode: "0600"
validate: "/usr/sbin/sshd -t -f %s"
notify: Restart SSH
handlers:
- name: Restart SSH
ansible.builtin.service:
name: sshd
state: restartedTemplate sshd_config.j2-nya:
# Managed by Ansible - perubahan manual akan ditimpa
Port {{ ssh_port | default(22) }}
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers {{ ssh_allowed_users | default([]) | join(' ') }}
AllowTcpForwarding no
X11Forwarding noWarning
Perhatikan atribut validate: "/usr/sbin/sshd -t -f %s". Ini memvalidasi syntax config sebelum mengganti file asli — menyelamatkan kalian dari lockout fatal jika template salah. Dan selalu pastikan key SSH kalian sudah terpasang (authorized_key) sebelum menonaktifkan PasswordAuthentication, atau kalian akan terkunci di luar server sendiri.
Firewall adalah pagar pertama dari sebuah server. Ansible menyediakan modul khusus untuk masing-masing backend, dan keputusan terbaik adalah memilih satu firewall per host dan konsisten — jangan mencampur UFW dan firewalld pada sistem yang sama.
Contoh code group berikut menunjukkan pendekatan yang setara di tiga dunia berbeda — satu untuk Debian/Ubuntu (UFW), satu untuk RHEL/Rocky (firewalld), dan satu yang low-level (iptables) untuk kasus yang sangat spesifik:
- name: Konfigurasi firewall UFW (Debian/Ubuntu)
hosts: ubuntu_servers
become: true
tasks:
- name: Default policy deny incoming
community.general.ufw:
policy: deny
direction: incoming
- name: Izinkan SSH dari subnet internal
community.general.ufw:
rule: allow
proto: tcp
port: "22"
src: 10.0.0.0/8
- name: Izinkan HTTP/HTTPS publik
community.general.ufw:
rule: allow
port: "80,443"
proto: tcp
- name: Aktifkan UFW
community.general.ufw:
state: enabledNote
Untuk managed node yang berada di balik security group cloud (AWS, GCP, Azure), ingat bahwa security group cloud tidak menggantikan firewall OS — keduanya harus saling melengkapi. Security group melindungi dari luar VPC, sedangkan firewall OS melindungi dari host lain di dalam network yang sama. Buat aturan firewalld dengan immediate: true agar perubahan berlaku tanpa menunggu reload service — mencegah lockout saat menerapkan policy deny secara live.
Patch management adalah salah satu kontrol keamanan paling murah namun paling efektif — sebagian besar serangan ransomware dan zero-day exploitation memanfaatkan kerentanan yang sebenarnya sudah ditambal berbulan-bulan lalu. Masalahnya, manual patching di banyak server hampir mustahil dilakukan konsisten.
Ansible menawarkan dua pendekatan: automated security updates (patch kecil berjalan otomatis) dan scheduled patch cycles (patch besar dengan jadwal dan reboot terkontrol).
Untuk Ubuntu/Debian, unattended-upgrades menginstal patch keamanan secara otomatis di latar belakang. Konfigurasinya bisa di-template oleh Ansible:
- name: Aktifkan automated security updates
hosts: ubuntu_servers
become: true
tasks:
- name: Install unattended-upgrades
ansible.builtin.apt:
name: unattended-upgrades
state: present
update_cache: true
- name: Template konfigurasi auto-upgrade
ansible.builtin.template:
src: 50unattended-upgrades.j2
dest: /etc/apt/apt.conf.d/50unattended-upgrades
mode: "0644"
- name: Aktifkan interval upgrade otomatis
ansible.builtin.copy:
dest: /etc/apt/apt.conf.d/20auto-upgrades
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";Untuk RHEL, dnf-automatic memainkan peran yang sama:
dnf install -y dnf-automatic
sed -i 's/apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf
systemctl enable --now dnf-automatic.timerCaution
Automated security update adalah pedang bermata dua. Di satu sisi ia menutup lubang keamanan dengan cepat; di sisi lain ia bisa memasang update yang merusak aplikasi di jam 3 pagi tanpa sepengetahuan siapa pun. Praktik terbaik: aktifkan automated update hanya untuk patch keamanan, lakukan pinning versi untuk service kritis, dan pantau hasilnya lewat log serta monitoring (ingat episode 25).
Update kernel selalu membutuhkan reboot — dan reboot adalah momen paling menegangkan dalam operasional. Di sinilah modul ansible.builtin.reboot berperan. Modul ini tidak sekadar me-reboot; ia bisa menunggu koneksi SSH turun, menunggu service kembali, dan menunda reboot agar tidak terjadi secara tiba-tiba.
Contoh playbook patch + reboot yang aman untuk fleet production — memanfaatkan serial agar hanya sebagian server yang dipatch bersamaan:
- name: Patch dan reboot aman
hosts: app_servers
become: true
serial: 1
order: sorted
tasks:
- name: Update semua paket (termasuk kernel)
ansible.builtin.dnf:
name: "*"
state: latest
update_cache: true
- name: Cek apakah reboot dibutuhkan
ansible.builtin.command: /usr/bin/needs-restarting -r
register: needs_reboot
failed_when: needs_reboot.rc not in [0, 1]
changed_when: false
- name: Reboot dengan grace period
ansible.builtin.reboot:
reboot_timeout: 600
pre_reboot_delay: 30
post_reboot_delay: 15
connect_timeout: 30
when: needs_reboot.rc == 1Tip
Beberapa parameter penting modul reboot: pre_reboot_delay memberi waktu 30 detik agar aplikasi drain graceful, post_reboot_delay menunggu sistem benar-benar stabil setelah boot, dan reboot_timeout membatasi waktu tunggu maksimal. Untuk service yang tidak boleh drop, tambahkan task pre-check kesehatan aplikasi (misalnya cek HTTP endpoint) setelah reboot — Ansible punya wait_for yang bisa menunggu port/URL kembali sehat. Kombinasi serial: 1 + drain + health check adalah resep rolling reboot tanpa downtime.
STIG (Security Technical Implementation Guide) adalah standar hardening yang dikeluarkan oleh DISA (Defense Information Systems Agency) Amerika Serikat, diwajibkan untuk semua sistem di lingkungan militer dan pemerintahan, dan banyak diadopsi industri sebagai acuan "hardening tingkat lanjut". Di episode ini cukup kita pahami pola dasarnya: STIG dikategorikan per control (misalnya SV-XXXXX untuk aturan tertentu), dan role seperti ansible-lockdown.stig_rhel9 mengotomasi implementasinya.
Pilar compliance yang kedua adalah audit logging — tanpa log yang baik, kalian tidak bisa membuktikan kepatuhan (atau menemukan jejak serangan). Contoh berikut mengkonfigurasi rsyslog agar log di-forward ke log server terpusat, plus mengaktifkan auditd untuk memantau perubahan file penting:
- name: Konfigurasi audit logging terpusat
hosts: all
become: true
vars:
central_log_host: 10.0.0.50
tasks:
- name: Forward log auth ke server terpusat
ansible.builtin.copy:
dest: /etc/rsyslog.d/60-central.conf
content: |
auth.* @@{{ central_log_host }}:514
kern.* @@{{ central_log_host }}:514
mail.* @@{{ central_log_host }}:514
notify: Restart rsyslog
- name: Pantau integritas file penting dengan auditd
ansible.builtin.copy:
dest: /etc/audit/rules.d/audit.rules
content: |
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k identity
-w /var/log/auth.log -p wa -k authlog
-a always,exit -F arch=b64 -S execve -k process_execution
notify: Restart auditd
handlers:
- name: Restart rsyslog
ansible.builtin.service:
name: rsyslog
state: restarted
- name: Restart auditd
ansible.builtin.service:
name: auditd
state: restartedFile integrity monitoring (FIM) melengkapi audit logging: ia mendeteksi perubahan pada file penting yang seharusnya tidak pernah berubah. AIDE (Advanced Intrusion Detection Environment) adalah pilihan FIM open source yang populer. Alurnya: inisialisasi database baseline → bandingkan berkala → laporkan perbedaan.
- name: Setup AIDE file integrity monitoring
hosts: all
become: true
tasks:
- name: Install AIDE
ansible.builtin.apt:
name: aide
state: present
- name: Inisialisasi database baseline AIDE
ansible.builtin.command: aideinit
args:
creates: /var/lib/aide/aide.db
changed_when: false
- name: Jadwalkan scan harian via cron
ansible.builtin.cron:
name: "AIDE daily integrity check"
minute: "0"
hour: "3"
job: "/usr/bin/aide.wrapper --check | mail -s 'AIDE report' security@example.com"Warning
Prinsip emas FIM: database baseline harus dibuat di sistem yang sudah bersih dan ter-verified, bukan setelah sistem berjalan berbulan-bulan dengan kemungkinan sudah ter-compromise. Setelah inisialisasi, update database baseline secara manual hanya saat perubahan memang disengaja (misalnya deploy baru), dan simpan hash database di lokasi yang sulit diakali penyerang. Kalau tidak, kalian akan tenggelam dalam ratusan false-positive alert setiap hari.
Hardening tanpa verifikasi hanyalah klaim. Scanner keamanan mengubah klaim menjadi bukti: berapa banyak kontrol yang lolos, mana yang gagal, dan mana yang masih rawan. Ansible adalah kendaraan sempurna untuk menjalankan scanner, mengumpulkan hasil, dan membuat laporan di seluruh fleet secara berkala.
OpenSCAP adalah scanner compliance berbasis standar (menjalankan profil seperti CIS, STIG, PCI-DSS) dan menghasilkan laporan dalam format HTML/XML. Lynis adalah scanner audit keamanan yang memberikan hardening index dan rekomendasi berbasis heuristik. Contoh code group berikut menunjukkan keduanya:
- name: Scan compliance dengan OpenSCAP
hosts: rhel_servers
become: true
tasks:
- name: Install openscap-scanner
ansible.builtin.dnf:
name: openscap-scanner
state: present
- name: Jalankan scan profil STIG RHEL 9
ansible.builtin.command:
cmd: >-
oscap xccdf eval
--profile stig
--results /root/scap-results.xml
--report /root/scap-report.html
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
register: scan_result
changed_when: scan_result.rc != 0
- name: Tarik laporan scan ke control node
ansible.builtin.fetch:
src: /root/scap-report.html
dest: "reports/{{ inventory_hostname }}-scap.html"
flat: trueTip
Keluarkan scan secara berkala (misalnya via cron atau pipeline CI/CD pada episode 19) dan jadikan laporannya source of truth untuk audit. Integrasikan nilai kerentanan ke sistem ticketing atau dashboard — misalnya community.general punya modul grafana_dashboard jika kalian ingin memvisualisasikan skor compliance. Yang lebih penting: scan harus di-remediate, bukan sekadar disimpan. Pasangkan hasil scan dengan playbook hardening agar kontrol yang gagal otomatis diperbaiki pada run berikutnya.
1. Hardening langsung di production tanpa staging
Role CIS dan STIG agresif; satu rule bisa mengunci user, mematikan service yang dipakai aplikasi, atau memblokir network. Selalu --check, uji di staging, lalu promote ke production.
2. Lupa menyisakan jalur pemulihan
Sebelum menonaktifkan PasswordAuthentication, pastikan key SSH sudah terpasang di semua host. Sebelum mematikan firewall default policy, pastikan ada akses out-of-band (misalnya IPMI atau console cloud). Satu kesalahan dan kalian terkunci — dan Ansible tidak bisa menolong kalian lagi.
3. Reboot tanpa drain
Reboot semua server sekaligus (serial: 1 diabaikan) menjamin everything down. Selalu batasi batch, beri pre_reboot_delay, dan tunggu health check sebelum melanjutkan ke batch berikutnya.
4. Automated update tanpa monitoring
unattended-upgrades yang berjalan diam-diam tanpa alert sama berbahayanya dengan tidak pernah update. Selalu pantau log update dan verifikasi bahwa service tetap sehat setelah patch.
5. Baseline AIDE dibuat saat sistem sudah "tercemar"
Database FIM hanya berguna jika dibuat dari sistem yang bersih. Dan jangan lupa update baseline saat perubahan disengaja — kalau tidak, noise alert akan membuat kalian mematikan alert-nya (yang jauh lebih berbahaya).
6. Mengandalkan scanner sebagai pengganti hardening
OpenSCAP/Lynis menemukan masalah, bukan memperbaiki masalah. Scanning harus dipasangkan dengan playbook remediation, kalau tidak skor compliance hanyalah angka di dashboard.
Pada episode ini kita telah membahas security hardening dan compliance automation secara menyeluruh: implementasi CIS Benchmark dengan collection ansible-lockdown, hardening SSH dan konfigurasi firewall (UFW, firewalld, iptables), patch management dengan automated security updates dan reboot yang aman, compliance as code untuk STIG, audit logging, dan file integrity monitoring dengan AIDE, serta integrasi scanner keamanan OpenSCAP dan Lynis dengan laporan otomatis. Kita juga menutup dengan kesalahan umum yang sering membuat tim terjebak.
Intinya, keamanan bukanlah produk yang dibeli, melainkan proses yang dijaga terus-menerus — dan Ansible mengubah proses itu dari aktivitas manual yang rawan lupa menjadi sistem deklaratif yang terverifikasi dan bisa diaudit. Dengan kemampuan ini, kalian bisa mengklaim tidak hanya bahwa infrastruktur kalian tersedia, tapi juga terjamin.
Di episode 28 selanjutnya, kita akan membahas topik yang menantang anggapan "Ansible hanya untuk Linux": Windows Automation dengan Ansible — mengelola WinRM, modul ansible.windows dan community.windows, automasi IIS, Windows Update, hingga Active Directory dari control node Linux yang sama. Pastikan tetap semangat!