Let's start with a cliché. Everyone agrees that security is important, right? We work on deployment process and we need to get secrets into the system securely. Secrets can be passwords and private keys, for instance.
We use Ansible for configuration management so we started with ansible-vault. It has some drawbacks so we found a compelling contender - Vault made by Hashicorp. I would like to describe how we made Ansible work with Vault.
Ansible
Ansible (https://www.ansible.com) - automation for everyone. Dubbed as the most developer friendly automation tool it sports easy syntax, it is simple to translate from what devs are usually most acquiented - Bash - and it runs masterless so one does not need a special master node to handle updates like in cases of Chef and Puppet. The learning curve is favorable.
Vault
Vault (https://www.vaultproject.io) - a server application for storing securely secrets and to allow access to them via remote API. It supports host of features like access tokens, fine-grained access rights, auditing, revoking only secrets which were compromised, certificates provisioning on demand and more.
Running Vault
We use Vault in development configuration since setting up production Vault is more complicated and hard to automate by nature. Development configuration suffice to get you started.
We will provision it locally with Ansible and we will directly set it up with some access policy, enter secrets and get a token which will give us read-only access to some of the secrets.
The structure will be following:
A simple playbook that invokes the vault role.
vault.yml:
It can be invoked with ansible-playbook vault.yml
.
We leverage that we are working with Docker (v1.12.5) and we use Ansible Docker integration (available in Ansible v2.2). We deploy official Vault image on Docker first and then perform operations on it.
The steps are:
- Run the image with Docker.
- Get the image logs.
- Grep them for the root token.
- Run the
setup-vault.sh
. - The script outputs an access token for the specified read policy and we save it to
~/.vault-token
file where the Ansible Vault lookup plugin expects it.
setup-vault.sh
script:The setup creates the access policy, enters two secrets and creates a token which has the aforementioned policy so one can only read these secrets with the token.
The read-policy.json
:
You can check the setup works by running:
export VAULT_TOKEN=$(cat ~/.vault-token)
- to export the file content to env variable.curl -H "X-Vault-Token: $VAULT_TOKEN" localhost:8200/v1/secret/app/test/ldap-pwd
. - to hit the Vault API.
Ansible with Vault
Now that we have Vault up and running let's get secrets into Ansible. It is surprisingly easy thanks to the good work of Johan Haals on his ansible-vault lookup plugin (https://github.com/jhaals/ansible-vault). I would say that the name is confusing (being the same with ansible-vault tool) but other than that the plugin works very well. I also read that the chances are the plugin will make it into Ansible so you wouldn't have to install it manually.
ansible-vault installation
Let's say we stick with default Ansible plugins' location as outlined in the configuration.
sudo mkdir /usr/share/ansible/plugins/lookup
sudo vim /etc/ansible/ansible.cfg
and uncomment the linelookup_plugins = /usr/share/ansible/plugins/lookup
.sudo git clone https://github.com/jhaals/ansible-vault.git /usr/share/ansible/plugins/lookup/ansible-vault
Retrieving Secrets
In our case we have configuration templates and we want to replace hard-coded secrets with lookup. A typical template in our case is an XML file or a properties file. It may look like this:
We put the password in Vault and modify the template:
Ansible template_module uses Jinja2. We wrap variables in {{ }}
. We put in the lookup call where we invoke our freshly installed vault lookup plugin.
We can also see how to use variable within Ansible lookup. Simply put it without any quotation. In case you need some literals around it like we do, concatenate it with +
.
The last step is to use to invoke the template module from a playbook:
And the role:
The source application.properties
can be found in the /files
.
That's it! Personally, I struggled a bit with Vault setup, its API calls syntax. But the documentation was helpful and once I had that running making Ansible use Vault was very smooth.
No comments:
Post a Comment