added unsafe toggle to vars_prompt (#49219)

* added unsafe toggle to vars_prompt

	fixes #47534
This commit is contained in:
Brian Coca 2019-01-30 15:01:13 -05:00 committed by GitHub
parent 4a0fceaa3b
commit 4ac0c23db6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 51 additions and 10 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- added 'unsafe' keyword to vars_prompt so users can signal 'template unsafe' content

View file

@ -89,6 +89,16 @@ Depending on your platform at most the following crypt schemes are supported:
- *sha256_crypt* - SHA-256 Crypt - *sha256_crypt* - SHA-256 Crypt
- *sha512_crypt* - SHA-512 Crypt - *sha512_crypt* - SHA-512 Crypt
.. versionadded:: 2.8
If you need to put in special characters (i.e `{%`) that might create templating errors, use the ``unsafe`` option::
vars_prompt:
- name: "my_password_with_wierd_chars"
prompt: "Enter password"
unsafe: yes
private: yes
.. seealso:: .. seealso::
:doc:`playbooks` :doc:`playbooks`
@ -101,6 +111,3 @@ Depending on your platform at most the following crypt schemes are supported:
Have a question? Stop by the google group! Have a question? Stop by the google group!
`irc.freenode.net <http://irc.freenode.net>`_ `irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel #ansible IRC chat channel

View file

@ -111,6 +111,7 @@ class PlaybookExecutor:
templar = Templar(loader=self._loader, variables=all_vars) templar = Templar(loader=self._loader, variables=all_vars)
setattr(play, 'vars_prompt', templar.template(play.vars_prompt)) setattr(play, 'vars_prompt', templar.template(play.vars_prompt))
# FIXME: this should be a play 'sub object' like loop_control
if play.vars_prompt: if play.vars_prompt:
for var in play.vars_prompt: for var in play.vars_prompt:
vname = var['name'] vname = var['name']
@ -121,11 +122,13 @@ class PlaybookExecutor:
encrypt = var.get("encrypt", None) encrypt = var.get("encrypt", None)
salt_size = var.get("salt_size", None) salt_size = var.get("salt_size", None)
salt = var.get("salt", None) salt = var.get("salt", None)
unsafe = var.get("unsafe", None)
if vname not in self._variable_manager.extra_vars: if vname not in self._variable_manager.extra_vars:
if self._tqm: if self._tqm:
self._tqm.send_callback('v2_playbook_on_vars_prompt', vname, private, prompt, encrypt, confirm, salt_size, salt, default) self._tqm.send_callback('v2_playbook_on_vars_prompt', vname, private, prompt, encrypt, confirm, salt_size, salt,
play.vars[vname] = display.do_var_prompt(vname, private, prompt, encrypt, confirm, salt_size, salt, default) default, unsafe)
play.vars[vname] = display.do_var_prompt(vname, private, prompt, encrypt, confirm, salt_size, salt, default, unsafe)
else: # we are either in --list-<option> or syntax check else: # we are either in --list-<option> or syntax check
play.vars[vname] = default play.vars[vname] = default

View file

@ -303,7 +303,7 @@ class CallbackBase(AnsiblePlugin):
def playbook_on_task_start(self, name, is_conditional): def playbook_on_task_start(self, name, is_conditional):
pass pass
def playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None): def playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None, unsafe=None):
pass pass
def playbook_on_setup(self): def playbook_on_setup(self):
@ -387,8 +387,8 @@ class CallbackBase(AnsiblePlugin):
def v2_playbook_on_handler_task_start(self, task): def v2_playbook_on_handler_task_start(self, task):
pass # no v1 correspondence pass # no v1 correspondence
def v2_playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None): def v2_playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None, unsafe=None):
self.playbook_on_vars_prompt(varname, private, prompt, encrypt, confirm, salt_size, salt, default) self.playbook_on_vars_prompt(varname, private, prompt, encrypt, confirm, salt_size, salt, default, unsafe)
# FIXME: not called # FIXME: not called
def v2_playbook_on_import_for_host(self, result, imported_file): def v2_playbook_on_import_for_host(self, result, imported_file):

View file

@ -39,7 +39,7 @@ from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.six import with_metaclass from ansible.module_utils.six import with_metaclass
from ansible.utils.color import stringc from ansible.utils.color import stringc
from ansible.utils.singleton import Singleton from ansible.utils.singleton import Singleton
from ansible.utils.unsafe_proxy import wrap_var
try: try:
# Python 2 # Python 2
@ -305,7 +305,7 @@ class Display(with_metaclass(Singleton, object)):
else: else:
return input(prompt_string) return input(prompt_string)
def do_var_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None): def do_var_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None, unsafe=None):
result = None result = None
if sys.__stdin__.isatty(): if sys.__stdin__.isatty():
@ -343,6 +343,9 @@ class Display(with_metaclass(Singleton, object)):
# handle utf-8 chars # handle utf-8 chars
result = to_text(result, errors='surrogate_or_strict') result = to_text(result, errors='surrogate_or_strict')
if unsafe:
result = wrap_var(result)
return result return result
@staticmethod @staticmethod

View file

@ -109,6 +109,12 @@ tests = [
'test_spec': [ 'test_spec': [
[('prompting for host:', 'testhost\r')], [('prompting for host:', 'testhost\r')],
r'testhost.*ok=1']}, r'testhost.*ok=1']},
# Test play unsafe toggle
{'playbook': 'unsafe.yml',
'test_spec': [
[('prompting for variable:', '{{whole}}\r')],
r'testhost.*ok=2']},
] ]
for t in tests: for t in tests:

View file

@ -0,0 +1,20 @@
- name: Test vars_prompt unsafe
hosts: testhost
become: no
gather_facts: no
vars:
whole: INVALID
vars_prompt:
- name: input
prompt: prompting for variable
unsafe: true
tasks:
- name:
assert:
that:
- input != whole
- input != 'INVALID'
- debug:
var: input