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/