Ansible Vaults

I figured it would be a good idea to post about Ansible Vaults before I dive into the deep end of using them with my AD deployment series. An Ansible vault allows for a user to keep passwords or keys safe in a file as opposed to the alternative of storing them in plaintext. This is great for one off playbooks that don't need to be completely automated (such as deploying an AD environment as needed). It also has the added benefit of allowing the credentials to be placed in version control.

While it is possible to use ansible-vault to encrypt many different types of files, such as variable files, tasks, and arbitrary files that need to be distributed via Ansible (per their documenation), I'll be focusing on the way that I mostly use ansible vault, which is to encrypt variables with credentials.

Ansible Vault Basics

Creating an ansible vault is easy enough with ansible-vault create <vars file>. You'll be prompted for a password, then confirm the password, and finally an open editor with whatever you have set in the $EDITOR environment variable. Viewing and editing the file is easy enough as well. Just run ansible-vault view <file> or ansible-vault edit <file> respectively. You can decrypt a vault with ansible-vault decrypt <file>. Running a playbook with a vault file specified in a playbook only requires a password passed through the command line or a password file and can be called on with --ask-vault-pass or vault-password-file. Here's an example of what might be called:

ansible-playbook test.yml --ask-vault-pass

Ansible Vault IDs

While there's nothing wrong with the simple method above, I'm lazy and don't want to type or copy/paste my vault password all the time. If you'd like to get fancy with your ansible vaults you can set a vault id at creation of a file, or even a string inside a file. This can be used in conjunction with a password file and a line in your ansible config file to automatically unlock vaults with the same id! Really cool way of doing things.

Password File And Permissions

First we create a password file somewhere with proper permissions. In my example I just made a file with the password in it located in my home directory:

after that we create a line in our ansible config file, located in /etc/ansible/ansible.cfg, that allows for us map our password file to our vault-id group. The line we care about is vault_identity_list. This maps the test group to the file we created just above.

# Since Ansible 2.12 (core):
# To generate an example config file (a "disabled" one with all default settings, commented out):
#               $ ansible-config init --disabled > ansible.cfg
#
# Also you can now have a more complete file by including existing plugins:
# ansible-config init --disabled -t all > ansible.cfg

# For previous versions of Ansible you can check for examples in the 'stable' branches of each version
# Note that this file was always incomplete  and lagging changes to configuration settings

# for example, for 2.9: https://github.com/ansible/ansible/blob/stable-2.9/examples/ansible.cfg
[defaults]
host_key_checking = false

vault_identity_list = test@/home/ipa/davm/.testvault_pass

Vault Creation

We can then create our vault file that will hold the encrypted data with the following command: ansible-vault create --encrypt-vault-id test testvault.yml. I just entered in a variable called enc_var that I can test with.

entry in ansible vault on top, printing encrypted file on bottom

Test the Vault

Now we can create a simple playbook that defines the vault we created as a vars_file. Here's an example that will print the variable we defined in our encrypted vault:

---

- name: "Vault Test"
  hosts: localhost
  vars_files:
    - ../vaults/testvault.yml
  tasks:

    - name: "Print Encrypted Var to Screen"
      debug:
        msg: Is the vault unlocked? "{{ enc_var }}"

We then use the variable located in our encrypted vault, which should decrypt based on the entry we made in our ansible config.

Ansible Vault Bitwarden Integration

The final method of securing sensitive information in ansible vaults is through the password manager bitwarden. I was really surprised to see that this was a thing, but you learn something new everyday I suppose. This has the added benefit of being behind bitwarden which does client side encryption. The process to get this to work looks like this:

  1. Install Bitwarden cli tool (link here)
  2. Login to bitwarden using the bw login command.
  3. Set session key environment variable for password caching

You can download the zipped binary from the bitwarden link above. I moved it into a directory in my $PATH and made it executable. You can login with bw login which will walk you through the login, it even supports 2FA! After you login, it will print an environment variable to the screen that you can set to interact with your vault. Simply run export BW_SESSION=<session-id> and the rest of your login you can interact with your vault through the CLI.

Configuring Bitwarden and Ansible

Just like with our password file we setup, we can set the vault password file to be a script that grabs our password from bitwarden. The script should look like this:

#!/bin/bash

set -e

bw get password "Ansible Vault Password"

The ansible.cfg should look like something like this at a minimum:

# Since Ansible 2.12 (core):
# To generate an example config file (a "disabled" one with all default settings, commented out):
#               $ ansible-config init --disabled > ansible.cfg
#
# Also you can now have a more complete file by including existing plugins:
# ansible-config init --disabled -t all > ansible.cfg

# For previous versions of Ansible you can check for examples in the 'stable' branches of each version
# Note that this file was always incomplete  and lagging changes to configuration settings

# for example, for 2.9: https://github.com/ansible/ansible/blob/stable-2.9/examples/ansible.cfg
[defaults]
host_key_checking = false

vault_password_file = ./vault_pass.sh

The playbook should run without any password prompting:

For the sake of developing good habits it's always a good idea to lock your vault before you log out with bw lock. When you log back in, you'll have to unlock and set your $BW_SESSION variable again. You can do this with a one-liner by running export BW_SESSION=$(bw unlock --raw).

I think the bitwarden method is the safest and the one I'll move forward with. It also makes submitting my ansible playbooks to git much safer. Hopefully you learned something here and stay tuned for my post deploying the windows server template from Proxmox!

Follow Me on Mastodon! Follow Me on Twitter