Ansible un-vault and template a file

James picture James · Jun 7, 2016 · Viewed 8.8k times · Source

I have a file on my local machine that I want to upload to a remote server, it contains confidential information that I don't want exposed in my VCS. It also has some text I need to replace dynamically in it (at the moment as Jinja2 placeholders "{{}}").

If I use the copy module, then the file is un-vaulted when I upload it, but obviously the placeholders are note replaced.

If i use the template module, then it doesn't un-vault the file and hence it is uploaded in its encrypted format (and also doesn't replace placeholders because they are obfuscated by the encryption).

How can I both template and un-vault a file (using ansible) to the remote server?

Answer

fishi0x01 picture fishi0x01 · Jun 7, 2016

As already mentioned in the comments, you could set your secrets in variables and render them into the templates during provision, but if for some reason you want to keep your whole template a secret, there are some workarounds to also do that.

Handling encrypted templates

As a workaround you could temporarily decrypt the template locally and after the rollout delete the decrypted file with the local_action module. Lets assume your encrypted template resides as template.enc in your roles templates directory.

---

- name: Decrypt template
  local_action: "shell {{ view_encrypted_file_cmd }} {{ role_path }}/templates/template.enc > {{ role_path }}/templates/template"
  changed_when: False

- name: Deploy template
  template:
    src=templates/template
    dest=/home/user/file

- name: Remove decrypted template
  local_action: "file path={{ role_path }}/templates/template state=absent"
  changed_when: False

Please note the changed_when: False. This is important in order to run idempotence tests with your ansible roles - otherwise each time you run the playbook a change is signaled. In group_vars/all.yml you could set a global decrypt command for reuse, e.g., as view_encrypted_file_cmd.

group_vars/all.yml

---

view_encrypted_file_cmd: "ansible-vault --vault-password-file {{ lookup('env', 'ANSIBLE_VAULT_PASSWORD_FILE') }} view"

Handling encrypted static files

One way: as template

You could set the content of your secret static file (e.g., a private key) as a variable in ansible and provision it as a template.

var.yml

---

my_private_key: |
  YOUR KEY
  asfdlsafkj
  asdlkfjasf

templates/private_key.j2

{{ private_key }}

tasks/main.yml

---

template: 
  src=templates/private_key.j2
  dest=/home/user/.ssh/id_rsa
  vars:
    private_key: "{{ my_private_key }}"

Another way: via lookup pipe

Another way would be to use the lookup module with pipe to set the content property within the copy module - that way you do not need an extra variable.

---

- copy:
    dest=/your/dest
    content=lookup('pipe', 'VAULT_PASSWORD_FILE=path/to/pass_file ansible-vault view path/to/file.enc')