Sunday October 17 2021

Ansible + Pass ( Eliminate Ansible Vault )

Normally if you want to secure secrets in Ansible you use Vault, there’s nothing wrong with it, other than it’s slightly annoying to use. Either you encrypt entire files at once and they become a large encrypted blob of data, or you use the individual variable encryption which becomes a pain to update in the future if you want to rotate secrets. Additionally if you’re already keeping track of your secrets in pass putting them into Ansible Vault is just going to lead to duplication.

We can use a lookup plugin to suck the data out of pass. Simply add a folder, lookup_plugins to your Ansible directory, then pop this script in there as pass.py

from ansible.errors import AnsibleError, AnsibleParserError
from ansible.plugins.lookup import LookupBase
from ansible.utils.display import Display
import subprocess

display = Display()


class LookupModule(LookupBase):

    def run(self, terms, variables=None, **kwargs):
        # lookups in general are expected to both take a list as input and output a list
        # this is done so they work with the looping construct 'with_'.
        ret = []
        for term in terms:
            display.debug("Pass lookup term: %s" % term)
            display.vvvv(u"Pass lookup using %s" % term)

            try:
                contents = subprocess.check_output(["pass", term]).decode('utf-8').rstrip()
            except subprocess.CalledProcessError:
                raise AnsibleError("could not locate password: %s" % term)

            ret.append(contents)
        return ret

Now all you have to do is instead of:

---

some_var: !vault |
    $ANSIBLE_VAULT;1.2;AES256;mriedstra
    31346630626333613361346461333830623036306435646534366138666566616663653730393430
    3761383765666666636239323933646336353063623133630a386537326434616534636661626664
    62376230373232623565613131653764343833333731663365653331663934343933396635376538
    3236336465323038320a666164376531306638336331613531636139333232613830626239386166
    37383436373438383639393534386337636564353732383530306538613264663132616438303761
    3539643065363632666563666165356462386339643435326465

you do:

---

some_var: '{{lookup("pass", "ansible/some/path/to/the/secret")}}'

This works wonderfully for multi line secrets as well such as key files as well.

If you’re using an GPG / PGP smart card this integrates well and gives Ansible the backing of hardware security.