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

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)

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

        return ret

Now all you have to do is instead of:


some_var: !vault |

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.