If you’ve been here previously, you may know about the sudo cake I had baked and the reason I had it baked. Current events make me want to point out again how important it is to validate files you push out to machines with Ansible. Case in point is a shop which brought down a group of DNS servers by pushing out a broken configuration file.
Consider this Ansible playbook, and in particular, the template action:
---
- hosts: bindservers
user: root
vars:
- checkconf: /usr/sbin/named-checkconf
tasks:
- name: Install and validate named.conf
action: template src=named.conf.j2 dest=/etc/named.conf validate='{{ checkconf }} %s'
The validate
option (also available for the copy command) specifies a
validation command which will be run when Ansible creates (i.e. copies) the
template to the target machine, but before that is moved into it’s final
_dest_ination. If this command fails (a single %s
is replaced by the
filename) the whole task fails, which is good: the _dest_ination file is not
modified. Here’s an example of the task failing:
TASK: [Install and validate named.conf] ***************************************
failed: [ns03] => {"failed": true}
msg: failed to validate: rc:1 error:
FATAL: all hosts have already failed -- aborting
and here is the task passing validation:
TASK: [Install and validate named.conf] ***************************************
changed: [ns03]
In this particular example I’m lucky because the BIND nameserver package actually has a program which can perform a validation check on its own configuration. (Just as sudo can with its visudo program, as I learned the hard way …) If that weren’t possible, I might want to create some script which does it for me and install that as an early Ansible task.
Here’s another template task with which I’ve deployed a syslog-ng configuration; it also validates the templated configuration file before installing it at its final destination.
- name: Install syslog-ng.conf from template
action: template >
src=syslog-ng.conf.in
dest=/etc/syslog-ng/syslog-ng.conf
owner=root
group=root
mode=644
backup=yes
validate="/sbin/syslog-ng -F -s -f %s"
notify: restart syslog
This is just a friendly reminder.