def run_command(command, target): p = Protocol(endpoint='https://' + target + ':5986/wsman', transport='kerberos') # We do not want printed info about kerberos ticket stdout_orig = sys.stdout f = open('/dev/null', 'w') sys.stdout = f try: shell_id = p.open_shell() command_id = p.run_command(shell_id, 'powershell', [command]) 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) sys.stdout = stdout_orig print std_out if std_err: sys.exit(std_err) except kerberos.GSSError as e: print >> sys.stderr, "kerberos GSSError:", e sys.exit(2) except: print >> sys.stderr, ( "Unexpected error during remote ps command execution :", sys.exc_info()[0], sys.exc_info()[1]) sys.exit(2)
class Session(object): #TODO implement context manager methods def __init__(self, target, auth, transport='plaintext'): username, password = auth self.url = self._build_url(target, transport) self.protocol = Protocol(self.url, transport=transport, username=username, password=password) def run_cmd(self, command, args=()): #TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell() command_id = self.protocol.run_command(shell_id, command, args) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) self.protocol.close_shell(shell_id) return rs @staticmethod def _build_url(target, transport): match = re.match( '(?i)^((?P<scheme>http[s]?)://)?(?P<host>[0-9a-z-_]+)(:(?P<port>\d+))?(?P<path>(/)?(wsman)?)?', target) scheme = match.group('scheme') if not scheme: scheme = 'https' if transport == 'ssl' else 'http' # TODO do we have anything other than HTTP/HTTPS host = match.group('host') port = match.group('port') if not port: port = 5986 if transport == 'ssl' else 5985 path = match.group('path') if not path: path = 'wsman' return '{0}://{1}:{2}/{3}'.format(scheme, host, port, path.lstrip('/'))
def run(self): # use win remote management to run powershell script # set command text, tell windows which module to import and run in this case script = "Import-Module -Name 'C:\\Users\\trota\\Source\\PowerShell\\Modules\\yo.psm1'; &WriteYo(' with var')" # must use utf16 little endian on windows # see run_ps in pywinrm __init__.py https://github.com/diyan/pywinrm/blob/master/winrm/__init__.py encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii') encoded_ps_command = 'powershell -encodedcommand {0}'.format( encoded_ps) print("") print("encoded ps command: ", encoded_ps_command) print("") # connect p = Protocol( endpoint='https://CCWL-2909.chsamerica.com:5986/wsman', transport='ntlm', username=r'chs\trota', password='******', # secure connection validation - see http://www.hurryupandwait.io/blog/understanding-and-troubleshooting-winrm-connection-and-authentication-a-thrill-seekers-guide-to-adventure # TODO: configure SSL properly for production/public spaces server_cert_validation='ignore' #server_cert_validation='validate' ) shell_id = p.open_shell() command_id = p.run_command(shell_id, encoded_ps_command) 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)
def getLastTaskResult(self, taskname): script = """ $task = Get-ScheduledTaskInfo -TaskName %s $task.LastTaskResult """ % taskname shell_id = None command_id = None p = None error = False try: p = Protocol(endpoint='https://' + self.hostname + ':5986/wsman', transport='ntlm', username=self.username, password=self.password, server_cert_validation='ignore') shell_id = p.open_shell() encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii') command_id = p.run_command(shell_id, 'powershell', [ '-encodedcommand {0}'.format(encoded_ps), ]) std_out, std_err, status_code = p.get_command_output( shell_id, command_id) lasttaskresult = std_out.rstrip() except Exception as e: print("UNKNOWN - Unable to get data from server (%s) %s." % (str(e), type(e).__name__)) error = True finally: p.cleanup_command(shell_id, command_id) p.close_shell(shell_id) if error: exit(3) return lasttaskresult
def run(self, host, password, command, params, username='******', port=5732, secure=True): proto = 'https' if secure else 'http' p = Protocol( endpoint='%s://%s:%i/wsman' % (proto, host, port), # RFC 2732? transport='ntlm', username=username, password=password, server_cert_validation='ignore') shell_id = p.open_shell() # run the command command_id = p.run_command(shell_id, command, params) 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) return {'stdout': std_out, 'stderr': std_err}
class ConnWinCls(object): def __init__(self): self.conn = self.connectWindows() def connectWindows(self): try: self.hostIP = "https://"+self.host_ip + ":5986/wsman" self.pro = Protocol( endpoint = self.hostIP, transport = "ntlm", username = self.u_name, password = self.pwd, server_cert_validation ="ignore") logger.info("Connecting Windows ...") script = """diskpart /s C:\Users\Administrator\Desktop\script1.txt > C:\Users\Administrator\Desktop\log1.txt""" shell_id = self.pro.open_shell() logger.info("Connected") command_id = self.pro.run_command(shell_id, script) std_out, std_err, status_code = self.pro.get_command_output(shell_id, command_id) logger.info("Executed Cmd status_code is : {}".format(status_code)) logger.info("Executed Command Output is : {}".format(std_out)) logger.info("Executed Command Error is : {}".format(std_err)) self.pro.cleanup_command(shell_id, command_id) self.pro.close_shell(shell_id) except Exception, e: logger.info( "Exception : {}".format(e))
def main(): args = parse_args() endpoint = '{}://{}:{}/{}'.format( 'http' if args.use_http else 'https', args.host, args.port, args.endpoint ) username = args.user if '\\' not in username or '@' not in username: username = '******'.format(args.host.split('.')[0], username) if args.shell: command = args.command[0] arguments = args.command[1:] else: command = 'powershell' encoded_command = ' '.join(args.command) encoded_command = base64.b64encode(encoded_command.encode('utf-16-le')) arguments = ['-EncodedCommand', encoded_command] proto = Protocol(endpoint, 'ntlm', username, args.password, server_cert_validation='ignore') shell_id = proto.open_shell() command_id = proto.run_command(shell_id, command, arguments) std_out, std_err, status_code = proto.get_command_output(shell_id, command_id) sys.stdout.write(std_out.decode('utf-8')) # sys.stderr.write(std_err.decode('utf-8')) proto.cleanup_command(shell_id, command_id) proto.close_shell(shell_id) return status_code
def run(self, scripturl, scriptarguments): scriptpath = "c:\\samanamon" #scripturl="http://%s/%s" % (self.nagiosaddress, scriptname) scriptname = scripturl.split('/')[-1] if self.cleanup: script = ''' if (-Not (Test-Path %(scriptpath)s)) { mkdir %(scriptpath)s | Out-Null} "Environment prepared." | Out-Host Invoke-WebRequest -Uri %(scripturl)s -OutFile "%(scriptpath)s\\%(scriptname)s" if (-Not (Test-Path %(scriptpath)s\\%(scriptname)s)) { "File not downloaded" | Out-Host; Remove-Item -Recurse -Force %(scriptpath)s exit 1 } "Downloaded Script." | Out-Host %(scriptpath)s\\%(scriptname)s %(scriptarguments)s| Out-Host "Done executing script" | Out-Host del %(scriptpath)s\\%(scriptname)s Remove-Item -Recurse -Force %(scriptpath)s "Done cleanup" | Out-Host''' % { 'scripturl': scripturl, 'scriptpath': scriptpath, 'scriptname': scriptname, 'scriptarguments': scriptarguments, 'hostaddress': self.hostaddress } else: script = ''' %(scriptpath)s\\%(scriptname)s %(scriptarguments)s| Out-Host "Done executing script" | Out-Host''' % { 'scriptpath': scriptpath, 'scriptname': scriptname, 'scriptarguments': scriptarguments } shell_id = None command_id = None p = None error = 0 std_out = '' std_err = '' try: p = Protocol( endpoint='http://%s:5985/wsman' % self.hostaddress, transport='ntlm', username=self.username, password=self.password) shell_id = p.open_shell() encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii') command_id = p.run_command(shell_id, 'powershell', ['-encodedcommand {0}'.format(encoded_ps), ]) std_out, std_err, status_code = p.get_command_output(shell_id, command_id) self.check_error(std_err) p.cleanup_command(shell_id, command_id) p.close_shell(shell_id) except Exception as e: raise CheckWinRMExceptionUNKNOWN("Unable to get data from Server (%s) %s." % (type(e).__name__, str(e))) if status_code != 0: raise CheckWinRMExceptionUNKNOWN(std_err) return "%s\n%s" % (std_out, "")
class SessionLinux(Session): def connect(self, output, server): self.output = output self.datastore = os.path.join(self.output, server['server']) os.makedirs(self.datastore) # session = winrm.Session(server['url'], # auth=(server['user'], server['password']), # transport='ntlm') self.protocol = Protocol(endpoint='http://{}:5985/wsman'.format( server['url']), transport='ntlm', username=server['user'], password=server['password']) def run_cmd(self, command, args=()): # TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell(codepage=65001) command_id = self.protocol.run_command(shell_id, command, args) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) self.protocol.close_shell(shell_id) return rs def run_ps(self, script): """base64 encodes a Powershell script and executes the powershell encoded script command """ # must use utf16 little endian on windows encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii') rs = self.run_cmd('powershell -encodedcommand {0}'.format(encoded_ps)) # if len(rs.std_err): # # if there was an error message, clean it it up and make it human # # readable # rs.std_err = self._clean_error_msg(rs.std_err) return rs # def execute(self, err_file, session, id, type, text): def execute(self, err_file, id, type, text): text = text.strip() # print("run:{},{},{}".format(id, type, text)) if type == "Cmdlet": result = self.run_ps(text) else: result = self.run_cmd(text) if result.status_code != 0: err_msg = "id:{},rc:{}\n".format(id, result.status_code) err_file.write(err_msg.encode()) err_file.write(result.std_err) # print(result.std_out.decode('utf-8')) with open(os.path.join(self.datastore, id), 'wb') as out_file: out_file.write(result.std_out) def finish(self): pass
def run_powershell_with_codepage_936(target, username, password, script): """ run remote command with WinRM [Chinese characters are not displayed properly #288](https://github.com/diyan/pywinrm/issues/288) [Code Page Identifiers](https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers) codepage use 936, gb2312, ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) :param target: hostname or ip address :type target: str :param username: :type username: str :param password: :type password: str :param script: powershell commands or scripts :type script: str | unicode :return: status_code, std_out :rtype: tuple """ script = to_unicode_or_bust(script) encoded_ps = b64encode(script.encode('utf_16_le')).decode("ascii") p = Protocol( endpoint='http://{}:5985/wsman'.format(target), transport='ntlm', username=username, password=password, read_timeout_sec=10, operation_timeout_sec=5, ) try: shell_id = p.open_shell(codepage=936) except requests.exceptions.ConnectionError as e: return 1, "requests failed.", str(e) try: command_id = p.run_command(shell_id, 'powershell.exe', ['-EncodedCommand', encoded_ps]) try: std_out, std_err, status_code = p.get_command_output( shell_id, command_id) finally: p.cleanup_command(shell_id, command_id) finally: p.close_shell(shell_id) # print(std_out.decode('utf-8')) # print(std_err.decode('utf-8')) # print(status_code) return status_code, std_out, std_err
def auto_ss(): from winrm.protocol import Protocol p = Protocol(endpoint='http://172.30.200.149:5985/wsman', transport='basic', username=r'chry', 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)
def main(computer, username, password, command): p = Protocol(endpoint='https://{}:5986/wsman'.format(computer), transport='ntlm', username=username, password=password, server_cert_validation='ignore') shell_id = p.open_shell() #command_id = p.run_command(shell_id, 'query', ['user']) command_id = p.run_command(shell_id, command, []) 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)
class Session(object): #TODO implement context manager methods def __init__(self, url, auth, transport = "plaintext"): #TODO convert short urls into well-formed endpoint self.protocol = Protocol(url, auth, transport) def run_cmd(self, command, args=()): #TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell() command_id = self.protocol.run_command(shell_id, command, args) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) self.protocol.close_shell(shell_id) return rs
def run_vncApplyAttribute_winrm_command(attribute_name, attribute_value, idrac_ip, idrac_userName, idrac_password, windows_ip, windows_username, windows_password): """ This function is used for getting output of enumeration class as speciified Function Owner : Nithya_V Date created : 6/9/2016 @param attribute_name : VNC attribute name which needs to be changed @param attribute_value : VNC attribute value which needs to be applied @param idrac_ip : (string) idrac ip of system @param idrac_userName : (string) idrac user name @param idrac_password : (string) idrac password @param windows_ip : (string) windows system ip from which query will be executed @param windows_userName : (string) windows system user name @param windows_password : (string) windows system password @param instance_id : (string) instance id for fetching data specific to an instance. Optional @return command_output : (string) Command Output, None in case of any error @return no_of_instances : (string) number of instances returned """ try: 'establish connection with windows system' p = Protocol(endpoint='http://' + windows_ip + ':5985/wsman', transport='plaintext', username=windows_username, password=windows_password) shell_id = p.open_shell() 'execute winrm command on idrac ip' winrm_command = global_vars.winrm_apply_vnc_attributes_command + ' -u:' + idrac_userName + ' -p:' + idrac_password + \ ' -r:https://' + idrac_ip + '/wsman -SkipCNcheck -SkipCAcheck -encoding:utf-8 -a:basic @{Target="iDRAC.Embedded.1";AttributeName=%s;AttributeValue=%s}' % (attribute_name, attribute_value) print "Winrm Command %s \n" % (winrm_command) command_id = p.run_command(shell_id, 'ls') 'get command output' command_output, command_error, command_status = p.get_command_output( shell_id, command_id) print 'Command Output:' + str(command_output) p.cleanup_command(shell_id, command_id) p.close_shell(shell_id) return command_output, 0 except: traceback.print_exc() return None, '0'
def _try_winrm(self, node): ip = node.private_ips[0] p = Protocol( endpoint='http://%s:5985/wsman' % ip, # RFC 2732 transport='ntlm', username=self.username, password=self.secret, 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) return std_out
def winrm_cmd(cmd): p = Protocol(endpoint='https://192.168.183.186:5986/wsman', transport='basic', username=r'Administrator', password='******', server_cert_validation='ignore') shell_id = p.open_shell() command_id = p.run_command(shell_id, cmd) 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) return std_out
def run_powerstate_change_winrm_command(power_state, idrac_ip, idrac_userName, idrac_password, windows_ip, windows_username, windows_password): """ This function is used for getting output of enumeration class as speciified Function Owner : Pooja_Rundwal Date created : 9/5/2016 @param powerstate : 2 - Power On , 8 - Graceful shutdown @param idrac_ip : (string) idrac ip of system @param idrac_userName : (string) idrac user name @param idrac_password : (string) idrac password @param windows_ip : (string) windows system ip from which query will be executed @param windows_userName : (string) windows system user name @param windows_password : (string) windows system password @param instance_id : (string) instance id for fetching data specific to an instance. Optional @return command_output : (string) Command Output, None in case of any error @return no_of_instances : (string) number of instances returned """ try: 'establish connection with windows system' p = Protocol(endpoint='http://' + windows_ip + ':5985/wsman', transport='plaintext', username=windows_username, password=windows_password) shell_id = p.open_shell() 'execute winrm command on idrac ip' winrm_command = global_vars.winrm_invoke_powerstate_command + ' @{PowerState="' + power_state + '"}' \ + ' -u:' + idrac_userName + ' -p:' + idrac_password + \ ' -r:https://' + idrac_ip + '/wsman -SkipCNcheck -SkipCAcheck -encoding:utf-8 -a:basic' print "Winrm Command %s \n" % (winrm_command) command_id = p.run_command(shell_id, winrm_command) 'get command output' command_output, command_error, command_status = p.get_command_output( shell_id, command_id) print 'Command Output:' + str(command_output) p.cleanup_command(shell_id, command_id) p.close_shell(shell_id) return command_output except: traceback.print_exc() return None, '0'
def check_creds(host, username, password, domain): has_access = False try: username = '******' % (domain, username) url = 'http://%s:5985/wsman' % host wsman = Protocol(endpoint=url, transport='ntlm', username=username, password=password) shell_id = wsman.open_shell() wsman.close_shell(shell_id) has_access = True except: has_access = False return has_access
def win(host, cmd, usern, userp): p = Protocol(endpoint="https://{}:5986/wsman".format(host), transport='ntlm', username=usern, password=userp, server_cert_validation='ignore') shell_id = p.open_shell() command_id = p.run_command(shell_id, cmd) std_out, std_err, status_code = p.get_command_output(shell_id, command_id) outlines = std_out.decode("utf-8") res = "".join(outlines) resp = [x.strip() for x in res.split('\n')] p.cleanup_command(shell_id, command_id) p.close_shell(shell_id) return resp
class Session(object): #TODO implement context manager methods def __init__(self, url, auth): #TODO convert short urls into well-formed endpoint username, password = auth self.protocol = Protocol(url, username=username, password=password) def run_cmd(self, command, args=()): #TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell() command_id = self.protocol.run_command(shell_id, command, args) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) self.protocol.close_shell(shell_id) return rs
def connectWin(self, host_ip, u_name, p_word, softwares, tc_name): """ Connects to Windows Host and checks for software existence - **parameters**, **types**, **return** and **return types**:: :param host_ip: windows host ip :param u_name: windows host username :param p_word: windows host password :param softwares: list of softwares to be checked :type host_ip: string :type u_name: string :type p_word: string :type softwares: list """ hostIP = "http://" + host_ip + ":5985/wsman" try: pro = Protocol(endpoint=hostIP, transport='ntlm', username=u_name, password=p_word, server_cert_validation='ignore') logger.info("\n***Connecting to Windows Host...") shell_id = pro.open_shell() for software in softwares: logger.info("Checking for software {} in "\ "windows" .format(software)) command_id = pro.run_command( shell_id, self.getSoftwareCmd(software, "Windows")) std_out, std_err, status_code = pro.get_command_output( shell_id, command_id) msg = "Software {} does not exist in the C drive.."\ "Hence Skipping"\ "the test case {}..." .format(software, tc_name) if std_out == "": notify.message(msg) raise Exception(msg) msg = 'Found software on host %s at ' % host_ip + std_out logger.info(msg) pro.cleanup_command(shell_id, command_id) pro.close_shell(shell_id) except Exception as e: text = "Requirements pre check failed.. "\ "Hence Skipping the test case "\ "{} ..." .format(tc_name) logger.error(text) notify.message(text) raise Exception(text)
def run(self, host, password, username='******', port=5732, secure=True): proto = 'https' if secure else 'http' p = Protocol( endpoint='%s://%s:%i/wsman' % (proto, host, port), # RFC 2732? transport='ntlm', username=username, 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) return {'stdout': std_out, 'stderr': std_err}
def run_to_delete(server_name, remote_path): """ Delete file from remote Windows host. Remark: No handing of any kind of exeception. Kerberos ticket should be intiated. Args: server_name(string): Name of the host to connect. remote_path(string): Absolute path to remote file. Returns: """ host_name = "http://" + server_name + ":5985/wsman" conn = Protocol(endpoint=host_name, transport='kerberos') shell_id = conn.open_shell() command_id = conn.run_command(shell_id, "del " + remote_path) stdout, stderr, return_code = conn.get_command_output(shell_id, command_id) conn.cleanup_command(shell_id, command_id) conn.close_shell(shell_id)
def do_winrm(lport, windows_user, windows_password, winrm_cmd): # if used with Terraform, there is an issue with backslashes so use the #BACKSLASH# placeholder instead winrm_cmd = winrm_cmd.replace("#BACKSLASH#", "\\\\") p = Protocol( endpoint='http://127.0.0.1:' + str(lport) + '/wsman', transport='basic', message_encryption='never', username=windows_user, password=windows_password, server_cert_validation='ignore') shell_id = p.open_shell() command_id = p.run_command(shell_id, 'powershell.exe', [winrm_cmd]) cmd_output = p.get_command_output(shell_id, command_id) for l in cmd_output: print (str(l).replace("\r\n", "\n")) p.cleanup_command(shell_id, command_id) p.close_shell(shell_id)
def run_command_with_codepage(server, script, codepage=936): """ [Chinese characters are not displayed properly #288](https://github.com/diyan/pywinrm/issues/288) [Code Page Identifiers](https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers) codepage use 936, gb2312, ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) :param server: :type server: :param script: :type script: :param codepage: :type codepage: :return: :rtype: """ ip, user, psw = get_acc_psw_with_ends(server) script = to_unicode_or_bust(script) encoded_ps = b64encode(script.encode('utf_16_le')).decode("ascii") p = Protocol(endpoint='http://{}:5985/wsman'.format(ip), transport='ntlm', username=user, password=psw) shell_id = p.open_shell(codepage=codepage) try: command_id = p.run_command(shell_id, 'powershell.exe', ['-EncodedCommand', encoded_ps]) try: std_out, std_err, status_code = p.get_command_output( shell_id, command_id) finally: p.cleanup_command(shell_id, command_id) finally: p.close_shell(shell_id) print(std_out.decode('utf-8')) print(std_err.decode('utf-8')) print(status_code) return status_code, std_out, std_err
def run_from_copy(server_name, local_path, remote_path): """ Transfer text file from remote Windows host to local Unix host. Remark: No handing of any kind of exeception. Kerberos ticket should be intiated. Args: server_name(string): Name of the host to connect. local_path(string): Absolute path to local file. remote_path(string): Absolute path to remote file. Returns: """ host_name = "http://" + server_name + ":5985/wsman" conn = Protocol(endpoint=host_name, transport='kerberos') shell_id = conn.open_shell() command_id = conn.run_command(shell_id, "type " + remote_path) stdout, stderr, return_code = conn.get_command_output(shell_id, command_id) conn.cleanup_command(shell_id, command_id) file = open(local_path, 'w') file.write(stdout.decode('ascii')) file.close() conn.close_shell(shell_id)
def _winrm_commands(self, node, commands): ip = node.private_ips[0] p = Protocol( endpoint='http://%s:5985/wsman' % ip, # RFC 2732 transport='ntlm', username=self.username, password=self.secret, server_cert_validation='ignore') shell_id = p.open_shell() std_out_logs = [] std_err_logs = [] # run the commands in sequence. for command, params in commands: command_id = p.run_command(shell_id, command, params) std_out, std_err, status_code = p.get_command_output(shell_id, command_id) std_out_logs.append(std_out) std_err_logs.append(std_err) p.cleanup_command(shell_id, command_id) p.close_shell(shell_id) return std_out_logs, std_err_logs
def getCitrix(self): script = """ Add-PSSnapin Citrix.* $m = Get-BrokerMachine -MaxRecordCount 5000 $json = ConvertTo-JSON -compress $m $json """ shell_id = None command_id = None p = None error = False try: from winrm.protocol import Protocol p = Protocol(endpoint='http://' + self.ddc + ':5985/wsman', transport='ntlm', username=self.username, password=self.password, server_cert_validation='ignore') shell_id = p.open_shell() encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii') command_id = p.run_command(shell_id, 'powershell', [ '-encodedcommand {0}'.format(encoded_ps), ]) std_out, std_err, status_code = p.get_command_output( shell_id, command_id) citrix = json.loads(std_out, 'latin-1') if not isinstance(citrix, list): citrix = [citrix] except Exception as e: print("UNKNOWN - Unable to get data from Citrix DDC (%s) %s." % (str(e), type(e).__name__)) error = True finally: p.cleanup_command(shell_id, command_id) p.close_shell(shell_id) if error: exit(3) return citrix
def run_to_copy(server_name, local_path, remote_path): """ Transfer text file to remote Windows host. Remark: No handing of any kind of exeception. Kerberos ticket should be intiated. Args: server_name(string): Name of the host to connect. local_path(string): Absolute path to local file. remote_path(string): Absolute path to remote file. Returns: """ host_name = "http://" + server_name + ":5985/wsman" conn = Protocol(endpoint=host_name, transport='kerberos') shell_id = conn.open_shell() file = open(local_path, 'r') text_file = file.read() file.close() remote_path_str = '"' + remote_path + '"' part_1 = """$stream = [System.IO.StreamWriter] """ + remote_path_str + """ $s = @" """ part_2 = """ "@ | %{ $_.Replace("`n","`r`n") } $stream.WriteLine($s) $stream.close()""" script = part_1 + text_file + part_2 encoded_script = base64.b64encode( script.encode('utf_16_le')).decode('ascii') command_id = conn.run_command( shell_id, "powershell -encodedcommand %s" % (encoded_script)) stdout, stderr, return_code = conn.get_command_output(shell_id, command_id) conn.cleanup_command(shell_id, command_id) conn.close_shell(shell_id)
class Session(object): # TODO implement context manager methods def __init__(self, target, auth, **kwargs): username, password = auth self.url = self._build_url(target, kwargs.get('transport', 'plaintext')) self.protocol = Protocol(self.url, username=username, password=password, **kwargs) def run_cmd(self, command, args=()): # TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell() command_id = self.protocol.run_command(shell_id, command, args) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) self.protocol.close_shell(shell_id) return rs def run_ps(self, script): """base64 encodes a Powershell script and executes the powershell encoded script command """ # must use utf16 little endian on windows encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii') rs = self.run_cmd('powershell -encodedcommand {0}'.format(encoded_ps)) if len(rs.std_err): # if there was an error message, clean it it up and make it human # readable rs.std_err = self._clean_error_msg(rs.std_err) return rs def _clean_error_msg(self, msg): """converts a Powershell CLIXML message to a more human readable string """ # TODO prepare unit test, beautify code # if the msg does not start with this, return it as is if msg.startswith(b"#< CLIXML\r\n"): # for proper xml, we need to remove the CLIXML part # (the first line) msg_xml = msg[11:] try: # remove the namespaces from the xml for easier processing msg_xml = self._strip_namespace(msg_xml) root = ET.fromstring(msg_xml) # the S node is the error message, find all S nodes nodes = root.findall("./S") new_msg = "" for s in nodes: # append error msg string to result, also # the hex chars represent CRLF so we replace with newline new_msg += s.text.replace("_x000D__x000A_", "\n") except Exception as e: # if any of the above fails, the msg was not true xml # print a warning and return the orignal string # TODO do not print, raise user defined error instead print("Warning: there was a problem converting the Powershell" " error message: %s" % (e)) else: # if new_msg was populated, that's our error message # otherwise the original error message will be used if len(new_msg): # remove leading and trailing whitespace while we are here return new_msg.strip().encode('utf-8') # either failed to decode CLIXML or there was nothing to decode # just return the original message return msg def _strip_namespace(self, xml): """strips any namespaces from an xml string""" p = re.compile(b"xmlns=*[\"\"][^\"\"]*[\"\"]") allmatches = p.finditer(xml) for match in allmatches: xml = xml.replace(match.group(), b"") return xml @staticmethod def _build_url(target, transport): match = re.match( '(?i)^((?P<scheme>http[s]?)://)?(?P<host>[0-9a-z-_.]+)(:(?P<port>\d+))?(?P<path>(/)?(wsman)?)?', target) # NOQA scheme = match.group('scheme') if not scheme: # TODO do we have anything other than HTTP/HTTPS scheme = 'https' if transport == 'ssl' else 'http' host = match.group('host') port = match.group('port') if not port: port = 5986 if transport == 'ssl' else 5985 path = match.group('path') if not path: path = 'wsman' return '{0}://{1}:{2}/{3}'.format(scheme, host, port, path.lstrip('/'))
class Session(object): # TODO implement context manager methods def __init__(self, target, auth, **kwargs): username, password = auth self.url = self._build_url(target, kwargs.get('transport', 'plaintext')) self.protocol = Protocol(self.url, username=username, password=password, **kwargs) def run_cmd(self, command, args=()): # TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell(codepage=65001) # utf-8 command_id = self.protocol.run_command(shell_id, command, args) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) self.protocol.close_shell(shell_id) return rs def run_ps(self, script): """base64 encodes a Powershell script and executes the powershell encoded script command """ script_bytes = script.encode('utf-8') packed_expression = b64encode(script_bytes).decode('ascii') # Use a custom strategy that encodes the script as UTF-8 instead of the # UTF-16-LE encoding employed by PowerShell's "-EncodedCommand". This # improves performance and increases the maximum script size by # reducing the size of the payload. expression_template = ( 'Invoke-Expression ' '$([System.Text.Encoding]::UTF8.GetString(' "[Convert]::FromBase64String('{0}'))" # NOQA ')') command = expression_template.format(packed_expression) rs = self.run_cmd('powershell -command "{0}"'.format(command)) if len(rs.std_err): # if there was an error message, clean it it up and make it human # readable rs.std_err = self._clean_error_msg(rs.std_err) return rs def _clean_error_msg(self, msg): """converts a Powershell CLIXML message to a more human readable string """ # TODO prepare unit test, beautify code if sys.version_info[:2] == (3, 7) and not isinstance(msg, text_type): msg = msg.decode('utf-8') # if the msg does not start with this, return it as is if msg.startswith("b#< CLIXML"): # for proper xml, we need to remove the CLIXML part # (the first line) msg_xml = msg[11:] try: # remove the namespaces from the xml for easier processing msg_xml = self._strip_namespace(msg_xml) root = ET.fromstring(msg_xml) # the S node is the error message, find all S nodes nodes = root.findall("./S") new_msg = "" for s in nodes: # append error msg string to result, also # the hex chars represent CRLF so we replace with newline new_msg += s.text.replace("_x000D__x000A_", "\n") except Exception as e: # if any of the above fails, the msg was not true xml # print a warning and return the orignal string # TODO do not print, raise user defined error instead print("Warning: there was a problem converting the Powershell" " error message: %s" % (e)) else: # if new_msg was populated, that's our error message # otherwise the original error message will be used if len(new_msg): # remove leading and trailing whitespace while we are here msg = new_msg.strip().encode('utf-8') return msg def _strip_namespace(self, xml): """strips any namespaces from an xml string""" p = re.compile(b"xmlns=*[\"\"][^\"\"]*[\"\"]") allmatches = p.finditer(xml) for match in allmatches: xml = xml.replace(match.group(), b"") return xml @staticmethod def _build_url(target, transport): match = re.match( '(?i)^((?P<scheme>http[s]?)://)?(?P<host>[0-9a-z-_.]+)(:(?P<port>\d+))?(?P<path>(/)?(wsman)?)?', target) # NOQA scheme = match.group('scheme') if not scheme: # TODO do we have anything other than HTTP/HTTPS scheme = 'https' if transport == 'ssl' else 'http' host = match.group('host') port = match.group('port') if not port: port = 5986 if transport == 'ssl' else 5985 path = match.group('path') if not path: path = 'wsman' return '{0}://{1}:{2}/{3}'.format(scheme, host, port, path.lstrip('/'))
class Session(object): # TODO implement context manager methods def __init__(self, target, auth, transport='plaintext'): username, password = auth self.url = self._build_url(target, transport) self.protocol = Protocol(self.url, transport=transport, username=username, password=password) def run_cmd(self, command, args=()): # TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell() command_id = self.protocol.run_command(shell_id, command, args) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) self.protocol.close_shell(shell_id) return rs def run_ps_long(self, script): """base64 encodes a Powershell script and executes the powershell encoded script command """ shell_id = self.protocol.open_shell() def run_command(command): command_id = self.protocol.run_command(shell_id, command) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) # Powershell errors are returned in XML, clean them up if len(rs.std_err): rs.std_err = self.clean_error_msg(rs.std_err) return rs def make_ps_command(ps_script): return ("powershell -encodedcommand %s" % base64.b64encode(ps_script.encode("utf_16_le"))) def run_and_check_ps(command, stage_message): rs = run_command(command) if len(rs.std_err) or rs.status_code != 0: self.protocol.close_shell(shell_id) raise Exception("%s\n%s" % (stage_message, rs.std_err)) return rs.std_out # Get the name of a temp file cmd = ("$script_file = [IO.Path]::GetTempFileName() | " " Rename-Item -NewName { $_ -replace 'tmp$', 'tmp.ps1' } -PassThru\n" '"$script_file"') script_file = run_and_check_ps(make_ps_command(cmd), "Creating temp script file") script_file = script_file.strip() # Append the data to the file base64_script = base64.b64encode(script) chunk_size = 2000 for chunk_index in range(0, len(base64_script), chunk_size): chunk = base64_script[chunk_index:chunk_index + chunk_size] cmd ='ECHO %s %s "%s" ' % (chunk, ('>>' if chunk_index else '>'), script_file) run_and_check_ps(cmd, "writing chunk %s to temp script file" % chunk_index) # Execute the powershell script cmd = ''' # Convert it from b64 encoded $b64 = get-content "%(script_file)s" [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($b64)) | out-file -Encoding Default "%(script_file)s" ''' % {'script_file':script_file} run_and_check_ps(make_ps_command(cmd), "Converting temp script file back from b64 encoding") cmd = ("""PowerShell.exe -ExecutionPolicy Bypass -Command "& '%s' " """ % script_file) rs = run_command(cmd) # Finally, cleanup the temp file cmd = "remove-item '%s' " % script_file run_and_check_ps(make_ps_command(cmd), "Deleting temp script file") self.protocol.close_shell(shell_id) return rs def run_ps(self, script): # Get a temp powershell file name # TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell() base64_script = base64.b64encode(script.encode("utf_16_le")) # There is an issue with powershell scripts over 2k or 8k (platform dependent) # You can not have a command line + argument longer than this if len(base64_script) > 2000: return self.run_ps_long(script) # must use utf16 little endian on windows rs = self.run_cmd("powershell -encodedcommand %s" % (base64_script)) if len(rs.std_err): # Clean it it up and make it human readable rs.std_err = self.clean_error_msg(rs.std_err) return rs def clean_error_msg(self, msg): """converts a Powershell CLIXML message to a more human readable string """ # if the msg does not start with this, return it as is if msg.startswith("#< CLIXML\r\n"): # for proper xml, we need to remove the CLIXML part # (the first line) msg_xml = msg[11:] try: # remove the namespaces from the xml for easier processing msg_xml = self.strip_namespace(msg_xml) root = ET.fromstring(msg_xml) # the S node is the error message, find all S nodes nodes = root.findall("./S") new_msg = "" for s in nodes: # append error msg string to result, also # the hex chars represent CRLF so we replace with newline new_msg += s.text.replace("_x000D__x000A_", "\n") except Exception as e: # if any of the above fails, the msg was not true xml # print a warning and return the orignal string print("Warning: there was a problem converting the Powershell" " error message: %s" % (e)) else: # if new_msg was populated, that's our error message # otherwise the original error message will be used if len(new_msg): # remove leading and trailing whitespace while we are here msg = new_msg.strip() return msg def strip_namespace(self, xml): """strips any namespaces from an xml string""" try: p = re.compile("xmlns=*[\"\"][^\"\"]*[\"\"]") allmatches = p.finditer(xml) for match in allmatches: xml = xml.replace(match.group(), "") return xml except Exception as e: raise Exception(e) @staticmethod def _build_url(target, transport): match = re.match( '(?i)^((?P<scheme>http[s]?)://)?(?P<host>[0-9a-z-_.]+)(:(?P<port>\d+))?(?P<path>(/)?(wsman)?)?', target) # NOQA scheme = match.group('scheme') if not scheme: # TODO do we have anything other than HTTP/HTTPS scheme = 'https' if transport == 'ssl' else 'http' host = match.group('host') port = match.group('port') if not port: port = 5986 if transport == 'ssl' else 5985 path = match.group('path') if not path: path = 'wsman' return '{0}://{1}:{2}/{3}'.format(scheme, host, port, path.lstrip('/'))
class Session(object): # TODO implement context manager methods def __init__(self, target, auth, transport='plaintext', timeout=None): username, password = auth self.url = self._build_url(target, transport) self.protocol = Protocol(self.url, transport=transport, username=username, password=password, timeout=timeout) def run_cmd(self, command, args=()): # TODO optimize perf. Do not call open/close shell every time shell_id = self.protocol.open_shell() command_id = self.protocol.run_command(shell_id, command, args) rs = Response(self.protocol.get_command_output(shell_id, command_id)) self.protocol.cleanup_command(shell_id, command_id) self.protocol.close_shell(shell_id) return rs def run_ps(self, script): """base64 encodes a Powershell script and executes the powershell encoded script command """ # must use utf16 little endian on windows encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii') rs = self.run_cmd('powershell -encodedcommand {0}'.format(encoded_ps)) if len(rs.std_err): # if there was an error message, clean it it up and make it human # readable rs.std_err = self._clean_error_msg(rs.std_err) return rs def _clean_error_msg(self, msg): """converts a Powershell CLIXML message to a more human readable string """ # TODO prepare unit test, beautify code # if the msg does not start with this, return it as is if msg.startswith("#< CLIXML\r\n"): # for proper xml, we need to remove the CLIXML part # (the first line) msg_xml = msg[11:] try: # remove the namespaces from the xml for easier processing msg_xml = self._strip_namespace(msg_xml) root = ET.fromstring(msg_xml) # the S node is the error message, find all S nodes nodes = root.findall("./S") new_msg = "" for s in nodes: # append error msg string to result, also # the hex chars represent CRLF so we replace with newline new_msg += s.text.replace("_x000D__x000A_", "\n") except Exception as e: # if any of the above fails, the msg was not true xml # print a warning and return the orignal string # TODO do not print, raise user defined error instead print("Warning: there was a problem converting the Powershell" " error message: %s" % (e)) else: # if new_msg was populated, that's our error message # otherwise the original error message will be used if len(new_msg): # remove leading and trailing whitespace while we are here msg = new_msg.strip() return msg def _strip_namespace(self, xml): """strips any namespaces from an xml string""" try: p = re.compile("xmlns=*[\"\"][^\"\"]*[\"\"]") allmatches = p.finditer(xml) for match in allmatches: xml = xml.replace(match.group(), "") return xml except Exception as e: raise Exception(e) @staticmethod def _build_url(target, transport): match = re.match( '(?i)^((?P<scheme>http[s]?)://)?(?P<host>[0-9a-z-_.]+)(:(?P<port>\d+))?(?P<path>(/)?(wsman)?)?', target) # NOQA scheme = match.group('scheme') if not scheme: # TODO do we have anything other than HTTP/HTTPS scheme = 'https' if transport == 'ssl' else 'http' host = match.group('host') port = match.group('port') if not port: port = 5986 if transport == 'ssl' else 5985 path = match.group('path') if not path: path = 'wsman' return '{0}://{1}:{2}/{3}'.format(scheme, host, port, path.lstrip('/'))
endpoint='http://' + host + ':5985/wsman', transport='ntlm', username=user, password=pasw ) sh = p.open_shell() rin = 'hostname' while rin != 'exit': if rin != None and rin != '': if rin.find("cd ") == 0: cds = rin[3:] cds.strip() if cds != None and cds != '': p.close_shell(sh) sh = p.open_shell(working_directory=cds) rin = 'cd' try: cmd = p.run_command(sh, rin, []) rout, rerr, stat = p.get_command_output(sh, cmd) if rout != None and rerr != '': t = rout.decode('utf-8') if t != None: print("%s" % t.strip()) if rerr != None and rerr != '': t = rerr.decode('utf-8') if t != None: print("%s" % t.strip()) p.cleanup_command(sh, cmd)
from winrm.protocol import Protocol p = Protocol(endpoint='http://<host fqdn>:5985/wsman', transport='ntlm', username='', password='', server_cert_validation='ignore') shell_id = p.open_shell() #command_id = p.run_command(shell_id, 'ipconfig', ['/all']) command_id = p.run_command(shell_id, 'powershell', ['$PSVersionTable']) std_out, std_err, status_code = p.get_command_output(shell_id, command_id) print(std_out) p.cleanup_command(shell_id, command_id) p.close_shell(shell_id)
# Run a process on a remote host s = winrm.Session('windows-host.example.com', auth=('john.smith', 'secret')) r = s.run_cmd('ipconfig', ['/all']) print r.status_code, r.std_out, # Run Powershell script on remote host ps_script = """$strComputer = $Host Clear $RAM = WmiObject Win32_ComputerSystem $MB = 1048576 "Installed Memory: " + [int]($RAM.TotalPhysicalMemory /$MB) + " MB" """ r = s.run_ps(ps_script) print r.status_code, r.std_out, # Run process with low-level API with domain user, disabling HTTPS cert validation from winrm.protocol import Protocol p = Protocol( endpoint='https://windows-host:5986/wsman', transport='ntlm', username=r'somedomain\someuser', 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)