How to use existing Vault files in Ansible Tower?

I want to import existing inventories that I have previously used with Ansible (standalone) including group_vars and vault files into Ansible Tower (3.2.0).

However, it doesn't seem to work once Vault files come into play. Once I've setup the Vault password file credential and create the inventory using source type "Sourced from a Project" - I can't select the Vault credential under "Source Details".

Credentials Dialog screenshot

When I manually put it in and save the source - the sync fails with the following error:

 1.735 INFO     Updating inventory 10: TEST
    1.753 DEBUG    Using system install of ansible-inventory CLI: /usr/bin/ansible-inventory
    1.753 INFO     Reading Ansible inventory source: /var/lib/awx/projects/_6__ansible_master/inventories/test/hosts
    1.754 DEBUG    Using private credential data in '/tmp/awx_123_LXUj9p'.
    1.755 DEBUG    Using fresh temporary directory '/tmp/awx_proot_ZURWmR' for isolation.
    1.755 DEBUG    Running from `/var/lib/awx/projects/_6__ansible_master/inventories/test` working directory.
Traceback (most recent call last):
  File "/usr/bin/awx-manage", line 9, in <module>
    load_entry_point('awx==3.2.0', 'console_scripts', 'awx-manage')()
  File "/lib/python2.7/site-packages/awx/__init__.py", line 107, in manage
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute_from_command_line
    utility.execute()
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/__init__.py", line 346, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/base.py", line 394, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/base.py", line 445, in execute
    output = self.handle(*args, **options)
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/base.py", line 661, in handle
    return self.handle_noargs(**options)
  File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 1000, in handle_noargs
  File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 243, in load_inventory_source
  File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 179, in load
  File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 163, in command_to_json
RuntimeError: ansible-inventory failed (rc=4) with stdout:

stderr:
ERROR! Attempting to decrypt but no vault secrets found

I have also tried create an ansible_vault file and pointing the variable "vault_password_file" to it - but this won't work either (complaining it can't find the vault password file).

Has anyone encountered this before?


Solution 1:

So it looks like this was more of an implementation issue. According to RedHat, it is not recommended to keep the vault files with the inventory - as this would mean it decrypts the file every time the inventory sync runs.

The way I've solved this now is by using "vars_files" in the playbook. It looks like this:

  # Secrets
  vars_files:
    - '../../secrets/{{ tower_env }}/vault.yml'

In Tower, I pass in the tower_env variable e.g. "dev" or "qa", which then decrypts the corresponding vault file when a playbook runs - rather then when syncing inventories.

Solution 2:

There are 2 things you are trying to do that aren't (at least of this moment) supported:

  • decrypting your secrets at the time of inventory import
  • using ansible-vault to encrypt the entire file, as opposed to variables

The terminology here is a little poor, but see in these docs the section "Single Encrypted Variable", I sometimes call these in-line variables.

https://docs.ansible.com/ansible/latest/user_guide/playbooks_vault.html

Ansible now supports moving these in-line variables through the inventory parsing process. This format is also no less safe, it's the same algorithm under the hood. The name of the encrypted variables will be exposed to people with access to your source control (which is probably reasonable), but your value will be encrypted.

Now store values with that syntax in .yml variable files under group_vars/ or host_vars/ folders. You should find that the inventory sync inside of Tower is successful (without using any vault credential), and when you navigate to the group or host, you see the encrypted form of the variable.

When you run a playbook (job template in Tower), then attach a vault credential at that time. This delays encryption until the runtime context when it is actually needed.

Example inventory file structure:

https://github.com/AlanCoding/Ansible-inventory-file-examples/tree/master/vault/single_var_file

Also, as the other comment points out, you can put either whole-file encrypted or in-line encrypted variables in that folder structure in source control where your playbook is, and that will be picked up by Ansible and decrypted by vault credentials you attach to the job template.

Solution 3:

ok - after investigation I can acknowledge that there is currently no way to do it in version 2.6.5 with the following reason:

  • it is perfectly possible to encrypt variables whereever you want in either host_vars or group_vars
  • the vault-passphrase is solely taken by the the ways:

-- vault-password-file parameter

-- ask-vault-pass which has been replaced by --vault-id=@prompt

as per code stated here from line 220

What we would need is another possibility to provide the vault-passphrase, e.g. by a group-variable, what is currently not possible.

And this means the Bugreport on Github is not solved / replaced by something else. IMHO it is still uncovered by all other threads. I will continue on this github bug thread.