Deploying Security Controls with Ansible

I use several tools for various security or compliance controls on production Linux servers. Some of those aren't automatically installed/maintained through our package management utility, and with 100+ machines it is far too time-consuming to manually deal with each one. I've started experimenting with Ansible to simplify this and thought I'd share the first role I've written while I'm learning.

Identify Tools and Required Tasks

The first step was to identify what tools I wanted the playbook to manage, and what steps I take to install and configure them. Two tools I use that aren't managed by Spacewalk are Samhain and M/Monit.

Samhain

We currently deploy Samhain in a simple standalone fashion that logs locally, then those logs get picked up by our SIEM. I download and compile Samhain from source but don't use a ton of options at compile time as we aren't currently running a Yule server. That means the required tasks are pretty simple:

Download Samhain

Extract & verify PGP signature

Configure, compile, install

Copy in preferred config

Initialize or re-initialize file signature database

Start the daemon

I opted to split these steps into two tasks named install and update.

M/Monit

M/Monit is just a centralized dashboard used to manage multiple instances of the Linux utility monit. Setting this up just requires customizing the monit configuration file with M/Monit server details and any custom services you want to manage. The tasks here include:

Make sure monit is installed

Backup current/default monitrc

Install new monitrc from template

Start or restart the service

Create Ansible role structure

Now it's time to create the folder hierarchy for our Ansible job. When using roles, Ansible expects certain files to exist in specific directories and will automatically pull in your variable files, handlers, templates, etc. If you're unfamiliar, read up on roles here.

Pretty simple, right? I added tags so that I can pick and choose which roles I want to run as this project expands. For example I can run just the monit role with the command ansible-playbook main.yml --tags monit.

Roles in Detail

Monit

Let's take a closer look at each role now, starting with Monit. Here's the roles/monit/tasks/main.yml task file:

You can see it referencing the variable {{ monitrc_path }}, template file monitrc.j2, and handlers stop monit service and start monit service. Ansible automatically pulls these in from roles/monit/vars/main.yml, roles/monit/templates/, and roles/monit/handlers/main.yml, respectively.

The vars file contains a single line: monitrc_path: /etc/monitrc

I won't attach the entire monitrc template, but it just substitutes a single variable from the facts Ansible gathers on each host when first running a playbook. Example:

set httpd port 2812 and
use address {{ ansible_default_ipv4.address }}

Samhain

Now for a quicker look at the Samhain role. Here are the contents of roles/samhain/tasks/main.yml:

---
- include: install.yml
- include: update.yml

This simply calls the separate install and update tasks. I typically comment one of them out and just run install if it's a new system needing security tools installed the first time, or update if it's an existing system that just needs an update to the samhain config file.

This is all fairly simple but has greatly reduced the amount of time I spend installing and maintaining these tools. I realize the Samhain role doesn't adhere to Ansible's idea of idempotence very well due to the heavy usage of the command module. I'm looking for ways to improve it, but it does what I need with some basic error handling for now.

Hopefully this helps illustrate how Ansible roles work and some of the advantages roles have versus doing everything from one giant playbook. I'm relatively new to Ansible so feel free to leave a reply below or reach out on Twitter if you have questions, comments, or even suggestions on how this could be improved.