#ansible #gopass #vaults

Ansible Vaults with gopass

Since Ansible version 2.4 the vault IDs became quite powerful. Together with a password manager like gopass automatically decrypting vaults became quite easy, although a bit of manual work is required.


Introduction Vault IDs

The main ansible commands ansible-vault and ansible-playbook already support the --vault-id parameter. It requires a compound of two things: the vault ID label (e.g. dev, prod, etc.) and the means of getting the password (e.g. prompt, a password file or an executable). The vault ID label can be specified while creating the vault or later by modifying the encrypted variant. In the following example the label is called vault-id-label. Notice the format version of 1.2, which you might need to change in your file too.

$ANSIBLE_VAULT;1.2;AES256;vault-id-label

During an ansible run this vault could be opened by adding the --vault-id vault-id-label@prompt parameter, which would prompt the user for the vault password. Changing prompt to vaultpass would let ansible load the password from the file vaultpass.

Password scripts

The third option would be to specify an executable, which will get called by ansible. There are two variants:

  1. Normal scripts, which are called without any parameters and just return a password
  2. Client scripts, which have to end in client and are called with the --vault-id option plus the label of the vault

In this example I will use a client script, since I have several vaults with different labels/passwords. The implementation is quite straightforward:

#!/usr/bin/env python

import sys
from subprocess import run, PIPE, STDOUT

VAULT_PASSWORD_LOCATION='pathToMyAnsibleVaultPasswords/'


def main():
    if len(sys.argv) != 3 or sys.argv[1] != "--vault-id":
        print('Necessary argument "--vault-id" missing')
        sys.exit(1)
    result = run(
        ["gopass", VAULT_PASSWORD_LOCATION + sys.argv[2]],
        text=True,
        stderr=STDOUT,
        stdout=PIPE,
    )
    if result.returncode != 0:
        print(result.stdout)
        sys.exit(result.returncode)
    else:
        sys.stdout.write(result.stdout)
        sys.exit(0)


if __name__ == "__main__":
    main()

Save this script as gopass-client.py next to your ansible.cfg (also make it executable) and use --vault-id vault-label@gopass-client in your ansible command and it will magically unlock your vault using gopass. Don’t forget to change the VAULT_PASSWORD_LOCATION to the path of your ansible passswords in your gopass store.