diff --git a/docs/docsite/rst/playbooks_vault.rst b/docs/docsite/rst/playbooks_vault.rst index 2d8a8f16f59..99ca6a05ede 100644 --- a/docs/docsite/rst/playbooks_vault.rst +++ b/docs/docsite/rst/playbooks_vault.rst @@ -18,7 +18,7 @@ The vault feature can encrypt any structured data file used by Ansible. This ca Ansible tasks, handlers, and so on are also data so these can be encrypted with vault as well. To hide the names of variables that you're using, you can encrypt the task files in their entirety. However, that might be a little too much and could annoy your coworkers :) -The vault feature can also encrypt arbitrary files, even binary files. If a vault-encrypted file is given as the `src` argument to the `copy` module, the file will be placed at the destination on the target host decrypted (assuming a valid vault password is supplied when running the play). ++The vault feature can also encrypt arbitrary files, even binary files. If a vault-encrypted file is given as the `src` argument to the `copy`, `template`, `unarchive`, `script` or `assemble` modules, the file will be placed at the destination on the target host decrypted (assuming a valid vault password is supplied when running the play). As of version 2.3, Ansible also supports encrypting single values inside a YAML file, using the `!vault` tag to let YAML and Ansible know it uses special processing. This feature is covered in more details below. diff --git a/lib/ansible/plugins/action/template.py b/lib/ansible/plugins/action/template.py index adf39891249..4358c4b0e7c 100644 --- a/lib/ansible/plugins/action/template.py +++ b/lib/ansible/plugins/action/template.py @@ -20,7 +20,7 @@ __metaclass__ = type import os from ansible import constants as C -from ansible.errors import AnsibleError +from ansible.errors import AnsibleError, AnsibleFileNotFound from ansible.module_utils._text import to_bytes, to_native, to_text from ansible.plugins.action import ActionBase from ansible.template import generate_ansible_template_vars @@ -107,10 +107,18 @@ class ActionModule(ActionBase): if dest_stat['exists'] and dest_stat['isdir']: dest = self._connection._shell.join_path(dest, os.path.basename(source)) - # template the source data locally & get ready to transfer - b_source = to_bytes(source) + # Get vault decrypted tmp file try: - with open(b_source, 'r') as f: + tmp_source = self._loader.get_real_file(source) + except AnsibleFileNotFound as e: + result['failed'] = True + result['msg'] = "could not find src=%s, %s" % (source, e) + self._remove_tmp_path(tmp) + return result + + # template the source data locally & get ready to transfer + try: + with open(tmp_source, 'r') as f: template_data = to_text(f.read()) # set jinja2 internal search path for includes @@ -150,6 +158,8 @@ class ActionModule(ActionBase): result['failed'] = True result['msg'] = type(e).__name__ + ": " + str(e) return result + finally: + self._loader.cleanup_tmp_file(tmp_source) if not tmp: tmp = self._make_tmp_path() diff --git a/test/integration/targets/vault/roles/test_vaulted_template/tasks/main.yml b/test/integration/targets/vault/roles/test_vaulted_template/tasks/main.yml new file mode 100644 index 00000000000..b6e6ce78f10 --- /dev/null +++ b/test/integration/targets/vault/roles/test_vaulted_template/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: Template from a vaulted template file + template: + src: vaulted_template.j2 + dest: "{{ output_dir }}/vaulted_template.out" + vars: + vaulted_template_var: "here_i_am" + +- name: Get output template contents + slurp: + path: "{{ output_dir }}/vaulted_template.out" + register: vaulted_tempalte_out + +- debug: + msg: "{{ vaulted_tempalte_out.content|b64decode }}" + +- assert: + that: + - vaulted_tempalte_out.content|b64decode == 'here_i_am\n' diff --git a/test/integration/targets/vault/roles/test_vaulted_template/templates/vaulted_template.j2 b/test/integration/targets/vault/roles/test_vaulted_template/templates/vaulted_template.j2 new file mode 100644 index 00000000000..af9c3eb1eb4 --- /dev/null +++ b/test/integration/targets/vault/roles/test_vaulted_template/templates/vaulted_template.j2 @@ -0,0 +1,6 @@ +$ANSIBLE_VAULT;1.1;AES256 +65626437623461633630303033303939616334373263633438623938396564376435366534303865 +6363663439346464336437346263343235626463663130640a373233623733653830306262376430 +31666538323132343039613537323761343234613531353035373434666632333932623064316564 +3532363462643736380a303136353830636635313662663065343066323631633562356663633536 +31343265376433633234656432393066393865613235303165666338663930303035 diff --git a/test/integration/targets/vault/runme.sh b/test/integration/targets/vault/runme.sh index 05603ee747a..8b327202969 100755 --- a/test/integration/targets/vault/runme.sh +++ b/test/integration/targets/vault/runme.sh @@ -57,4 +57,4 @@ ansible-playbook test_vault.yml -i ../../inventory -v "$@" --vault-pass ansible-playbook test_vault_embedded.yml -i ../../inventory -v "$@" --vault-password-file vault-password --syntax-check ansible-playbook test_vault_embedded.yml -i ../../inventory -v "$@" --vault-password-file vault-password ansible-playbook test_vaulted_inventory.yml -i vaulted.inventory -v "$@" --vault-password-file vault-password - +ansible-playbook test_vaulted_template.yml -i ../../inventory -v "$@" --vault-password-file vault-password diff --git a/test/integration/targets/vault/test_vaulted_template.yml b/test/integration/targets/vault/test_vaulted_template.yml new file mode 100644 index 00000000000..b495211de83 --- /dev/null +++ b/test/integration/targets/vault/test_vaulted_template.yml @@ -0,0 +1,6 @@ +- hosts: testhost + gather_facts: False + vars: + - output_dir: . + roles: + - { role: test_vaulted_template, tags: test_vaulted_template}