Security Anti Pattern

Security Anti Pattern #

Keamanan infrastruktur adalah fondasi utama dari seluruh siklus hidup pengembangan sistem dan operasi (DevOps). Saat kita mengotomatiskan pengelolaan server menggunakan Ansible, setiap keputusan konfigurasi yang kita ambil dapat berdampak besar pada postur keamanan sistem secara keseluruhan. Berbeda dengan kesalahan sintaksis atau error eksekusi biasa yang langsung menghentikan jalannya playbook, anti pattern keamanan sering kali berjalan lancar tanpa memicu error apa pun. Namun, celah tersembunyi ini membuka pintu lebar-lebar bagi potensi pelanggaran data, eskalasi hak akses, hingga kompromi total pada infrastruktur kita.

Satu kata sandi atau kunci privat yang tidak sengaja ter-commit ke repositori Git publik dapat dieksploitasi oleh bot pemindai otomatis dalam hitungan detik. Menonaktifkan verifikasi kunci host SSH secara global di lingkungan produksi menghilangkan perlindungan kita dari serangan penyadapan aktif. Terlalu malas membatasi hak akses perintah sudo membuat akun otomasi kita menjadi titik masuk yang sangat rentan. Melalui pembahasan mendalam ini, kita akan mengupas tuntas berbagai anti-pattern keamanan kritis di Ansible, memahami risiko di baliknya, dan mempelajari langkah konkret untuk mengimplementasikan solusi yang aman dan andal.


1. Menyimpan Secret secara Terbuka di Repositori Git #

Menyimpan informasi sensitif seperti kata sandi database, API key, sertifikat SSL privat, atau credential cloud provider dalam format teks polos (plaintext) di dalam file konfigurasi Ansible yang masuk ke kontrol versi Git adalah salah satu kesalahan paling fatal. Repositori Git dirancang untuk merekam riwayat perubahan selamanya, sehingga menghapus file atau baris secret di commit terbaru tidak akan menghilangkannya dari riwayat Git (git history).

Mengapa Ini Berbahaya? #

Setiap developer atau sistem CI/CD yang memiliki akses ke repositori dapat melihat credential tersebut. Jika repositori tersebut bersifat publik atau tidak sengaja terekspos, pihak luar dapat langsung mengambil kendali atas infrastruktur kita. Bahkan pada repositori privat sekalipun, kebocoran credential internal tetap melanggar prinsip kepatuhan (compliance) dan mempermudah pergerakan lateral (lateral movement) bagi penyerang yang berhasil masuk ke jaringan internal kita.

# ANTI-PATTERN: Menyimpan secret langsung di file konfigurasi yang masuk Git
# File: group_vars/all.yml
db_password: "super_secret_password_123"      # ✗ JANGAN: Password plaintext langsung terbaca
api_key: "sk-live-abc123def456"               # ✗ JANGAN: API key sensitif terekspos
aws_secret_key: "wJalrXUtnFEMI/K7MDENG"      # ✗ JANGAN: Kredensial cloud provider bocor

# File: ansible.cfg
[defaults]
vault_password_file = ~/.vault_pass   # ✗ JANGAN: Berisiko ter-commit jika tidak dikecualikan di .gitignore
# BENAR: Menggunakan Ansible Vault untuk mengenkripsi informasi sensitif
# File: group_vars/all.yml (Aman untuk di-commit ke Git)
db_user: "appuser"
db_host: "{{ vault_db_host }}"                 # ✓ Merujuk ke variabel terenkripsi
db_password: "{{ vault_db_password }}"         # ✓ Merujuk ke variabel terenkripsi

# File: group_vars/vault.yml (Dibuat dan diedit dengan 'ansible-vault encrypt')
# Semua data di bawah ini telah dienkripsi dengan algoritma AES-256
vault_db_host: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          65383561333765333737656662366164626135663737383062326532653262336336626535646132
          3964353434653838613134373461623861643431613133330a616263303863643765343536396465
          6661646364356464613361626364313233343536373839300a396263646566313233343536373839
vault_db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          31353930613765333737656662366164626135663737383062326532653262336336626535646132
          3964353434653838613134373461623861643431613133330a616263303863643765343536396465
          6661646364356464613361626364313233343536373839300a396263646566313233343536373839

# File: .gitignore
# Mengecualikan semua file yang menyimpan password vault lokal secara eksplisit
.vault_pass
*.vault_pass
secrets/*.vault_pass

Memeriksa dan Membersihkan Kebocoran Git #

Jika kita mencurigai adanya secret yang telah bocor ke dalam riwayat Git, kita harus bertindak cepat dengan melakukan pemindaian riwayat komit menggunakan alat bantu seperti git log atau utilitas khusus seperti gitleaks.

# Mencari string sensitif di seluruh riwayat komit Git
git log --all --full-history -- "**/*secret*" "**/*password*" "**/*key*"

# Menggunakan ekspresi reguler untuk melacak potensi kebocoran token atau password
git grep -i "password\|secret\|api_key\|aws_" $(git log --format="%H") 2>/dev/null | head -20

[!CAUTION] Jika secret telah terlanjur masuk ke repositori Git yang di-push ke remote, kita wajib segera merotasi semua credential tersebut. Mengedit commit atau menghapusnya dengan force push tidak menjamin data tersebut belum disalin oleh pihak lain. Gunakan alat seperti git-filter-repo atau BFG Repo-Cleaner untuk membersihkan riwayat Git lokal secara permanen sebelum melakukan push paksa.


2. Menonaktifkan Host Key Checking (host_key_checking = False) di Production #

Demi kemudahan saat melakukan provisioning awal pada banyak server baru, banyak administrator mematikan pemeriksaan kunci host SSH (host_key_checking = False) di konfigurasi ansible.cfg atau melalui variabel lingkungan.

Mengapa Ini Berbahaya? #

SSH Host Key Checking berfungsi untuk memvalidasi identitas server tujuan sebelum bertukar credential enkripsi dan sesi data. Ketika opsi ini dinonaktifkan, Ansible akan menerima kunci host apa pun secara membabi buta tanpa mencocokkannya dengan database known_hosts. Hal ini membuka celah keamanan bagi serangan Man-in-the-Middle (MITM). Penyerang yang berada di jalur jaringan yang sama (misalnya melalui DNS spoofing atau ARP poisoning) dapat membelokkan lalu lintas SSH ke server mereka sendiri, menangkap credential login, dan memanipulasi task yang dijalankan oleh Ansible.

# ANTI-PATTERN: Mematikan host key checking secara global di lingkungan produksi
# File: ansible.cfg
[defaults]
host_key_checking = False    # ✗ JANGAN: Membuka celah serangan Man-in-the-Middle (MITM)
# ANTI-PATTERN: Mematikan pemeriksaan secara inline dalam task
- name: Eksekusi command langsung di server remote
  command: ssh [email protected] "systemctl restart app"
  environment:
    ANSIBLE_HOST_KEY_CHECKING: "False"  # ✗ JANGAN: Bypass keamanan SSH host key

Untuk mengatasinya, kita harus mengelola host key server dengan benar. Pada saat provisioning pertama kali, kita bisa mengambil host key server secara otomatis lalu menyimpannya di file known_hosts lokal, atau memanfaatkan mode penerimaan host key yang lebih aman.

# BENAR: Melakukan verifikasi host key dan menambahkannya ke known_hosts sebelum play utama dijalankan
- name: Inisialisasi Kunci Host SSH secara Aman
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Ambil host key terbaru dari server target dan daftarkan ke known_hosts
      known_hosts:
        name: "{{ item }}"
        key: "{{ lookup('pipe', 'ssh-keyscan -t rsa,ecdsa,ed25519 ' + item) }}"
        state: present
      loop: "{{ groups['production'] }}"
      run_once: true

# Alternatif untuk lingkungan dinamis (misalnya pipeline CI/CD dengan ephemeral runner)
# File: ansible.cfg (Gunakan accept-new, bukan mematikan total verifikasi)
[ssh_connection]
ssh_args = -o StrictHostKeyChecking=accept-new
# ✓ BENAR: Opsi "accept-new" secara otomatis menyimpan key baru yang belum pernah dilihat,
# tetapi tetap menolak dan memutus koneksi jika key server yang sudah ada tiba-tiba berubah.

Berikut adalah visualisasi alur pengambilan keputusan SSH Client saat memverifikasi Host Key server target:

flowchart TD
    Start["Control Node menginisiasi koneksi SSH"] --> Check["Apakah Host Key ada di known_hosts?"]
    Check -- "Ya, cocok" --> Success["Koneksi aman terjalin"]
    Check -- "Ya, tapi tidak cocok (berubah)" --> Warning["SSH Warning: Kemungkinan MITM Attack!"]
    Warning --> Fail["Koneksi diputus oleh SSH client"]
    Check -- "Tidak ada" --> Policy{"Bagaimana kebijakan host_key_checking?"}
    Policy -- "True (Default)" --> Reject["Koneksi ditolak / Meminta konfirmasi interaktif"]
    Policy -- "accept-new" --> Save["Simpan Host Key baru ke known_hosts & Lanjutkan"]
    Policy -- "False" --> Bypass["Abaikan verifikasi & Teruskan koneksi"]
    Bypass -. "Rentan terhadap penyadapan / MITM!" .-> Success

3. Eskalasi Hak Akses Global dengan Privilege Escalation Berlebihan #

Menyetel parameter become: true di tingkat teratas (play-level) agar semua task berjalan sebagai root adalah kebiasaan buruk yang sering kita temui. Hal ini sering dilakukan karena rasa malas mengidentifikasi task mana saja yang sebenarnya membutuhkan hak akses tinggi.

Mengapa Ini Berbahaya? #

Prinsip Least Privilege (Hak Akses Minimum) mengajarkan kita untuk memberikan hak akses administratif hanya saat benar-benar dibutuhkan. Jika kita menerapkan become: true secara global, task sederhana seperti membaca file konfigurasi lokal, mengunduh artifact aplikasi, atau mencetak status debugging akan berjalan dengan privilese root. Jika terjadi bug atau kesalahan logika pada task tersebut (misalnya task yang menghapus folder sementara), dampaknya bisa merusak seluruh sistem operasi karena dieksekusi dengan hak akses penuh. Selain itu, jika modul pihak ketiga yang kita unduh dari Ansible Galaxy ternyata disusupi kode jahat (malware), kode tersebut akan langsung mendapatkan akses root pada host kita.

# ANTI-PATTERN: Menerapkan become secara global di level play
- name: Konfigurasi dan Deploy Aplikasi Web
  hosts: webservers
  become: true      # ✗ JANGAN: Semua task di bawah ini akan berjalan sebagai root secara default
  tasks:
    - name: Unduh source code aplikasi dari repositori internal
      git:
        repo: "https://git.company.internal/app/web.git"
        dest: "/var/www/myapp"
      # Task ini tidak membutuhkan root jika folder /var/www/myapp dimiliki oleh user deployer

    - name: Salin file konfigurasi nginx
      template:
        src: "nginx.conf.j2"
        dest: "/etc/nginx/nginx.conf"
      # Hanya task ini yang memerlukan hak akses administratif root

    - name: Jalankan validasi konfigurasi lokal aplikasi
      command: "npm run test"
      become_user: "appuser"  # Terlalu ribet mengubah user kembali karena become: true sudah di-set di atas
# BENAR: Menjalankan playbook dengan hak akses biasa dan mengaktifkan become per task
- name: Konfigurasi dan Deploy Aplikasi Web secara Aman
  hosts: webservers
  become: false     # ✓ BENAR: Default jalankan task dengan user SSH biasa (non-root)
  tasks:
    - name: Pastikan direktori aplikasi dimiliki oleh user pengelola
      file:
        path: "/var/www/myapp"
        state: directory
        owner: "deployer"
        group: "deployer"
        mode: "0755"
      become: true  # ✓ Aktifkan root privilege hanya untuk setup kepemilikan direktori

    - name: Unduh source code aplikasi (tanpa become)
      git:
        repo: "https://git.company.internal/app/web.git"
        dest: "/var/www/myapp"
      # Berjalan sebagai user deployer biasa (non-root), meminimalkan risiko keamanan

    - name: Salin file konfigurasi nginx (butuh root)
      template:
        src: "nginx.conf.j2"
        dest: "/etc/nginx/nginx.conf"
      become: true  # ✓ Aktifkan root privilege hanya untuk menulis ke direktori sistem /etc

    - name: Restart service nginx (butuh root)
      systemd:
        name: nginx
        state: restarted
      become: true  # ✓ Aktifkan root privilege hanya untuk berinteraksi dengan systemd

4. Konfigurasi Sudoers di Managed Node yang Terlalu Permisif #

Agar Ansible dapat mengelola server jarak jauh tanpa kendala interaktif, kita sering kali mengonfigurasi user Ansible di file /etc/sudoers atau direktori /etc/sudoers.d/ pada target host agar dapat menggunakan perintah sudo tanpa memerlukan input password.

Mengapa Ini Berbahaya? #

Jika konfigurasi sudo diset terlalu bebas (misalnya ALL=(ALL) NOPASSWD: ALL), kita telah memberikan kekuasaan mutlak yang tidak terkontrol. Apabila laptop control node milik kita kompromi, atau SSH key yang digunakan untuk mengakses server dicuri, penyerang langsung memiliki kendali administratif tak terbatas atas seluruh server remote tanpa hambatan verifikasi tambahan. Ini juga menyulitkan audit keamanan karena tidak ada pembatasan perintah yang jelas.

# ANTI-PATTERN: Memberikan hak sudo tanpa batasan perintah di server remote
# File: /etc/sudoers.d/ansible
ansible ALL=(ALL) NOPASSWD: ALL    # ✗ JANGAN: Memberikan akses root tanpa batas dan tanpa password

Untuk meningkatkan keamanan infrastruktur, kita harus membatasi perintah sudo yang boleh dieksekusi oleh user otomasi kita. Buat daftar perintah spesifik yang benar-benar dibutuhkan oleh playbook kita untuk dijalankan dengan hak akses tinggi.

# BENAR: Membatasi izin sudo hanya untuk perintah administratif yang spesifik
# File: /etc/sudoers.d/ansible
ansible ALL=(ALL) NOPASSWD: /usr/bin/apt-get update, /usr/bin/apt-get install -y *, /bin/systemctl restart nginx, /bin/systemctl status nginx, /bin/systemctl reload nginx, /usr/bin/systemd-tmpfiles *
# ✓ BENAR: User ansible hanya bisa menjalankan perintah paket manager dan manajemen service nginx sebagai root.
# Semua upaya menjalankan perintah lain (seperti sudo su, sudo vi, atau sudo rm -rf /) akan langsung ditolak.

Selain pembatasan perintah, jika playbook kita tidak memerlukan eksekusi dinamis pada sistem host yang dalam (deep system configuration), kita dapat mempertimbangkan penggunaan password vault untuk memverifikasi eksekusi privilege escalation.

# BENAR: Memerlukan password sudo yang aman dari Ansible Vault
# File: group_vars/all.yml
# Simpan password sudo user ansible dalam variabel terenkripsi vault
ansible_become_password: "{{ vault_ansible_become_password }}"

# Saat menjalankan playbook, pastikan password dilewatkan dengan aman melalui vault
# ansible-playbook -i inventory/production/ site.yml --ask-vault-pass

5. Kebocoran Informasi Sensitif pada Output Log dan Debug #

Ansible secara default mencatat semua detail eksekusi task, termasuk argumen yang dikirim ke modul, variabel yang digunakan, serta output standar (stdout dan stderr) ke layar konsol terminal dan file log yang dikonfigurasi.

Mengapa Ini Berbahaya? #

Saat kita mengeksekusi modul seperti command atau shell yang membawa parameter sensitif (misalnya password database atau token API), nilai tersebut akan terpampang jelas di output konsol. Kredensial ini juga akan tersimpan dalam riwayat log sistem CI/CD, log server pusat, atau file dump log lokal yang dapat dibaca oleh tim operasional lain atau pihak ketiga yang memiliki akses ke sistem monitoring.

# ANTI-PATTERN: Mengekspos kredensial ke log eksekusi
- name: Hubungkan dan inisialisasi schema database
  command: >
    psql postgresql://{{ db_user }}:{{ db_password }}@{{ db_host }}/{{ db_name }}
    -c "CREATE EXTENSION IF NOT EXISTS citext;"    
  # ✗ JANGAN: db_password akan langsung tertulis di output log terminal jika terjadi kegagalan atau verbose mode aktif

- name: Konfigurasi file konfigurasi environment aplikasi
  lineinfile:
    path: "/home/appuser/app/.env"
    line: "STRIPE_API_KEY={{ stripe_api_key }}"
  # ✗ JANGAN: Perubahan lineinfile ini akan menampilkan nilai token stripe_api_key pada diff output Ansible

Solusi untuk masalah ini adalah dengan menggunakan parameter no_log: true pada setiap task yang menangani data sensitif. Ini akan menginstruksikan Ansible untuk menyembunyikan semua parameter input dan output task tersebut dari sistem log.

# BENAR: Menyembunyikan parameter sensitif dengan no_log
- name: Hubungkan dan inisialisasi schema database (Sembunyikan kredensial)
  command: >
    psql postgresql://{{ db_user }}:{{ db_password }}@{{ db_host }}/{{ db_name }}
    -c "CREATE EXTENSION IF NOT EXISTS citext;"    
  no_log: true # ✓ BENAR: Menyembunyikan log command yang membawa kredensial plaintext

- name: Konfigurasi file konfigurasi environment aplikasi
  lineinfile:
    path: "/home/appuser/app/.env"
    line: "STRIPE_API_KEY={{ stripe_api_key }}"
  no_log: true # ✓ BENAR: Mencegah output diff menampilkan API key asli

# Cara menangani debugging pada task yang menggunakan no_log
- name: Jalankan registrasi agent cloud secara aman
  uri:
    url: "https://api.cloudprovider.com/v1/register"
    method: POST
    body_format: json
    headers:
      Authorization: "Bearer {{ secure_api_token }}"
    body:
      instance_id: "{{ ansible_machine_id }}"
  no_log: true
  register: registration_result

- name: Tampilkan status hasil registrasi (Tanpa menampilkan token api)
  debug:
    msg: "Registrasi selesai. Status HTTP: {{ registration_result.status }}. Pesan: {{ registration_result.json.message | default('Tidak ada pesan') }}"
  # ✓ BENAR: Kita tetap bisa melakukan debugging status tanpa mengekspos token otorisasi asli

6. Mengabaikan Validasi Input Eksternal yang Berpotensi Command Injection #

Ansible sering kali dipicu dari sistem luar, seperti form input di Jenkins/GitLab CI, webhook eksternal, atau input langsung developer melalui opsi extra variables (-e atau --extra-vars).

Mengapa Ini Berbahaya? #

Jika kita langsung menggunakan variabel masukan eksternal tersebut ke dalam directive penting seperti nama host target (hosts:) atau argumen eksekusi perintah shell tanpa validasi ketat, sistem kita rentan terhadap Command Injection atau eksekusi playbook yang salah sasaran. Contohnya, jika penyerang menyisipkan karakter pemisah perintah seperti ; atau && ke dalam variabel input, mereka dapat mengeksekusi perintah arbitrer di server control node maupun target host dengan hak akses Ansible.

# ANTI-PATTERN: Menerima input dari luar secara langsung tanpa validasi
- name: Pemeliharaan Server Dinamis
  hosts: "{{ target_hosts }}"   # ✗ JANGAN: Jika target_hosts diisi 'all', playbook akan berjalan di seluruh server!
  tasks:
    - name: Jalankan skrip kustom pemeliharaan
      shell: "bash /opt/scripts/cleanup.sh --user {{ user_input }}"
      # ✗ JANGAN: Jika user_input diisi '; rm -rf / ;', perintah ini akan merusak server remote!

Untuk mengamankan playbook kita dari input berbahaya, kita wajib menyaring dan memvalidasi setiap variabel eksternal di awal eksekusi (pre_tasks) menggunakan modul assert.

# BENAR: Validasi ketat semua variabel eksternal sebelum eksekusi utama
- name: Pemeliharaan Server Dinamis secara Aman
  hosts: all
  gather_facts: false
  pre_tasks:
    - name: Pastikan parameter target_host telah didefinisikan dengan benar
      assert:
        that:
          - target_host is defined
          - target_host != ""
          - target_host in groups['all']
        fail_msg: "Target host '{{ target_host | default('KOSONG') }}' tidak terdaftar di inventory!"
      delegate_to: localhost
      run_once: true

    - name: Validasi username agar hanya berisi karakter alfanumerik aman (mencegah injection)
      assert:
        that:
          - user_input is defined
          - user_input is match('^[a-zA-Z0-9_-]+$')
        fail_msg: "User input '{{ user_input | default('') }}' tidak valid! Hanya karakter alfanumerik, dash, dan underscore yang diizinkan."
      delegate_to: localhost
      run_once: true

  tasks:
    - name: Jalankan skrip kustom pemeliharaan (Sekarang aman dari command injection)
      shell: "bash /opt/scripts/cleanup.sh --user {{ user_input }}"
      # Jalankan task ini hanya pada host yang divalidasi
      when: inventory_hostname == target_host

7. Penggunaan Protokol SSH dengan Konfigurasi Tidak Aman #

Ansible sangat bergantung pada kekuatan dan keamanan protokol SSH untuk berkomunikasi dengan server remote. Namun, kita sering kali mengabaikan konfigurasi SSH pada tingkat sistem dan membiarkan Ansible menggunakan nilai default bawaan OS yang mungkin sudah usang.

Mengapa Ini Berbahaya? #

Jika control node dan server target menegosiasikan enkripsi menggunakan cipher lama yang lemah (seperti 3DES, RC4, atau Blowfish) atau metode pertukaran kunci yang rentan (seperti Diffie-Hellman Group 1 SHA1), sesi komunikasi kita dapat didekripsi oleh penyerang yang mampu menyadap lalu lintas jaringan. Begitu pula jika port SSH dibiarkan standar (22) tanpa proteksi brute force atau mengizinkan login root langsung menggunakan password.

Kita harus memperketat konfigurasi koneksi SSH baik di ansible.cfg maupun konfigurasi server target.

# BENAR: Mengonfigurasi parameter SSH yang aman di ansible.cfg
# File: ansible.cfg
[ssh_connection]
# Aktifkan pipelining dan batasi opsi SSH argumen ke cipher modern
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -o [email protected],diffie-hellman-group16-sha512 -o [email protected],[email protected]
# Opsi di atas memaksa SSH menggunakan algoritma pertukaran kunci kurva eliptik yang sangat kuat dan cipher modern tahan dekripsi.

Untuk menerapkan standarisasi SSH yang aman di seluruh infrastruktur target, kita harus menggunakan playbook khusus untuk mengonfigurasi daemon SSH (sshd_config).

# BENAR: Menerapkan konfigurasi SSH Daemon yang aman di managed node
- name: Amankan Layanan SSH di Server Remote
  hosts: all
  become: true
  tasks:
    - name: Nonaktifkan login root langsung menggunakan password
      lineinfile:
        path: "/etc/ssh/sshd_config"
        regexp: "^#?PermitRootLogin"
        line: "PermitRootLogin prohibit-password"
        state: present
      notify: Reload SSH Service

    - name: Matikan autentikasi password polos (Paksa penggunaan SSH Key)
      lineinfile:
        path: "/etc/ssh/sshd_config"
        regexp: "^#?PasswordAuthentication"
        line: "PasswordAuthentication no"
        state: present
      notify: Reload SSH Service

    - name: Batasi cipher SSH yang lemah di sisi server
      lineinfile:
        path: "/etc/ssh/sshd_config"
        regexp: "^#?Ciphers"
        line: "Ciphers [email protected],[email protected],[email protected]"
        state: present
      notify: Reload SSH Service

  handlers:
    - name: Reload SSH Service
      systemd:
        name: sshd
        state: reloaded

Ringkasan #

  • Ansible Vault Wajib Digunakan — Kredensial sensitif seperti kata sandi dan API token tidak boleh disimpan secara plaintext di repositori Git. Lakukan enkripsi file menggunakan Ansible Vault dan pastikan file password lokal terdaftar di .gitignore.
  • Pertahankan Pemeriksaan Kunci Host SSH — Hindari menonaktifkan host_key_checking = False di lingkungan produksi karena membuka celah serangan Man-in-the-Middle (MITM). Gunakan opsi StrictHostKeyChecking=accept-new untuk runner CI/CD ephemeral.
  • Batasi Privilege Escalation dengan Tepat — Jangan gunakan deklarasi become: true secara global di level play. Aktifkan privilege root secara spesifik hanya pada task yang benar-benar memerlukan akses administratif tinggi.
  • Terapkan Prinsip Sudoers Terbatas — Konfigurasikan file sudoers pada server remote agar hanya mengizinkan user Ansible mengeksekusi perintah administratif tertentu dengan opsi NOPASSWD, hindari pemberian akses universal ALL.
  • Gunakan no_log: true untuk Mencegah Kebocoran Kredensial — Sembunyikan parameter input dan output yang sensitif dari log stdout/stderr dan log sistem CI/CD menggunakan opsi no_log: true pada task yang relevan.
  • Validasi Ketat Input Eksternal — Lindungi sistem dari celah command injection dengan memvalidasi setiap parameter masukan dari extra variables (-e) menggunakan modul assert dengan ekspresi reguler.
  • Perketat Protokol SSH secara Konsisten — Konfigurasikan ssh_args di ansible.cfg untuk memaksa penggunaan algoritma pertukaran kunci (KexAlgorithms) dan cipher modern yang aman, serta nonaktifkan login password langsung di managed node.

← Sebelumnya: Variable Anti Pattern   Berikutnya: Performance Anti Pattern →

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