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".
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.