Validate Ansible templates!
If you've been here previously, you may know about the [1]sudo cake I
had baked and the [2]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 [3]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 [4]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
[5]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.
References
1.
https://jpmens.net/2013/02/12/sudo-bake-me-a-cake/
2.
https://jpmens.net/2013/02/06/don-t-try-this-at-the-office-etc-sudoers/
3.
https://jpmens.net/2012/06/06/configuration-management-with-ansible/
4.
https://www.isc.org/bind/
5.
https://jpmens.net/2012/06/06/configuration-management-with-ansible/