Post

Ansible reads from KeePass

For small projects, I’d still like to handle their credentials carefully while keeping the effort small.

Since KeePass is a low-effort Password Manager, why not get automation tools to read credentials from KeePass? Then, having been read, those credentials are available for downstream processes.

I found a way that works with Ansible and KeePass, where the following steps work:

  • Save a test entry (e.g., Username) in Keepass.
  • Encrypt Password for KeePass and set it in Ansible.
  • Ansible uses that encrypted password to read in username and print to console.

tl;dr see code on GitHub

Prepare KeePass

  • Create a KeePass database file. There’s an example AnsiblePrototype.kdbx in the Ansible folder ansible/securevars/files.
  • Add an entry with username test_username

Use Ansible Vault Ids

I used Ansible’s vault-id as described in a RedHat tutorial.

Trying to encrypt using the file keepass.secret didn’t work for me. I always get “permission denied” problems. Since I’m using WSL2, I’d rather tackle WSL file permissions another time.

So, I used the encrypt_string option to encrypt the password of KeePass. More on that later.

Ansible config

1
2
3
4
5
6
# file: ansible/ansible.cfg
/path/to/til/ansible$> cat ansible.cfg
[defaults]
inventory = hosts
# pre-create two vault password files
vault_identity_list = inline@securevars/files/.inline_pass, files@securevars/files/.files_pass

Copy these 2 files .file_pass and .inline_pass to /path/to/til/ansible/securevars/files/

Their contents are up to you. Mine look like this:

1
2
3
4
5
6
# file: ansible/ansible.cfg
/path/to/til/ansible$> cat securevars/files/.inline_pass
use-this-to-encrypt-strings

/path/to/til/ansible$> cat securevars/files/.inline_pass
use-this-to-encrypt-files

Update Ansible files

Update Ansible files.

Update hosts

1
2
3
4
5
# file: ansible/hosts
/path/to/til/ansible$> cat hosts
# useful for testing locally.
# https://docs.ansible.com/ansible/latest/inventory/implicit_localhost.html
localhost ansible_connection=local ansible_python_interpreter="{{ansible_playbook_python}}" gather_facts=false

Update main task

Create securevars/tasks/main.yml

1
2
3
4
5
6
7
# file: securevars/tasks/main.yml
- include_tasks: get_from_keepass.yml
  with_items: 
    - "test_a"
- name: Display KeePass Output
  debug:
    msg: "Keepass Output is '{{ test_a }}'"

Create securevars/tasks/get_from_keepass.yml. Hint came by way of a reddit comment

1
2
3
4
5
6
# file: securevars/tasks/get_from_keepass.yml
- name: get vars
  ansible.builtin.include_vars: host_vars/localhost.yaml
  no_log: True

- ansible.builtin.set_fact: "{{ item }}={{ lookup('viczem.keepass.keepass', 'AnsibleWithKeePass/{{ item }}', 'username') }}"

Update variables

In the host_vars is where we keep the variables that we want to use.

1
2
3
4
5
6
7
8
9
10
# file: securevars/host_vars/localhost.yml

# vars for module, viczem.keepass
# Socket TTL in seconds
keepass_ttl: 30
# path to Keepass database
keepass_dbx: "securevars/files/AnsibleTil.kdbx"
keepass_psw: !vault |
          $ANSIBLE_VAULT;1.2;AES256;inline
          12345....

Encrypt KeePass password

The password for KeePass should be encrypted. Generate it as follows. I’m running Ansible in its own virtual environment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$> cd /path/to/til/ansible
# if you have python installed but no venv, run
/path/to/til/ansible$> python3 -m venv venv
# if you have a venv, activate it
/path/to/til/ansible$> source venv/bin/activate
(venv) /path/to/til/ansible$> read -s -p "Enter Keepasswd: " KEEPASS_PASSWD
# enter password for the keepass database
(venv) /path/to/til/ansible$> export KEEPASS_PASSWD
# use vault-id 'inline' to encrypt KEEPASS_PASSWD for variable name 'keepass_psw'
(venv) /path/to/til/ansible$> ansible-vault encrypt_string --encrypt-vault-id inline "$KEEPASS_PASSWD" --name 'keepass_psw'

# output should look like
Encryption successful
keepass_psw: !vault |
          $ANSIBLE_VAULT;1.2;AES256;inline
          65123...

Copy that whole string, starting from ‘keepass_psw’ and paste it in the file, securevars/host_vars/localhost.yml where the key, keepass_psw is.

Run Playbook

1
2
3
4
5
6
7
8
# run playbook
(venv) /path/to/til/ansible$>ansible-playbook setup.yml 

# output should have an entry like
TASK [securevars : Display KeePass Output] *****************************
ok: [localhost] => {
    "msg": "KeyPass Output is 'test_username' "
}

Troubleshooting

Ensure that the module is installed

If you get the error below, check that you’ve installed the ansible module viczem.keepass.keepass. Take a look at the module’s installation steps.

1
fatal: [localhost]: FAILED! => {"msg": "lookup plugin (viczem.keepass.keepass) not found"}

Ensure correct KeePass password is encrypted

If you get the error below, check that the password you entered in KEEPASS_PASSWD is the correct one for the KeePass database.

1
fatal: [localhost]: FAILED! => {"msg": "An unhandled exception occurred while running the lookup plugin 'viczem.keepass.keepass'. Error was a <class 'ansible.errors.AnsibleError'>, original message: KeePass: socket connection failed for /home/wsl/path/to/ansible/securevars/files/AnsibleTilPPrototype.kdbx. KeePass: socket connection failed for home/wsl/path/to/ansible/securevars/files/AnsibleTilPPrototype.kdbx"}

Other Resources

This post is licensed under CC BY 4.0 by the author.