def test_dzdo(mocker, parser, reset_cli_args): options = parser.parse_args([]) context._init_global_context(options) play_context = PlayContext() default_cmd = "/bin/foo" default_exe = "/bin/bash" dzdo_exe = 'dzdo' dzdo_flags = '' cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert cmd == default_cmd success = 'BECOME-SUCCESS-.+?' play_context.become = True play_context.become_user = '******' play_context.set_become_plugin(become_loader.get('dzdo')) play_context.become_method = 'dzdo' play_context.become_flags = dzdo_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert re.match("""%s %s -u %s %s -c 'echo %s; %s'""" % (dzdo_exe, dzdo_flags, play_context.become_user, default_exe, success, default_cmd), cmd) is not None play_context.become_pass = '******' play_context.set_become_plugin(become_loader.get('dzdo')) cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert re.match("""%s %s -p %s -u %s %s -c 'echo %s; %s'""" % (dzdo_exe, dzdo_flags, r'\"\[dzdo via ansible, key=.+?\] password:\"', play_context.become_user, default_exe, success, default_cmd), cmd) is not None
def test_su(mocker, parser, reset_cli_args): options = parser.parse_args([]) context._init_global_context(options) play_context = PlayContext() default_cmd = "/bin/foo" default_exe = "/bin/bash" su_exe = 'su' su_flags = '' cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert cmd == default_cmd success = 'BECOME-SUCCESS-.+?' play_context.become = True play_context.become_user = '******' play_context.become_pass = None play_context.become_method = 'su' play_context.set_become_plugin(become_loader.get('su')) play_context.become_flags = su_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert (re.match( """%s %s -c '%s -c '"'"'echo %s; %s'"'"''""" % (su_exe, play_context.become_user, default_exe, success, default_cmd), cmd) is not None)
def test_sudo(mocker, parser, reset_cli_args): options = parser.parse_args([]) context._init_global_context(options) sudo = become_loader.get('sudo') sh = shell_loader.get('sh') sh.executable = "/bin/bash" sudo.set_options(direct={ 'become_user': '******', 'become_flags': '-n -s -H', }) cmd = sudo.build_become_command('/bin/foo', sh) assert re.match( r"""sudo\s+-n -s -H\s+-u foo /bin/bash -c 'echo BECOME-SUCCESS-.+? ; /bin/foo'""", cmd), cmd sudo.set_options( direct={ 'become_user': '******', 'become_flags': '-n -s -H', 'become_pass': '******', }) cmd = sudo.build_become_command('/bin/foo', sh) assert re.match( r"""sudo\s+-s\s-H\s+-p "\[sudo via ansible, key=.+?\] password:"******""", cmd), cmd
def test_sudosu(mocker, parser, reset_cli_args): options = parser.parse_args([]) context._init_global_context(options) play_context = PlayContext() default_cmd = "/bin/foo" default_exe = "/bin/bash" sudo_exe = 'sudo' sudo_flags = '-H -s -n' cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert cmd == default_cmd success = 'BECOME-SUCCESS-.+?' play_context.become = True play_context.become_user = '******' play_context.set_become_plugin( become_loader.get('community.general.sudosu')) play_context.become_flags = sudo_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert (re.match( """%s %s su -l %s %s -c 'echo %s; %s'""" % (sudo_exe, sudo_flags, play_context.become_user, default_exe, success, default_cmd), cmd) is not None) play_context.become_pass = '******' cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert (re.match( """%s %s -p "%s" su -l %s %s -c 'echo %s; %s'""" % (sudo_exe, sudo_flags.replace( '-n', ''), r"\[sudo via ansible, key=.+?\] password:", play_context.become_user, default_exe, success, default_cmd), cmd) is not None)
def test_play_context_make_become_bad(mocker, parser, reset_cli_args): options = parser.parse_args([]) context._init_global_context(options) play_context = PlayContext() default_cmd = "/bin/foo" default_exe = "/bin/bash" play_context.become = True play_context.become_user = '******' play_context.set_become_plugin(become_loader.get('bad')) play_context.become_method = 'bad' with pytest.raises(AnsibleError): play_context.make_become_cmd(cmd=default_cmd, executable=default_exe)
def test_su(mocker, parser, reset_cli_args): options = parser.parse_args([]) context._init_global_context(options) su = become_loader.get('su') sh = shell_loader.get('sh') sh.executable = "/bin/bash" su.set_options(direct={ 'become_user': '******', 'become_flags': '', }) cmd = su.build_become_command('/bin/foo', sh) assert re.match( r"""su\s+foo -c '/bin/bash -c '"'"'echo BECOME-SUCCESS-.+?; /bin/foo'"'"''""", cmd)
def _execute_module_with_become(self, module_name, module_args, task_vars, wrap_async, use_task): orig_become = self._connection.become try: if not use_task and orig_become is None: become = become_loader.get('runas') become.set_options(direct={ 'become_user': '******', 'become_pass': None }) self._connection.set_become_plugin(become) module_res = self._execute_module(module_name=module_name, module_args=module_args, task_vars=task_vars, wrap_async=wrap_async) finally: self._connection.set_become_plugin(orig_become) return module_res
def mock_run_env(request, mocker): pc = PlayContext() new_stdin = StringIO() conn = connection_loader.get('ssh', pc, new_stdin) conn.set_become_plugin(become_loader.get('sudo')) conn._send_initial_data = MagicMock() conn._examine_output = MagicMock() conn._terminate_process = MagicMock() conn._load_name = 'ssh' conn.sshpass_pipe = [MagicMock(), MagicMock()] request.cls.pc = pc request.cls.conn = conn mock_popen_res = MagicMock() mock_popen_res.poll = MagicMock() mock_popen_res.wait = MagicMock() mock_popen_res.stdin = MagicMock() mock_popen_res.stdin.fileno.return_value = 1000 mock_popen_res.stdout = MagicMock() mock_popen_res.stdout.fileno.return_value = 1001 mock_popen_res.stderr = MagicMock() mock_popen_res.stderr.fileno.return_value = 1002 mock_popen_res.returncode = 0 request.cls.mock_popen_res = mock_popen_res mock_popen = mocker.patch('subprocess.Popen', return_value=mock_popen_res) request.cls.mock_popen = mock_popen request.cls.mock_selector = MockSelector() mocker.patch('ansible.compat.selectors.DefaultSelector', lambda: request.cls.mock_selector) request.cls.mock_openpty = mocker.patch('pty.openpty') mocker.patch('fcntl.fcntl') mocker.patch('os.write') mocker.patch('os.close')
def test_pfexec(mocker, parser, reset_cli_args): options = parser.parse_args([]) context._init_global_context(options) play_context = PlayContext() default_cmd = "/bin/foo" default_exe = "/bin/bash" pfexec_exe = 'pfexec' pfexec_flags = '' cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert cmd == default_cmd success = 'BECOME-SUCCESS-.+?' play_context.become = True play_context.become_user = '******' play_context.set_become_plugin(become_loader.get('pfexec')) play_context.become_method = 'pfexec' play_context.become_flags = pfexec_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert re.match( '''%s %s "'echo %s; %s'"''' % (pfexec_exe, pfexec_flags, success, default_cmd), cmd) is not None
def test_play_context_make_become_cmd(mocker, parser, reset_cli_args): (options, args) = parser.parse_args([]) options.args = args context._init_global_context(options) play_context = PlayContext() default_cmd = "/bin/foo" default_exe = "/bin/bash" sudo_exe = 'sudo' sudo_flags = '-H -s -n' su_exe = 'su' su_flags = '' pbrun_exe = 'pbrun' pbrun_flags = '' pfexec_exe = 'pfexec' pfexec_flags = '' doas_exe = 'doas' doas_flags = '-n' ksu_exe = 'ksu' ksu_flags = '' dzdo_exe = 'dzdo' dzdo_flags = '' cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert cmd == default_cmd success = 'BECOME-SUCCESS-.+?' play_context.become = True play_context.become_user = '******' play_context.set_become_plugin(become_loader.get('sudo')) play_context.become_flags = sudo_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") assert (re.match("""%s %s -u %s %s -c 'echo %s; %s'""" % (sudo_exe, sudo_flags, play_context.become_user, default_exe, success, default_cmd), cmd) is not None) play_context.become_pass = '******' cmd = play_context.make_become_cmd(cmd=default_cmd, executable=default_exe) assert (re.match("""%s %s -p "%s" -u %s %s -c 'echo %s; %s'""" % (sudo_exe, sudo_flags.replace('-n', ''), r"\[sudo via ansible, key=.+?\] password:"******"/bin/bash") assert (re.match("""%s %s -c '%s -c '"'"'echo %s; %s'"'"''""" % (su_exe, play_context.become_user, default_exe, success, default_cmd), cmd) is not None) play_context.set_become_plugin(become_loader.get('pbrun')) play_context.become_flags = pbrun_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") assert re.match("""%s %s -u %s 'echo %s; %s'""" % (pbrun_exe, pbrun_flags, play_context.become_user, success, default_cmd), cmd) is not None play_context.set_become_plugin(become_loader.get('pfexec')) play_context.become_flags = pfexec_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") assert re.match('''%s %s "'echo %s; %s'"''' % (pfexec_exe, pfexec_flags, success, default_cmd), cmd) is not None play_context.set_become_plugin(become_loader.get('doas')) play_context.become_flags = doas_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") assert (re.match("""%s %s -u %s %s -c 'echo %s; %s'""" % (doas_exe, doas_flags, play_context.become_user, default_exe, success, default_cmd), cmd) is not None) play_context.set_become_plugin(become_loader.get('ksu')) play_context.become_flags = ksu_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") assert (re.match("""%s %s %s -e %s -c 'echo %s; %s'""" % (ksu_exe, play_context.become_user, ksu_flags, default_exe, success, default_cmd), cmd) is not None) play_context.set_become_plugin(become_loader.get('bad')) with pytest.raises(AnsibleError): play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") play_context.set_become_plugin(become_loader.get('dzdo')) play_context.become_flags = dzdo_flags cmd = play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") assert re.match("""%s %s -u %s %s -c 'echo %s; %s'""" % (dzdo_exe, dzdo_flags, play_context.become_user, default_exe, success, default_cmd), cmd) is not None play_context.become_pass = '******' play_context.set_become_plugin(become_loader.get('dzdo')) cmd = play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") assert re.match("""%s %s -p %s -u %s %s -c 'echo %s; %s'""" % (dzdo_exe, dzdo_flags, r'\"\[dzdo via ansible, key=.+?\] password:\"', play_context.become_user, default_exe, success, default_cmd), cmd) is not None
def _get_become(self, name): become = become_loader.get(name) if not become: raise AnsibleError("Invalid become method specified, could not find matching plugin: '%s'. " "Use `ansible-doc -t become -l` to list available plugins." % name) return become
def test_plugins_connection_ssh__examine_output(self): pc = PlayContext() new_stdin = StringIO() conn = connection_loader.get('ssh', pc, new_stdin) conn.set_become_plugin(become_loader.get('sudo')) conn.check_password_prompt = MagicMock() conn.check_become_success = MagicMock() conn.check_incorrect_password = MagicMock() conn.check_missing_password = MagicMock() def _check_password_prompt(line): if b'foo' in line: return True return False def _check_become_success(line): if b'BECOME-SUCCESS-abcdefghijklmnopqrstuvxyz' in line: return True return False def _check_incorrect_password(line): if b'incorrect password' in line: return True return False def _check_missing_password(line): if b'bad password' in line: return True return False conn.become.check_password_prompt = MagicMock( side_effect=_check_password_prompt) conn.become.check_become_success = MagicMock( side_effect=_check_become_success) conn.become.check_incorrect_password = MagicMock( side_effect=_check_incorrect_password) conn.become.check_missing_password = MagicMock( side_effect=_check_missing_password) # test examining output for prompt conn._flags = dict( become_prompt=False, become_success=False, become_error=False, become_nopasswd_error=False, ) pc.prompt = True conn.become.prompt = True def get_option(option): if option == 'become_pass': return 'password' return None conn.become.get_option = get_option output, unprocessed = conn._examine_output( u'source', u'state', b'line 1\nline 2\nfoo\nline 3\nthis should be the remainder', False) self.assertEqual(output, b'line 1\nline 2\nline 3\n') self.assertEqual(unprocessed, b'this should be the remainder') self.assertTrue(conn._flags['become_prompt']) self.assertFalse(conn._flags['become_success']) self.assertFalse(conn._flags['become_error']) self.assertFalse(conn._flags['become_nopasswd_error']) # test examining output for become prompt conn._flags = dict( become_prompt=False, become_success=False, become_error=False, become_nopasswd_error=False, ) pc.prompt = False conn.become.prompt = False pc.success_key = u'BECOME-SUCCESS-abcdefghijklmnopqrstuvxyz' conn.become.success = u'BECOME-SUCCESS-abcdefghijklmnopqrstuvxyz' output, unprocessed = conn._examine_output( u'source', u'state', b'line 1\nline 2\nBECOME-SUCCESS-abcdefghijklmnopqrstuvxyz\nline 3\n', False) self.assertEqual(output, b'line 1\nline 2\nline 3\n') self.assertEqual(unprocessed, b'') self.assertFalse(conn._flags['become_prompt']) self.assertTrue(conn._flags['become_success']) self.assertFalse(conn._flags['become_error']) self.assertFalse(conn._flags['become_nopasswd_error']) # test examining output for become failure conn._flags = dict( become_prompt=False, become_success=False, become_error=False, become_nopasswd_error=False, ) pc.prompt = False conn.become.prompt = False pc.success_key = None output, unprocessed = conn._examine_output( u'source', u'state', b'line 1\nline 2\nincorrect password\n', True) self.assertEqual(output, b'line 1\nline 2\nincorrect password\n') self.assertEqual(unprocessed, b'') self.assertFalse(conn._flags['become_prompt']) self.assertFalse(conn._flags['become_success']) self.assertTrue(conn._flags['become_error']) self.assertFalse(conn._flags['become_nopasswd_error']) # test examining output for missing password conn._flags = dict( become_prompt=False, become_success=False, become_error=False, become_nopasswd_error=False, ) pc.prompt = False conn.become.prompt = False pc.success_key = None output, unprocessed = conn._examine_output(u'source', u'state', b'line 1\nbad password\n', True) self.assertEqual(output, b'line 1\nbad password\n') self.assertEqual(unprocessed, b'') self.assertFalse(conn._flags['become_prompt']) self.assertFalse(conn._flags['become_success']) self.assertFalse(conn._flags['become_error']) self.assertTrue(conn._flags['become_nopasswd_error'])
def call_become_plugin(task, var_options, cmd, executable=None): """Helper function to call become plugin simiarly on how Ansible itself handles this.""" plugin = become_loader.get(task['become_method']) plugin.set_options(task_keys=task, var_options=var_options) shell = get_shell_plugin(executable=executable) return plugin.build_become_command(cmd, shell)
def test_check_password_prompt(self): local = ( b'[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: \n' b'BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq\n' ) ssh_pipelining_vvvv = b''' debug3: mux_master_read_cb: channel 1 packet type 0x10000002 len 251 debug2: process_mux_new_session: channel 1: request tty 0, X 1, agent 1, subsys 0, term "xterm-256color", cmd "/bin/sh -c 'sudo -H -S -p "[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: "******"'"'echo BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq; /bin/true'"'"' && sleep 0'", env 0 debug3: process_mux_new_session: got fds stdin 9, stdout 10, stderr 11 debug2: client_session2_setup: id 2 debug1: Sending command: /bin/sh -c 'sudo -H -S -p "[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: "******"'"'echo BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq; /bin/true'"'"' && sleep 0' debug2: channel 2: request exec confirm 1 debug2: channel 2: rcvd ext data 67 [sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: debug2: channel 2: written 67 to efd 11 BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq debug3: receive packet: type 98 ''' # noqa ssh_nopipelining_vvvv = b''' debug3: mux_master_read_cb: channel 1 packet type 0x10000002 len 251 debug2: process_mux_new_session: channel 1: request tty 1, X 1, agent 1, subsys 0, term "xterm-256color", cmd "/bin/sh -c 'sudo -H -S -p "[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: "******"'"'echo BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq; /bin/true'"'"' && sleep 0'", env 0 debug3: mux_client_request_session: session request sent debug3: send packet: type 98 debug1: Sending command: /bin/sh -c 'sudo -H -S -p "[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: "******"'"'echo BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq; /bin/true'"'"' && sleep 0' debug2: channel 2: request exec confirm 1 debug2: exec request accepted on channel 2 [sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: debug3: receive packet: type 2 debug3: Received SSH2_MSG_IGNORE debug3: Received SSH2_MSG_IGNORE BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq debug3: receive packet: type 98 ''' # noqa ssh_novvvv = ( b'[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: \n' b'BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq\n' ) dns_issue = ( b'timeout waiting for privilege escalation password prompt:\n' b'sudo: sudo: unable to resolve host tcloud014\n' b'[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: \n' b'BECOME-SUCCESS-ouzmdnewuhucvuaabtjmweasarviygqq\n' ) nothing = b'' in_front = b''' debug1: Sending command: /bin/sh -c 'sudo -H -S -p "[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: "******"'"'echo ''' class ConnectionFoo(ConnectionBase): @property def transport(self): pass def _connect(self): pass def exec_command(self): pass def put_file(self): pass def fetch_file(self): pass def close(self): pass c = ConnectionFoo(self.play_context, self.in_stream) c.set_become_plugin(become_loader.get('sudo')) c.become.prompt = '[sudo via ansible, key=ouzmdnewuhucvuaabtjmweasarviygqq] password: ' self.assertTrue(c.check_password_prompt(local)) self.assertTrue(c.check_password_prompt(ssh_pipelining_vvvv)) self.assertTrue(c.check_password_prompt(ssh_nopipelining_vvvv)) self.assertTrue(c.check_password_prompt(ssh_novvvv)) self.assertTrue(c.check_password_prompt(dns_issue)) self.assertFalse(c.check_password_prompt(nothing)) self.assertFalse(c.check_password_prompt(in_front))