Running pkg audit From Ansible

by Tykling


25. feb 2018 13:10 UTC


The nature of Ansible is that it connects to the hosts in its inventory files over SSH. This opens up some new possibilities since I now have a place which has SSH access to the rest of the infrastructure, which I can use to automate various monitoring scripts.

I've recently added this script to my Ansible roles and wanted to post it here. It is very simple, nothing fancy about it, it just loops over the hostnames found in the Ansible inventory files, SSHs into each (using Ansibles shell module, and runs pkg audit -F. If a problem is found it sends the output in an email to the email address specified on the commandline.

My ansible_server Ansible role adds this script to crontab on the Ansible servers on the different infrastructures I manage. This means that I get an email if one or more vulnerable packages was found on a server.

The same information is available in the FreeBSD daily periodic security run output emails, but since those mails come every night, and not only when something needs to be acted on, they tend to get overlooked.

Enough talk, here is the code:

#!/bin/sh

# the main function
check_inventory() {
        # find unique hosts in ansible inventory file and loop over them
        for host in $(grep -Ev "(\\[|^#|^$)" "$1" | sort | uniq); do
                # get the pkg audit output, run with -F to ensure we have a fresh vuln xml
                output=$(/usr/local/bin/ansible "$host" -m shell -b -a "/usr/sbin/pkg audit -F" -i "$1")
                if [ $? -ne 0 ]; then
                        # vulns found, or ansible could not connect, send email regardless
                        echo "$output" | mail -s "$(basename "$1") - $host: Vulnerable packages found!" "$2"
                fi
        done
}

# do we have an email?
if [ $# -ne 1 ]; then
        echo "usage: $0 "
        exit 1
fi

# loop over inventory files and check them
for file in /usr/local/etc/ansible/*_hosts; do
        check_inventory "$file" "$1"
done

By convention my Ansible inventory files are called production_hosts, staging_hosts and so on, so the glob in the script is *_hosts, YMMV.

Search this blog

Tags for this blogpost