Common Mistake

Common Mistake #

Sebagian besar insiden keamanan dalam otomasi Ansible bukan disebabkan oleh kelemahan kriptografi atau zero-day exploit — melainkan oleh kesalahan konfigurasi yang sederhana dan pola yang tampaknya tidak berbahaya tapi punya konsekuensi serius. Artikel ini mengumpulkan kesalahan keamanan yang paling sering ditemukan, menjelaskan mengapa berbahaya, dan memberikan cara yang benar.

Kesalahan 1: Secret dalam Plaintext di Repository #

Ini adalah kesalahan paling umum dan paling berbahaya:

# ANTI-PATTERN: secret dalam plaintext
# group_vars/production/vars.yml
db_password: MyDatabasePassword123
aws_access_key: AKIAIOSFODNN7EXAMPLE
aws_secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
slack_webhook: https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

Satu kali file ini masuk ke Git, secret tersebut ada di history selamanya — bahkan setelah dihapus di commit berikutnya. Bot pemindai repositori di internet secara aktif mencari pola seperti ini.

# BENAR: gunakan Ansible Vault
# group_vars/production/vault.yml (enkripsi dengan ansible-vault encrypt)
vault_db_password: MyDatabasePassword123

# group_vars/production/vars.yml (plaintext, aman di Git)
db_password: "{{ vault_db_password }}"

Kesalahan 2: Menonaktifkan Host Key Checking di Production #

# ANTI-PATTERN: di ansible.cfg production
[defaults]
host_key_checking = False    # JANGAN di production!

host_key_checking = False memungkinkan man-in-the-middle attack — Ansible akan terhubung ke server manapun yang menjawab, bahkan jika itu bukan server yang seharusnya. Penyerang bisa mengarahkan koneksi ke server mereka sendiri dan menerima semua secret yang dikirim Ansible.

# BENAR: aktifkan di production
[defaults]
host_key_checking = True

# Untuk server baru yang belum ada di known_hosts, gunakan:
[ssh_connection]
ssh_args = -o StrictHostKeyChecking=accept-new
# Ini menerima key baru tapi tetap validasi key yang sudah dikenal

Kesalahan 3: Privilege Escalation yang Terlalu Luas #

# ANTI-PATTERN: sudoers yang terlalu permisif
ansible-deploy ALL=(ALL) NOPASSWD: ALL
# User ansible-deploy bisa melakukan APA SAJA sebagai root

Jika credential ansible-deploy bocor, penyerang mendapat akses root penuh ke semua server. Batasi privilege escalation hanya ke perintah yang benar-benar diperlukan:

# BENAR: sudoers yang spesifik
ansible-deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp
ansible-deploy ALL=(ALL) NOPASSWD: /usr/bin/pip3 install -r /opt/app/requirements.txt
ansible-deploy ALL=(ALL) NOPASSWD: /usr/bin/rsync --archive /tmp/release/ /opt/app/

Kesalahan 4: Variabel Sensitif di Log #

# ANTI-PATTERN: task yang menampilkan secret di output
- name: Konfigurasi database
  command: mysql -u root -p{{ db_root_password }} -e "CREATE USER..."
  # Jika task ini gagal, Ansible menampilkan command lengkap beserta password!

- name: Debug nilai variabel
  debug:
    var: hostvars[inventory_hostname]
  # Ini menampilkan SEMUA variabel termasuk yang sensitif!
# BENAR: sembunyikan output yang sensitif
- name: Konfigurasi database
  command: mysql -u root -p{{ db_root_password }} -e "CREATE USER..."
  no_log: true    # Jangan tampilkan apapun dari task ini

- name: Debug variabel (tanpa yang sensitif)
  debug:
    msg: "Deploy ke {{ inventory_hostname }} dengan user {{ deploy_user }}"
  # Hanya tampilkan yang memang aman ditampilkan

Kesalahan 5: Tidak Mem-pin Versi Role dan Collection #

# ANTI-PATTERN: tanpa pin versi
# requirements.yml
roles:
  - name: geerlingguy.nginx
    # Tidak ada version — selalu ambil terbaru

# Konsekuensi:
# Hari ini: role v3.2 berjalan normal
# Besok: role v3.3 dirilis, CI/CD mengambil versi baru
# Role baru mengubah nama variabel → playbook break
# Tidak ada yang tahu kenapa pipeline tiba-tiba gagal
# BENAR: pin versi secara eksplisit
roles:
  - name: geerlingguy.nginx
    version: "3.2.0"    # Pin ke versi yang sudah ditest

Kesalahan 6: Menjalankan Playbook Langsung ke Production tanpa Staging #

# ANTI-PATTERN: langsung ke production
ansible-playbook -i inventory/production/ site.yml

# Konsekuensi: bug di playbook langsung merusak production
# Tidak ada cara tahu dampaknya sebelum terjadi
# BENAR: staging dulu, production setelah dikonfirmasi
# Langkah 1: Deploy ke staging
ansible-playbook -i inventory/staging/ site.yml

# Langkah 2: Verifikasi staging berjalan normal
# ... test manual atau otomatis ...

# Langkah 3: Dry run ke production
ansible-playbook -i inventory/production/ site.yml --check --diff

# Langkah 4: Deploy ke production
ansible-playbook -i inventory/production/ site.yml

Kesalahan 7: Menggunakan become: true di Semua Task #

# ANTI-PATTERN: semua task berjalan sebagai root
- name: Deploy aplikasi
  hosts: appservers
  become: true      # Root untuk semua task — termasuk yang tidak memerlukannya

  tasks:
    - name: Install nginx (perlu root)
      apt:
        name: nginx
        state: present

    - name: Deploy kode aplikasi (tidak perlu root!)
      git:
        repo: https://github.com/org/app.git
        dest: /opt/app   # Sekarang direktori ini dimiliki root
# BENAR: escalate privilege hanya saat diperlukan
- name: Deploy aplikasi
  hosts: appservers
  become: false     # Default: tanpa sudo

  tasks:
    - name: Install nginx (perlu root)
      apt:
        name: nginx
        state: present
      become: true    # Eskalasi hanya untuk task ini

    - name: Deploy kode aplikasi (sebagai user deployer)
      git:
        repo: https://github.com/org/app.git
        dest: /opt/app
      become_user: deployer   # Jalankan sebagai deployer, bukan root
      become: true

Ringkasan #

  • Jangan pernah commit secret dalam plaintext — gunakan Ansible Vault atau external secret manager. Secret di Git history tidak bisa benar-benar dihapus.
  • host_key_checking = False dilarang di production — ini membuka celah man-in-the-middle attack.
  • Sudoers harus spesifik — bukan NOPASSWD: ALL, tapi hanya perintah yang benar-benar diperlukan.
  • no_log: true untuk semua task yang menangani secret — log adalah storage persistent yang sering diabaikan.
  • Pin versi semua role dan collection eksternal — tanpa pin, update otomatis bisa membreak playbook kapan saja.
  • Selalu test di staging sebelum production — tidak ada alasan yang cukup kuat untuk skip langkah ini.
  • Eskalasi privilege hanya saat diperlukan — jangan become: true di level play jika hanya satu-dua task yang membutuhkannya.

← Sebelumnya: SSH Security   Berikutnya: Provision Host →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact