1

The ansible code below takes an ansible vault (vault.yml) and then uses the ansible.builtin.unvault lookup to retrieve and save the entire vault as the variable full_vault. The output of the debug shows the code in json. This code is working as expected.

- name: Pull vault into Variable from encrypted YAML file
  hosts: localhost
  gather_facts: no
  tasks:
    - name: Get specific value from vault file
      set_fact:
        full_vault: "{{ lookup('ansible.builtin.unvault', 'vault.yml') | from_yaml }}"
    - name: Display Vault
      ansible.builtin.debug:
        msg: "Vault: {{ full_vault }}"

The challenge I am having is trying to use the ansible.builtin.vault lookup to put the full_vault variable back into an ansible vault. How can I accomplish this in a single task?

I am using the environment variable ANSIBLE_VAULT_PASSWORD_FILE=pass.txt for encryption/decryption.

Zeitounator
  • 38,476
  • 7
  • 53
  • 66
Eric P
  • 151
  • 2
  • 6
  • 2
    Could you please explain why you are trying to do all of the above? Because this strongly looks like an [x/y problem](https://xyproblem.info). Just including the vaulted var file (with `vars_files:` at play level or with `include_vars` in a task) will make the vars inside the file immediately decrypted and available leaving the file untouched with absolutely no need to re-encrypt anything. – Zeitounator Feb 03 '23 at 16:31
  • 1
    @Zeitounator- I am trying to rotate AWS Access Key credentials. I have all the Ansible tasks to rotate on the AWS side completed. I am able to use the 'ansible.builtin.unvault' filter to extract the the Access Key and Secret from vault. Now that I have the new information, I am trying to write back to the vault using the 'ansible.builtin.vault' filter, but so far have not been able to get the code working. – Eric P Feb 03 '23 at 18:20

1 Answers1

1

Your question and example is focusing on the ansible.builtin.unvault lookup which is abolutely not needed in your situation. The only case I can think of where this would be needed is if you fetch your vault password from an other system/app/source while running your playbook. But since it is available with classic env vars to ansible, you just have to use the encrypted file which will be decrypted on the fly.

For the rest of the example, let's imagine your vault.yml file contains (decrypted):

my_login: vip
my_pass: v3rys3cr3t
some_other_key: toto

Using the above encrypted file is as easy as

---
- hosts: localhost
  gather_facts: false

  vars_files:
    - vault.yml
  
  tasks:
    - name: Dummy use of login and pass
      ansible.builtin.debug:
        msg: "Login in {{ my_login }} and password is {{ my_pass }}"

Now if you want to easily load that file with all its content, change a value for a key in the contained dict and push back the content encrypted with the same configured password, here is a first draft that you will probably have to enhanced. But it worked for my local test with your current configuration.

The update_vault.yml playbook

---
- hosts: localhost
  gather_facts: false

  vars:
    vault_file: vault.yml
    new_pass: n3ws3cr3t

  tasks:
    - name: Import vaulted variables in a namespace (for further easier manipulation)
      ansible.builtin.include_vars:
         file: "{{ vault_file }}"
         name: my_vault

    - name: Dummy task just to show above worked
      debug:
        msg:
          - Login is {{ my_vault.my_login }}.
          - Password is {{ my_vault.my_pass }}
          - Some other key is {{ my_vault.some_other_key }}

    - name: Update an element and push back to encrypted file
      vars:
        new_vault_content: "{{ my_vault | combine({'my_pass': new_pass}) }}"
        vault_pass_file: "{{ lookup('ansible.builtin.env', 'ANSIBLE_VAULT_PASSWORD_FILE') }}"
        vault_pass: "{{ lookup('ansible.builtin.file', vault_pass_file) }}"
      copy:
        content: "{{ new_vault_content | to_nice_yaml | ansible.builtin.vault(vault_pass) }}"
        dest: "{{ vault_file }}"
        decrypt: false

gives:

$ ansible-playbook update_vault.yml 

PLAY [localhost] ***********************************************************************************************************************************************************************************************************************

TASK [Import vaulted variables in a namespace (for furthre easier manipulation)] *******************************************************************************************************************************************************
ok: [localhost]

TASK [Dummy task just to show above worked] ********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "Login is vip.",
        "Password is v3rys3cr3t",
        "Some other key is toto"
    ]
}

TASK [Update an element and push back to encrypted file] *******************************************************************************************************************************************************************************
changed: [localhost]

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

And you can easilly check the file was correctly updated:

$ ansible-vault view vault.yml 
my_login: vip
my_pass: n3ws3cr3t
some_other_key: toto

Note that the above playbook is not idempotent. If you run it a second time, the decrypted content of your file will stay identical (with the same new password), but the file will still be changed as the vault salt will change and the encrypted content will be different.

Zeitounator
  • 38,476
  • 7
  • 53
  • 66