From a77dbf08663e002198d0fa2af502d5cde8009454 Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Tue, 14 Jul 2020 10:56:26 -0500 Subject: [PATCH] Allow single vault encrypted values to be used directly as module parameters. Fixes #68275 (#70607) --- changelogs/fragments/68275-vault-module-args.yml | 3 +++ lib/ansible/executor/module_common.py | 5 +++-- lib/ansible/module_utils/common/json.py | 8 ++++++-- .../targets/vault/single_vault_as_string.yml | 14 ++++++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/68275-vault-module-args.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 4257ae6b98b..7f75e9a17d5 100644 --- a/lib/ansible/executor/module_common.py +++ b/lib/ansible/executor/module_common.py @@ -37,6 +37,7 @@ from ansible import constants as C 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.common.json import AnsibleJSONEncoder from ansible.module_utils.common.text.converters import to_bytes, to_text, to_native from ansible.plugins.loader import module_utils_loader from ansible.utils.collection_loader._collection_finder import _get_collection_metadata, AnsibleCollectionRef @@ -1075,7 +1076,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)) @@ -1256,7 +1257,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/single_vault_as_string.yml b/test/integration/targets/vault/single_vault_as_string.yml index b80a94c43ef..1eb17d04c24 100644 --- a/test/integration/targets/vault/single_vault_as_string.yml +++ b/test/integration/targets/vault/single_vault_as_string.yml @@ -107,3 +107,17 @@ that: - vaulted_value|wordcount == 2 when: lookup('pipe', ansible_python.executable ~ ' -c "import jinja2; print(jinja2.__version__)"') is version('2.11.2', '>=') + + - ping: + data: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 35323961353038346165643738646465376139363061353835303739663538343266303232326635 + 3365353662646236356665323135633630656238316530640a663362363763633436373439663031 + 33663433383037396438656464636433653837376361313638366362333037323961316364363363 + 3835616438623261650a636164376534376661393134326662326362323131373964313961623365 + 3833 + register: ping_result + + - assert: + that: + - ping_result.ping == 'foo bar'