How can I write vault encryped string »as is« to a file without being ask for the vault password?

395 Views Asked by At

Within a playbook I am created a key pair. I want to store both keys. To do that I want to encrypt them using ansible vault. So the playbook look like that:

- name: Generate ECDSA Keypair
  openssh_keypair:
    path: "{{ ssh_key_file }}"
    type: ecdsa
    size: 521
  delegate_to: localhost

- name: Encrypt Keys
  ansible.builtin.template:
    dest: "{{ ssh_key_file ~ '.yml' }}"
    src: ../templates/dump.j2
  vars:
    private: "{{ lookup('ansible.builtin.file', ssh_key_file, rstrip=True) }}"
    public: "{{ lookup('ansible.builtin.file', ssh_key_file ~ '.pub') }}"
    content: "{{ lookup('template', '../templates/key-pair.yml.j2') }}"
    data: "{{ content | ansible.builtin.vault('***') }}"
  delegate_to: localhost

But running that fails:

fatal: [10.11.12.13 -> localhost]: FAILED! => {"msg": "A vault password or secret must be
 specified to decrypt /home/ansible/.ansible/tmp/ansible-local-3958nmbhie77/tmp4sausqh1/dump.j2"}

So ansible is asking me for the vault password to decrypt the string before rendering in the template. BUT I would love to store is encrypted for security reasons. How can I disable decryption for that task?

UPDATE Content of dump.j2

{{ data  }}

UPDATE #2 The documentation for the above can be found here: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/vault_filter.html#examples

1

There are 1 best solutions below

0
philipp On

Thanks @β.εηοιτ.βε, whose comment linked directly to the root of the issue:

[…] However, there is one exception. If you pass an encrypted file as the src argument to the copy, template, unarchive, script or assemble module, the file will not be encrypted on the target host […]

What happened is the intended and documented behaviour. Since I have tried to use a »vaulted« source withing the ansible.builtin.template module, the module tried to »un-vault« the value before rendering it.

To work around that I needed to use a different module to print the plain value, which I have achieved using this:

 - name: Encrypt Keys
   ansible.builtin.shell:
     cmd: echo '{{ data }}' > {{ ssh_key_file ~ '.yml' }}
     creates: "{{ ssh_key_file ~ '.yml' }}"
   vars:
     private: "{{ lookup('ansible.builtin.file', ssh_key_file, rstrip=True) }}"
     public: "{{ lookup('ansible.builtin.file', ssh_key_file ~ '.pub') }}"
     content: "{{ lookup('template', '../templates/key-pair.yml.j2') }}"
     data: "{{ content | ansible.builtin.vault(vaultpw) }}"
   delegate_to: localhost

Please note that this wont work on Windows and comes with all the disadvantages of using the ansible.builtin.shell module. So the general solution is: Do not use the: »copy, template, unarchive, script or assemble« module if you want to print / render encrypted values. The one that fits depends on the setup.