def test_run_cmd(protocol_fake): s = Session('windows-host', auth=('john.smith', 'secret')) r = s.run_cmd('ipconfig', ['/all']) assert r.status_code == 0 assert 'Windows IP Configuration' in r.std_out assert len(r.std_err) == 0
def __runPowerShellScript(self, scriptfile="FileCopy.ps1", isFile=True): """ run the content of a powershell script given in scriptfile if isFile=True, scriptFile must contain path to Powershell script, if isFile==False, scriptFile is treaded as scripting string prints std_out, std_err and status returns std_out """ script = "" if isFile == True: with open(scriptfile) as file: script = file.read() else: script = scriptfile s = Session(self.ip, auth=(self.remoteAdminUser, self.passwd)) r = s.run_ps(script) if self.debug: print("std_out:") for line in str(r.std_out).split(r"\r\n"): print(line) if r.status_code != self.STATUS_OK: print("status_code: " + str(r.status_code)) print("error: " + str(r.std_err)) return r.std_out.decode("utf-8").rstrip()
class ReauthenticatingKerberosSession: """ Wrapper around WinRM Session object that automatically tries to generate a new Kerberos token and session if authentication fails """ def _generate_kerberos_ticket(self): """ Tries to generate a new Kerberos ticket, through a call to kinit Raises an exception if the subprocess has non-zero exit code """ cmd = ["kinit", self._username] try: subprocess.run( cmd, check=True, input=self._password.encode(), stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, ) except subprocess.CalledProcessError as e: print(e.stderr.decode("utf-8")) raise def _create_new_session(self): """ Generate new internal session XXX: Session is not properly cleaned up when a command fails so we have to create a new internal session object each time """ self._session = Session(target=self._target, transport="kerberos", auth=(None, None)) def __init__(self, target: str, username: str, password: str): self._username = username self._password = password self._target = target self._create_new_session() def run_cmd(self, *args, **kwargs): try: rs = self._session.run_cmd(*args, **kwargs) except KerberosExchangeError: self._generate_kerberos_ticket() self._create_new_session() rs = self._session.run_cmd(*args, **kwargs) return rs def run_ps(self, *args, **kwargs): try: rs = self._session.run_ps(*args, **kwargs) except KerberosExchangeError: self._generate_kerberos_ticket() self._create_new_session() rs = self._session.run_ps(*args, **kwargs) return rs
def test_run_cmd(protocol_fake): # TODO this test should cover __init__ method s = Session('windows-host', auth=('john.smith', 'secret')) s.protocol = protocol_fake r = s.run_cmd('ipconfig', ['/all']) assert r.status_code == 0 assert 'Windows IP Configuration' in r.std_out assert len(r.std_err) == 0
def test_run_ps_with_error(protocol_fake): # TODO this test should cover __init__ method s = Session('windows-host', auth=('john.smith', 'secret')) s.protocol = protocol_fake r = s.run_ps('Write-Error "Error"') assert r.status_code == 1 assert b'Write-Error "Error"' in r.std_err assert len(r.std_out) == 0
def test_run_cmd(protocol_fake): # TODO this test should cover __init__ method s = Session('windows-host', auth=('john.smith', 'secret')) s.protocol = protocol_fake r = s.run_cmd('ipconfig', ['/all']) assert r.status_code == 0 assert b'Windows IP Configuration' in r.std_out assert len(r.std_err) == 0
def _create_new_session(self): """ Generate new internal session XXX: Session is not properly cleaned up when a command fails so we have to create a new internal session object each time """ self._session = Session(target=self._target, transport="kerberos", auth=(None, None))
def test_decode_clixml_invalid_xml(): s = Session('windows-host.example.com', auth=('john.smith', 'secret')) msg = b'#< CLIXML\r\n<in >dasf<?dsfij>' with pytest.warns( UserWarning, match="There was a problem converting the Powershell error message" ): actual = s._clean_error_msg(msg) assert actual == msg
def uruchom_ps(polecenie): sesja = Session('https://jumpbox.monad.net:5986', auth=(None, None), transport='kerberos', kerberos_delegation=True, server_cert_validation='ignore') try: wynik = sesja.run_ps(polecenie) print wynik.std_out if wynik.status_code > 0: raise PowerShellError(wynik.std_err) else: print "%sCommand return code 0 %s" % (bcolors.OKGREEN, bcolors.ENDC) except: raise
def test_run_ps(protocol_fake): s = Session('windows-host', auth=('john.smith', 'secret')) s.protocol = protocol_fake script = """ $strComputer = $Host Clear $RAM = WmiObject Win32_ComputerSystem $MB = 1048576 "Installed Memory: " + [int]($RAM.TotalPhysicalMemory /$MB) + " MB" """ r = s.run_ps(script) assert r.status_code == 0 assert b'Installed Memory: 2044 MB' in r.std_out assert len(r.std_err) == 0
def run_ps(command): print "Running command: %s" % command sesja = Session('https://jumpbox.monad.net:5986', auth=(None, None), transport='kerberos', kerberos_delegation=True, server_cert_validation='ignore') try: result = sesja.run_ps(command) print result.std_out if result.status_code > 0: raise PowerShellError(result.std_err) else: print "%sCommand returned code 0 %s" % (bcolors.OKGREEN, bcolors.ENDC) except: raise
def _create_session(self): # create the session LOG.info("Connecting via WinRM to url: {}".format(self._winrm_url)) session = Session(self._winrm_url, auth=(self._username, self._password), transport=self._transport, server_cert_validation=self._server_cert_validation, operation_timeout_sec=self._timeout, read_timeout_sec=self._read_timeout) return session
def _get_session(self): # cache session (only create if it doesn't exist yet) if not self._session: LOG.debug("Connecting via WinRM to url: {}".format(self._winrm_url)) self._session = Session(self._winrm_url, auth=(self._username, self._password), transport=self._transport, server_cert_validation=self._server_cert_validation, operation_timeout_sec=self._timeout, read_timeout_sec=self._read_timeout) return self._session
def generate_ntlm_session(hostname, system_user, password): """Method to create a ntlm session for running powershell scripts. Returns: winrm.Session """ session = Session( "https://{}:5986/wsman".format(hostname), transport="ntlm", auth=(system_user, password), server_cert_validation="ignore", ) return session
def run(self, host, port, username, password, transport, scheme, verify_ssl_cert, winrm_timeout, sleep_delay, retries): # read_timeout must be > operation_timeout (winrm_timeout) read_timeout = winrm_timeout + 1 # if connecting to the HTTP port then we must use "http" as the scheme # in the URL if port == WINRM_HTTP_PORT: scheme = "http" # construct the URL for connecting to WinRM on the host winrm_url = "{}://{}:{}/wsman".format(scheme, host, port) # convert boolean into text required by winrm library server_cert_validation = "validate" if verify_ssl_cert else "ignore" # create our session object, this doesn't actually connect # it just sets up all of the information into a reusable object session = Session(winrm_url, auth=(username, password), transport=transport, server_cert_validation=server_cert_validation, operation_timeout_sec=winrm_timeout, read_timeout_sec=read_timeout) # loop for the given number of retries for index in range(retries): attempt = index + 1 shell_id = None try: self.logger.debug('WinRM connection attempt: %s' % (attempt)) # openning up a shell is how WinRM connects, this way we do not # need to invoke a command and incur that overhead shell_id = session.protocol.open_shell() return True except Exception as e: self.logger.info( 'Attempt %s failed (%s), sleeping for %s seconds...' % (attempt, str(e), sleep_delay)) time.sleep(sleep_delay) finally: if shell_id: session.protocol.close_shell(shell_id) raise Exception('Exceeded max retries (%s)' % (retries))
def test_target_as_full_url(): s = Session('http://windows-host:1111/wsman', auth=('john.smith', 'secret')) assert s.url == 'http://windows-host:1111/wsman'
def test_target_as_schema_then_hostname_then_port(): s = Session('http://windows-host:1111', auth=('john.smith', 'secret')) assert s.url == 'http://windows-host:1111/wsman'
def test_target_as_hostname(): s = Session('windows-host', auth=('john.smith', 'secret')) assert s.url == 'http://windows-host:5985/wsman'
#!/usr/bin/env python from winrm import Session from sys import exit, argv if len(argv) < 2: exit('Usage: %s command' % argv[0]) command = " ".join(argv[1:]) mySession = Session( 'https://jumpbox.monad.net:5986', auth=(None, None), kerberos_delegation=True, transport='kerberos', ) result = mySession.run_ps(command) print result.std_out if result.status_code > 0: print "Error: %s" % result.std_err
def test_decode_clixml_no_clixml(): s = Session('windows-host.example.com', auth=('john.smith', 'secret')) msg = b"stderr line" expected = b"stderr line" actual = s._clean_error_msg(msg) assert actual == expected
def test_decode_clixml_error(): s = Session('windows-host.example.com', auth=('john.smith', 'secret')) msg = b'#< CLIXML\r\n<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj S="progress" RefId="0"><TN RefId="0"><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><I64 N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><Obj S="progress" RefId="1"><TNRef RefId="0" /><MS><I64 N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><S S="Error">fake : The term \'fake\' is not recognized as the name of a cmdlet, function, script file, or operable program. Check _x000D__x000A_</S><S S="Error">the spelling of the name, or if a path was included, verify that the path is correct and try again._x000D__x000A_</S><S S="Error">At line:1 char:1_x000D__x000A_</S><S S="Error">+ fake cmdlet_x000D__x000A_</S><S S="Error">+ ~~~~_x000D__x000A_</S><S S="Error"> + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException_x000D__x000A_</S><S S="Error"> + FullyQualifiedErrorId : CommandNotFoundException_x000D__x000A_</S><S S="Error"> _x000D__x000A_</S></Objs>' expected = b"fake : The term 'fake' is not recognized as the name of a cmdlet, function, script file, or operable program. Check \nthe spelling of the name, or if a path was included, verify that the path is correct and try again.\nAt line:1 char:1\n+ fake cmdlet\n+ ~~~~\n + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException\n + FullyQualifiedErrorId : CommandNotFoundException" actual = s._clean_error_msg(msg) assert actual == expected
def test_decode_clixml_no_errors(): s = Session('windows-host.example.com', auth=('john.smith', 'secret')) msg = b'#< CLIXML\r\n<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj S="progress" RefId="0"><TN RefId="0"><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><I64 N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><Obj S="progress" RefId="1"><TNRef RefId="0" /><MS><I64 N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj></Objs>' expected = msg actual = s._clean_error_msg(msg) assert actual == expected
def test_target_with_dots(): s = Session('windows-host.example.com', auth=('john.smith', 'secret')) assert s.url == 'http://windows-host.example.com:5985/wsman'
#!/usr/bin/env python from winrm import Session from sys import exit, argv if len(argv) < 3 : exit('Usage: %s times command' % argv[0]) times = int(argv[1]) command = " ".join(argv[2:]) * times print "Command length: %d" % len(command) mySession = Session( 'jumpbox.monad.net', auth = (None, None), transport = 'kerberos', ) result = mySession.run_ps(command) print "Output length: %d" % len(result.std_out) if result.status_code > 0: print "Error: %s" % result.std_err
#! /usr/bin/python from winrm import Session, Protocol print("Starting PyWinRM Script") host = input("hostname of windows with port: ") user = input("username of windows: ") password = input("password of windows: ") print("Running High Level API Test") s = Session(host, auth=(user, password)) r = s.run_cmd('ipconfig', ['/all']) print(r.std_out, r.std_err) print("Running Low Level API Test") p = Protocol(endpoint='http://' + host + '/wsman', transport='ntlm', username=user, password=password, server_cert_validation='ignore') shell_id = p.open_shell() command_id = p.run_command(shell_id, 'ipconfig', ['/all']) std_out, std_err, status_code = p.get_command_output(shell_id, command_id) p.cleanup_command(shell_id, command_id) p.close_shell(shell_id) print(std_out, std_err, status_code) print("Stopping PyWinRM Script")