Using Mac keychain to store and retrieve Ansible vault passwords

When using Ansible for my home lab, an initial problem was about how to keep sudo passwords for my various machines in an practical manner (I really don’t like the idea of password-less sudo even in my homelab).
The remote users used for my ansible logins to each of my machines are different, and can be managed via the inventory file. But the sudo passwords for them are not the same, and it is pretty annoying to enter them while running ansible on the command line.
I decided to find a way to make this a little less annoying.
Storing the encrypted sudo passwords
I first started keeping the individual sudo passwords for my hosts in an ansible-vault encrypted file outside my repo. Decrypted, they would look like this:
$ ansible-vault view ~/.ansible/sudo_passwords.yml
---
become_passwords:
host1: host1password
host2: host2password
Using the encrypted sudo passwords automatically
To use these passwords in my playbooks transparently, I did two things:
-
I put this in a
group_vars/all/111_setpasswords.yaml
file. This will now make Ansible look for sudo passwords from this variable that is kept inside the encrypted file:--- ansible_become_pass: '{{ become_passwords[inventory_hostname] }}'
-
Now to make Ansible read the encrypted file right at the beginning, I put a symlink to my encrypted vault file in
group_vars/all
directory as well.$ ln -sf ~/.ansible/sudo_passwords.yml group_vars/all/000passwords.yml
By this point, you should be able to use Ansible by providing a single password (for the encrypted file) and still use unique sudo passwords for each of your machines.
$ ansible --ask-vault-pass ubuntu -a "free -m"
Vault password:
host1 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 32005 4677 22684 25 4643 27052
Swap: 0 0 0
host2 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 15884 1088 12706 1 2089 14619
Swap: 0 0 0
Avoiding entering vault password everytime
I work on my playbooks iteratively, so I run ansible
or ansible-playbook
frequently. I still was mildly annoyed
having to enter the vault password every time.
Fortunately, Ansible provides a way to bypass this. If you set an environment variable ANSIBLE_VAULT_PASSWORD_FILE
and point it to a shell script, Ansible will execute the script and use the output as the password.
So I created a pretty simple script which would do the same and put it in ~/.ansible/vault-env
.
$ cat ~/.ansible/vault-env
#!/bin/bash
echo $ANSIBLE_VAULT_PASSWORD
Now I needed a way to set the environment variable without exposing it in bash history. For this, I created a support script which is checked into the repo.
$ cat support_scripts/set_vault_password_env.sh
#!/bin/bash
export ANSIBLE_VAULT_PASSWORD_FILE=~/.ansible/vault-env
export no_proxy='*'
read -sp "Vault password:" ANSIBLE_VAULT_PASSWORD
export ANSIBLE_VAULT_PASSWORD
Now whenever I have some Ansible work to do, I change directory to my playbook repo, source this script and I don’t have to enter passwords again for the rest of the session:
$ source support_scripts/set_vault_password_env.sh
Vault password:
$ ansible ...
$ ansible-playbook ...
Making it even simpler on Mac
On Mac, this process can be made even simpler by storing the password in the keychain and avoiding entering it ever!
Add password to keychain
Add the password to keychain. You willl have to run this script only once per mac machine you work on.
$ cat support_scripts/mac/keychain_set_vault_password.sh
#!/bin/bash
read -sp "Vault password:" ANSIBLE_VAULT_PASSWORD
echo
security add-generic-password -U -a $USER -s ansible-vault -w "$ANSIBLE_VAULT_PASSWORD"
Run it directly (i.e. you don’t source it).
Point ANSIBLE_VAULT_PASSWORD_FILE
to a mac specific script
$ cat ~/.ansible/vault-env-mac
#!/bin/bash
security find-generic-password -a $USER -s ansible-vault -w
And this is the file you source before your Ansible sessions.
$ cat support_scripts/mac/set_vault_password_env_from_keychain.sh
#!/bin/bash
export ANSIBLE_VAULT_PASSWORD_FILE=~/.ansible/vault-env-mac
export no_proxy='*'
Now you don’t have to remember the vault password. The keychain will keep it safe.
vault-id
to set a different passwords for encrypted files for different domains.