diff --git a/changelogs/fragments/fix_sudo_flag_mangling.yml b/changelogs/fragments/fix_sudo_flag_mangling.yml new file mode 100644 index 00000000000..8a844de6144 --- /dev/null +++ b/changelogs/fragments/fix_sudo_flag_mangling.yml @@ -0,0 +1,2 @@ +bugfixes: + - sudo become plugin, fix handling of non interactive flags, previous substitution was too naive diff --git a/lib/ansible/plugins/become/sudo.py b/lib/ansible/plugins/become/sudo.py index a4093b85f0b..9b6ded7db0c 100644 --- a/lib/ansible/plugins/become/sudo.py +++ b/lib/ansible/plugins/become/sudo.py @@ -69,6 +69,8 @@ DOCUMENTATION = """ key: password """ +import re +import shlex from ansible.plugins.become import BecomeBase @@ -94,7 +96,16 @@ class BecomeModule(BecomeBase): if self.get_option('become_pass'): self.prompt = '[sudo via ansible, key=%s] password:' % self._id if flags: # this could be simplified, but kept as is for now for backwards string matching - flags = flags.replace('-n', '') + reflag = [] + for flag in shlex.split(flags): + if flag in ('-n', '--non-interactive'): + continue + elif not flag.startswith('--'): + # handle -XnxxX flags only + flag = re.sub(r'^(-\w*)n(\w*.*)', r'\1\2', flag) + reflag.append(flag) + flags = shlex.join(reflag) + prompt = '-p "%s"' % (self.prompt) user = self.get_option('become_user') or '' diff --git a/test/units/plugins/become/test_sudo.py b/test/units/plugins/become/test_sudo.py index 8ccb2a12c3c..67eb9a46b42 100644 --- a/test/units/plugins/become/test_sudo.py +++ b/test/units/plugins/become/test_sudo.py @@ -38,3 +38,30 @@ def test_sudo(mocker, parser, reset_cli_args): cmd = sudo.build_become_command('/bin/foo', sh) assert re.match(r"""sudo\s+-s\s-H\s+-p "\[sudo via ansible, key=.+?\] password:" -u foo /bin/bash -c 'echo BECOME-SUCCESS-.+? ; /bin/foo'""", cmd), cmd + + sudo.set_options(direct={ + 'become_user': 'foo', + 'become_flags': '-snH', + 'become_pass': 'testpass', + }) + + cmd = sudo.build_become_command('/bin/foo', sh) + assert re.match(r"""sudo\s+-sH\s+-p "\[sudo via ansible, key=.+?\] password:" -u foo /bin/bash -c 'echo BECOME-SUCCESS-.+? ; /bin/foo'""", cmd), cmd + + sudo.set_options(direct={ + 'become_user': 'foo', + 'become_flags': '--non-interactive -s -H', + 'become_pass': 'testpass', + }) + + cmd = sudo.build_become_command('/bin/foo', sh) + assert re.match(r"""sudo\s+-s\s-H\s+-p "\[sudo via ansible, key=.+?\] password:" -u foo /bin/bash -c 'echo BECOME-SUCCESS-.+? ; /bin/foo'""", cmd), cmd + + sudo.set_options(direct={ + 'become_user': 'foo', + 'become_flags': '--non-interactive -nC5 -s -H', + 'become_pass': 'testpass', + }) + + cmd = sudo.build_become_command('/bin/foo', sh) + assert re.match(r"""sudo\s+-C5\s-s\s-H\s+-p "\[sudo via ansible, key=.+?\] password:" -u foo /bin/bash -c 'echo BECOME-SUCCESS-.+? ; /bin/foo'""", cmd), cmd