I struggle with fetching a variable from vault file. I know there are many useful information here on stackoverflow already. The reason for opening a new question is because it's a special workflow in my playbook. I'm open for constructive critic to my solution, if you have better ideas.
The vault has a var defined called passwort_abc. This variable is not always defined. If it's not it should generate a new password. I face the situation, that it's never fetched and always generated newly and it fails at the DEBUG existing_secret
with following error message:
fatal: [abc.domain.net]: FAILED! => {"msg": "The task includes an option with an undefined variable.
The error was: {{ pw_key_from_vault }}:
{{ vars['passwort_' + host] }}: 'dict object' has no attribute 'passwort_abc'. 'dict object' has no attribute 'passwort_abc'.
{{ vars['passwort_' + host] }}: 'dict object' has no attribute 'passwort_abc'. 'dict object' has no attribute 'passwort_abc'.
{{ pw_key_from_vault }}: {{ vars['passwort_' + host] }}: 'dict object' has no attribute 'passwort_abc'. 'dict object' has no attribute 'passwort_abc'.
{{ vars['passwort_' + host] }}: 'dict object' has no attribute 'passwort_abc'. 'dict object' has no attribute 'passwort_abc'
The error appears to be in './deploy_postgresql.yaml': line 11, column 7, but may be
elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
pre_tasks:
- name: DEBUG existing_secret
^ here\n"}
let me show and explain you the code...
-> For explanation purposes, I reproduced the issues with this code and steps:
Deploy something
the playbook "loads" all required vars_files and afterwardsDEBUG existing_secret
should print the "existing_secret" from vault file if a related secret is found in the vault fileGENERATE special_secret or fetch from vault_file
create the special_secret variable: in case existing_variable is define use it, otherwise default to generate_secret_string. This is how I handle the case when no variable in existing_secret is set.DEBUB special_secret
should print the "special_secret" which was generated before.
playbook
---
- name: Deploy something
hosts: abc.domain.net, klm.domain.net, xyz.domain.net
vars_files:
- /path/to/vault.yaml
- /path/to/vars.yaml
pre_tasks:
- name: DEBUG existing_secret
ansible.builtin.debug:
msg: "{{ existing_secret | d('I don't have any secret to show yet') }}"
- name: "GENERATE special_secret or fetch from vault_file"
ansible.builtin.set_fact:
special_secret : "{{ existing_secret | default(generate_secret_string) }}"
- name: DEBUB special_secret
ansible.builtin.debug:
msg: "{{ special_secret }}"
vars file
---
hostname: "{{ inventory_hostname }}"
host: "{{ hostname | regex_replace('^(.*?).domain.net$', '\\1') }}"
pw_key_from_vault: "{{ vars['passwort_' + host] }}"
existing_secret: "{{ pw_key_from_vault }}"
generate_secret_string: "{{ lookup('ansible.builtin.password','/dev/null length=30 chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!§$@&/()=#+?_.,') }}"
explanation to host
it's a variable from vars_file which is regexed and output eigther abc or xyz so we and up with a variable name like passwort_abc or passwort_xyz
, which then should match the variable from the vault_file.
vault file
---
passwort_abc: supersecretabc
passwort_xyz: supersecretklm
expectations
- The variable get's fetched from vault_file correctly if exists.
- If the variable in vault_file is missing - generate a new. (it should be processed or written back to vault. just the split between those to steps is primarily enough.
what has been checked already
- How to get password from ansible vault to be used as variable?
- https://www.digitalocean.com/community/tutorials/how-to-use-vault-to-protect-sensitive-ansible-data
- https://docs.ansible.com/ansible/latest/vault_guide/index.html
- Is it possible to parse encrypted Ansible vault values from a dynamic inventory in a playbook?