Keeping Ansible secrets in the Hashicorp Vault
Hashicorp Vault is an open source secret management tool. Vault is written in Go and distributed as a binary.
When used in conjunction with Ansible, secrets are stored in Vault in key-value form.
Preparing the Vault
We print the storage
$ vault operator unseal
Log in
$ vault login
Token (will be hidden):
Turn on the key-volume version 1 secrets store
$ vault secrets enable -tls-skip-verify -path=ansible kv
We write data in the honeymoon
$ vault kv put -tls-skip-verify ansible/serverlab/production/db
dbusername=wp_user
dbpassword=passwd123
dbhost=vault.exampe.local
dbname=blog
Run the following command to check
$ vault kv get ansible/serverlab/production/db
======= Data =======
Key Value
--- -----
dbhost vault.exampe.local
dbname blog
dbpassword passwd123
dbusername wp_user
Making a read-only policy
Let’s create an ansible.hcl file
$ nano ansible.hcl
path "ansible/*" {
capabilities = [ "read", "list" ]
}
Writing the “ansible” policy
$ vault policy write ansible ansible.hcl
Success! Uploaded policy: ansible
Let’s create a token so that we can authenticate
$ vault token create -policy="ansible"
Key Value
--- -----
token s.7JjtwBWjKrtNsP2pYbwNv9er
token_accessor JpMeUksuVRuRq0lSW07KRmLi
token_duration 10h
token_renewable true
token_policies ["ansible" "default"]
identity_policies []
policies ["ansible" "default"]
Preparing Ansible
Install ansible and the hashi_vault plugin
$ sudo dnf install ansible
$ sudo pip3 install hvac
Create a directory for a local playbook and go to it
$ mkdir ansible-test && cd ansible-test
Create a file with our local host
$ nano hosts
[servers]
vault.example.local ansible_ssh_host=127.0.0.1
Create a playbook
$ nano playbook.yml
---
- hosts: all
connection: local
vars:
vault_url: https://192.168.11.200
vault_token: s.7JjtwBWjKrtNsP2pYbwNv9er
vault_secret: ansible/serverlab/production/db
serverlab_db: "{{ lookup('hashi_vault', 'secret={{ vault_secret }} token={{ vault_token }} url={{ vault_url }}') }}"
roles:
- wordpress
$ mkdir -p roles/wordpress/{tasks,templates}
$ nano roles/wordpress/tasks/main.yml
---
- name: Configure WordPress
template:
src: wp-config.php.j2
dest: /tmp/wp-config.php
with_items:
- "{{ serverlab_db }}"
tags:
- update_wp_config
- name: Return all secrets from a path
debug:
msg: "{{ lookup('hashi_vault', 'secret={{ vault_secret }} token={{ vault_token }} url={{ vault_url }} validate_certs=False') }}"
tags:
- test
$ nano roles/wordpress/templates/wp-config.php.j2
define('DB_NAME', '{{ serverlab_db.dbname }}');
define('DB_USER', '{{ serverlab_db.dbusername }}');
define('DB_PASSWORD', '{{ serverlab_db.dbpassword }}');
define('DB_HOST', '{{ serverlab_db.dbhost }}');
Launching the playbook
$ ansible-playbook -i hosts -l servers playbook.yml --tags "test"
$ ansible-playbook -i hosts -l servers playbook.yml --tags "update_wp_config"
The first command will print the result to the console. The second command will pull data from Vault and save it to file
Checking
$ cat /tmp/wp-config.php
define('DB_NAME', 'blog');
define('DB_USER', 'wp_user');
define('DB_PASSWORD', 'passwd123');
define('DB_HOST', 'vault.exampe.local');