Search code examples
pythonencryptionansibleansible-vault

How to view/decrypt Ansible vault credentials files from within a Python script?


I'm trying to figure out how to provide the following facilities to a Python script so that it can:

  1. Import Ansible Python modules
  2. Open up my defined ansible.cfg and read vault_password_file variable
  3. Read vault_password_file and temporarily store in a Python variable
  4. Decrypt a referenced Ansible vaulted file

I found this code via google but it did not appear to work when I tried it:

import ansible.utils

bar = dict()

bar = ansible.utils._load_vars_from_path("secrets.yml", results=bar, vault_password="password")

print bar

Throws this error:

$ python ansible-vault-ex.py
Traceback (most recent call last):
  File "ansible-vault-ex.py", line 5, in <module>
    bar = ansible.utils._load_vars_from_path("credentials.vault", results=bar, vault_password="password")
AttributeError: 'module' object has no attribute '_load_vars_from_path'

When I investigated this I saw no indications of this function in any Ansible related files, leading me to believe that this method no longer worked with some newer version(s) of Ansible.

Bottom line is that I'd like some method for importing Ansible libraries/modules from a Python script, so that I can interact with ansible-vault managed files programmatically from Python.


Solution

  • Extending Kuba's answer, ansible-vault is a wrapper around VaultLib. It nicely handles the pre Ansible 2.4 version of Vaultlib along with the post 2.4 version.

    The ansible-vault load() method not only decrypts the file, but it also parses it and returns the contents as a dict. If you want the contents without parsing, it is probably easiest to just extend ansible-vault with something like:

    from ansible_vault import Vault
    
    class MyVault(Vault):
        def load_raw(self, stream):
            return self.vault.decrypt(stream)
    
        def dump_raw(self, text, stream=None):
            encrypted = self.vault.encrypt(text)
            if stream:
                stream.write(encrypted)
            else:
                return encrypted