From f556b6cdd896b1b0bfa6591bc1f820af12641eb3 Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Fri, 17 Jul 2020 16:42:01 -0500 Subject: [PATCH] [stable-2.9] Allow single vault encrypted values to be used directly as module parameters. Fixes #68275 (#70607) (#70642) * rebase conflicts * [stable-2.9] Allow single vault encrypted values to be used directly as module parameters. Fixes #68275 (#70607). (cherry picked from commit a77dbf08663e002198d0fa2af502d5cde8009454) Co-authored-by: Matt Martz --- changelogs/fragments/68275-vault-module-args.yml | 3 +++ lib/ansible/executor/module_common.py | 5 +++-- lib/ansible/module_utils/common/json.py | 8 ++++++-- test/integration/targets/vault/runme.sh | 1 + .../targets/vault/single_vault_as_string.yml | 15 +++++++++++++++ 5 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/68275-vault-module-args.yml create mode 100644 test/integration/targets/vault/single_vault_as_string.yml diff --git a/changelogs/fragments/68275-vault-module-args.yml b/changelogs/fragments/68275-vault-module-args.yml new file mode 100644 index 00000000000..9c4c5c22a86 --- /dev/null +++ b/changelogs/fragments/68275-vault-module-args.yml @@ -0,0 +1,3 @@ +bugfixes: +- Vault - Allow single vault encrypted values to be used directly as module + parameters. (https://github.com/ansible/ansible/issues/68275) diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py index d7a4742275c..65a52a70642 100644 --- a/lib/ansible/executor/module_common.py +++ b/lib/ansible/executor/module_common.py @@ -37,6 +37,7 @@ from ansible.errors import AnsibleError from ansible.executor.interpreter_discovery import InterpreterDiscoveryRequiredError from ansible.executor.powershell import module_manifest as ps_manifest from ansible.module_utils._text import to_bytes, to_text, to_native +from ansible.module_utils.common.json import AnsibleJSONEncoder from ansible.module_utils.compat.importlib import import_module from ansible.plugins.loader import module_utils_loader # Must import strategy and use write_locks from there @@ -1003,7 +1004,7 @@ def _find_module_utils(module_name, b_module_data, module_path, module_args, tas if module_substyle == 'python': params = dict(ANSIBLE_MODULE_ARGS=module_args,) try: - python_repred_params = repr(json.dumps(params)) + python_repred_params = repr(json.dumps(params, cls=AnsibleJSONEncoder, vault_to_text=True)) except TypeError as e: raise AnsibleError("Unable to pass options to module, they must be JSON serializable: %s" % to_native(e)) @@ -1195,7 +1196,7 @@ def _find_module_utils(module_name, b_module_data, module_path, module_args, tas ) elif module_substyle == 'jsonargs': - module_args_json = to_bytes(json.dumps(module_args)) + module_args_json = to_bytes(json.dumps(module_args, cls=AnsibleJSONEncoder, vault_to_text=True)) # these strings could be included in a third-party module but # officially they were included in the 'basic' snippet for new-style diff --git a/lib/ansible/module_utils/common/json.py b/lib/ansible/module_utils/common/json.py index 7da31f45987..3018e9e238e 100644 --- a/lib/ansible/module_utils/common/json.py +++ b/lib/ansible/module_utils/common/json.py @@ -36,15 +36,19 @@ class AnsibleJSONEncoder(json.JSONEncoder): Simple encoder class to deal with JSON encoding of Ansible internal types ''' - def __init__(self, preprocess_unsafe=False, **kwargs): + def __init__(self, preprocess_unsafe=False, vault_to_text=False, **kwargs): self._preprocess_unsafe = preprocess_unsafe + self._vault_to_text = vault_to_text super(AnsibleJSONEncoder, self).__init__(**kwargs) # NOTE: ALWAYS inform AWS/Tower when new items get added as they consume them downstream via a callback def default(self, o): if getattr(o, '__ENCRYPTED__', False): # vault object - value = {'__ansible_vault': to_text(o._ciphertext, errors='surrogate_or_strict', nonstring='strict')} + if self._vault_to_text: + value = to_text(o, errors='surrogate_or_strict') + else: + value = {'__ansible_vault': to_text(o._ciphertext, errors='surrogate_or_strict', nonstring='strict')} elif getattr(o, '__UNSAFE__', False): # unsafe object, this will never be triggered, see ``AnsibleJSONEncoder.iterencode`` value = {'__ansible_unsafe': to_text(o, errors='surrogate_or_strict', nonstring='strict')} diff --git a/test/integration/targets/vault/runme.sh b/test/integration/targets/vault/runme.sh index bd690012172..8b22dd33354 100755 --- a/test/integration/targets/vault/runme.sh +++ b/test/integration/targets/vault/runme.sh @@ -511,3 +511,4 @@ ansible-playbook -i ../../inventory -v "$@" --vault-password-file vault-password # Ensure we don't leave unencrypted temp files dangling ansible-playbook -v "$@" --vault-password-file vault-password test_dangling_temp.yml +ansible-playbook "$@" --vault-password-file vault-password single_vault_as_string.yml diff --git a/test/integration/targets/vault/single_vault_as_string.yml b/test/integration/targets/vault/single_vault_as_string.yml new file mode 100644 index 00000000000..dedbecf4838 --- /dev/null +++ b/test/integration/targets/vault/single_vault_as_string.yml @@ -0,0 +1,15 @@ +- hosts: localhost + tasks: + - ping: + data: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 35323961353038346165643738646465376139363061353835303739663538343266303232326635 + 3365353662646236356665323135633630656238316530640a663362363763633436373439663031 + 33663433383037396438656464636433653837376361313638366362333037323961316364363363 + 3835616438623261650a636164376534376661393134326662326362323131373964313961623365 + 3833 + register: ping_result + + - assert: + that: + - ping_result.ping == 'foo bar'