Hardening playbooks & the controller

become, SSH, and control-node risk.

Advanced14 min · lesson 11 of 12

Ansible’s power — pushing privileged changes to every host — is also its risk surface, and hardening splits into the playbooks and the control node. In playbooks, privilege escalation is become (usually sudo to root); grant it per-task where possible rather than globally, avoid the shell module (which sidesteps idempotency and is easy to misuse), and put no_log: true on any task handling secrets so they do not appear in output or logs.

play
- name: Write a credential file (do not leak it to the log)
ansible.builtin.copy:
dest: /etc/app/creds
content: "{{ vaulted_api_key }}"
mode: "0600"
no_log: true # keep the secret out of stdout and logs
become: true # escalate only for the task that needs it

The control node and SSH

The control node holds the keys to the fleet, so treat it as a bastion: restrict who can use it, protect the SSH private keys and Vault password, and prefer an SSH agent or a hardware-backed key over a plaintext key on disk. Verify host keys (do not disable host-key checking to “make it work” — that invites man-in-the-middle), and keep the become method auditable so privileged changes are attributable.

ansible.cfg
[defaults]
host_key_checking = True # never set to False in production
[privilege_escalation]
become = False # opt in per play/task, not globally
[ssh_connection]
pipelining = True # fewer round-trips; keep control-node access tight
host_key_checking = False is a MITM invitation
Disabling host-key checking to silence a prompt tells Ansible to trust any host that answers on that address — exactly what an attacker impersonating a host wants, and now you are handing them root via become. Keep host-key checking on, manage known_hosts properly, and treat any advice to disable it as a red flag rather than a fix.