def send_message(self, message): headers = { 'Content-Type': 'application/soap+xml;charset=UTF-8', 'Content-Length': len(message), 'User-Agent': 'Python WinRM client' } password_manager = HTTPPasswordMgrWithDefaultRealm() password_manager.add_password(None, self.endpoint, self.username, self.password) auth_manager = HTTPBasicAuthHandler(password_manager) opener = build_opener(auth_manager) install_opener(opener) request = Request(self.endpoint, data=message, headers=headers) try: response = urlopen(request, timeout=self.timeout) # Version 1.1 of WinRM adds the namespaces in the document instead of the envelope so we have to # add them ourselves here. This should have no affect version 2. response_text = response.read() return response_text #doc = ElementTree.fromstring(response.read()) #Ruby #doc = Nokogiri::XML(resp.http_body.content) #doc.collect_namespaces.each_pair do |k,v| # doc.root.add_namespace((k.split(/:/).last),v) unless doc.namespaces.has_key?(k) #end #return doc #return doc except HTTPError as ex: error_message = 'Bad HTTP response returned from server. Code {0}'.format( ex.code) if ex.msg: error_message += ', {0}'.format(ex.msg) raise WinRMTransportError(error_message) except URLError as ex: raise WinRMTransportError(ex.reason)
def send_message(self, message): headers = self._headers.copy() headers['Content-Length'] = len(message) self._setup_opener() request = Request(self.endpoint, data=message, headers=headers) try: response = urlopen(request, timeout=self.timeout) # Version 1.1 of WinRM adds the namespaces in the document instead of the envelope so we have to # add them ourselves here. This should have no affect version 2. response_text = response.read() return response_text #doc = ElementTree.fromstring(response.read()) #Ruby #doc = Nokogiri::XML(resp.http_body.content) #doc.collect_namespaces.each_pair do |k,v| # doc.root.add_namespace((k.split(/:/).last),v) unless doc.namespaces.has_key?(k) #end #return doc #return doc except HTTPError as ex: error_message = 'Bad HTTP response returned from server. Code {0}'.format(ex.code) if ex.msg: error_message += ', {0}'.format(ex.msg) raise WinRMTransportError(error_message) except URLError as ex: raise WinRMTransportError(ex.reason)
def send_message(self, message): # TODO current implementation does negotiation on each HTTP request which is not efficient # TODO support kerberos session with message encryption krb_ticket = KerberosTicket(self.krb_service) headers = { 'Authorization': krb_ticket.auth_header, 'Connection': 'Keep-Alive', 'Content-Type': 'application/soap+xml;charset=UTF-8', 'User-Agent': 'Python WinRM client' } request = Request(self.endpoint, data=message, headers=headers) try: response = urlopen(request, timeout=self.timeout) krb_ticket.verify_response(response.headers['WWW-Authenticate']) response_text = response.read() return response_text except HTTPError as ex: #if ex.code == 401 and ex.headers['WWW-Authenticate'] == 'Negotiate, Basic realm="WSMAN"': error_message = 'Kerberos-based authentication was failed. Code {0}'.format( ex.code) if ex.msg: error_message += ', {0}'.format(ex.msg) raise WinRMTransportError(error_message) except URLError as ex: raise WinRMTransportError(ex.reason)
def send_message(self, message): # TODO current implementation does negotiation on each HTTP request which is not efficient # TODO support kerberos session with message encryption krb_ticket = KerberosTicket(self.krb_service) headers = { 'Authorization': krb_ticket.auth_header, 'Connection': 'Keep-Alive', 'Content-Type': 'application/soap+xml;charset=UTF-8', 'User-Agent': 'Python WinRM client' } request = Request(self.endpoint, data=message, headers=headers) try: response = urlopen(request, timeout=self.timeout) krb_ticket.verify_response(response.headers['WWW-Authenticate']) response_text = response.read() return response_text except HTTPError as ex: response_text = ex.read() # Per http://msdn.microsoft.com/en-us/library/cc251676.aspx rule 3, # should handle this 500 error and retry receiving command output. if 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive' in message and 'Code="2150858793"' in response_text: return response_text #if ex.code == 401 and ex.headers['WWW-Authenticate'] == 'Negotiate, Basic realm="WSMAN"': error_message = 'Kerberos-based authentication was failed. Code {0}'.format( ex.code) if ex.msg: error_message += ', {0}'.format(ex.msg) raise WinRMTransportError('kerberos', error_message) except URLError as ex: raise WinRMTransportError('kerberos', ex.reason)
def send_message(self, message): # TODO support kerberos/ntlm session with message encryption if not self.session: self.session = self.build_session() # urllib3 fails on SSL retries with unicode buffers- must send it a byte string # see https://github.com/shazow/urllib3/issues/717 if isinstance(message, unicode_type): message = message.encode('utf-8') request = requests.Request('POST', self.endpoint, data=message) prepared_request = self.session.prepare_request(request) try: response = self.session.send(prepared_request, timeout=self.read_timeout_sec) response_text = response.text response.raise_for_status() return response_text except requests.HTTPError as ex: if ex.response.status_code == 401: raise InvalidCredentialsError("the specified credentials were rejected by the server") if ex.response.content: response_text = ex.response.content else: response_text = '' # Per http://msdn.microsoft.com/en-us/library/cc251676.aspx rule 3, # should handle this 500 error and retry receiving command output. if b'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive' in message and b'Code="2150858793"' in response_text: raise WinRMOperationTimeoutError() error_message = 'Bad HTTP response returned from server. Code {0}'.format(ex.response.status_code) raise WinRMTransportError('http', error_message)
def __init__(self, endpoint, realm=None, service='HTTP', keytab=None, server_cert_validation='validate'): """ Uses Kerberos/GSS-API to authenticate and encrypt messages @param string endpoint: the WinRM webservice endpoint @param string realm: the Kerberos realm we are authenticating to @param string service: the service name, default is HTTP @param string keytab: the path to a keytab file if you are using one """ if not HAVE_KERBEROS: raise WinRMTransportError('kerberos', 'kerberos is not installed') super(HttpKerberos, self).__init__(endpoint, None, None) parsed_url = urlparse(endpoint) self.krb_service = '{0}@{1}'.format(service, parsed_url.hostname) self.scheme = parsed_url.scheme self._server_cert_validation = server_cert_validation if HAVE_SSLCONTEXT and server_cert_validation == 'ignore': self.sslcontext = create_default_context() self.sslcontext.check_hostname = False self.sslcontext.verify_mode = CERT_NONE else: self.sslcontext = None
def send_message(self, message): headers = self._headers.copy() headers['Content-Length'] = len(message) self._setup_opener() request = Request(self.endpoint, data=message, headers=headers) try: # install_opener is ignored in > 2.7.9 when an SSLContext is passed to urlopen, so # we'll have to call open manually with our stored opener chain response = self.opener.open(request, timeout=self.timeout) # Version 1.1 of WinRM adds the namespaces in the document instead # of the envelope so we have to # add them ourselves here. This should have no affect version 2. response_text = response.read() return response_text # doc = ElementTree.fromstring(response.read()) # Ruby # doc = Nokogiri::XML(resp.http_body.content) # doc.collect_namespaces.each_pair do |k,v| # doc.root.add_namespace((k.split(/:/).last),v) # unless doc.namespaces.has_key?(k) # end # return doc # return doc except HTTPError as ex: if ex.code == 401: raise UnauthorizedError(transport='plaintext', message=ex.msg) response_text = ex.read() # Per http://msdn.microsoft.com/en-us/library/cc251676.aspx rule 3, # should handle this 500 error and retry receiving command output. if 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive' in message and 'Code="2150858793"' in response_text: # NOQA # TODO raise TimeoutError here instead of just return text return response_text error_message = 'Bad HTTP response returned from server. ' \ ' Code {0}'.format(ex.code) if ex.msg: error_message += ', {0}'.format(ex.msg) raise WinRMTransportError('http', error_message) except URLError as ex: raise WinRMTransportError('http', ex.reason)
def __init__(self, endpoint, realm=None, service='HTTP', keytab=None): """ Uses Kerberos/GSS-API to authenticate and encrypt messages @param string endpoint: the WinRM webservice endpoint @param string realm: the Kerberos realm we are authenticating to @param string service: the service name, default is HTTP @param string keytab: the path to a keytab file if you are using one """ if not HAVE_KERBEROS: raise WinRMTransportError('kerberos is not installed') super(HttpKerberos, self).__init__(endpoint, None, None) self.krb_service = '{0}@{1}'.format(service, urlparse(endpoint).hostname)
def _send_message_request(self, prepared_request, message): try: response = self.session.send(prepared_request, timeout=self.read_timeout_sec) response.raise_for_status() return response except requests.HTTPError as ex: if ex.response.status_code == 401: raise InvalidCredentialsError("the specified credentials were rejected by the server") if ex.response.content: response_text = self._get_message_response_text(ex.response) else: response_text = '' raise WinRMTransportError('http', ex.response.status_code, response_text)
def send_message(self, message): # TODO support kerberos/ntlm session with message encryption if not self.session: self.session = self.build_session() # urllib3 fails on SSL retries with unicode buffers- must send it a byte string # see https://github.com/shazow/urllib3/issues/717 if isinstance(message, unicode_type): message = message.encode('utf-8') request = requests.Request('POST', self.endpoint, data=message) prepared_request = self.session.prepare_request(request) try: response = self.session.send(prepared_request, timeout=self.read_timeout_sec) response_text = response.text response.raise_for_status() return response_text except requests.HTTPError as ex: if ex.response.status_code == 401: raise InvalidCredentialsError("the specified credentials were rejected by the server") if ex.response.content: response_text = ex.response.content else: response_text = '' # Per http://msdn.microsoft.com/en-us/library/cc251676.aspx rule 3, # should handle this 500 error and retry receiving command output. if b'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive' in message and b'Code="2150858793"' in response_text: raise WinRMOperationTimeoutError() error_message = 'Bad HTTP response returned from server. Code {0}'.format(ex.response.status_code) import xml.etree.ElementTree as ET if response_text: root = ET.fromstring(response_text) ns = {'s': "http://www.w3.org/2003/05/soap-envelope", 'a': "http://schemas.xmlsoap.org/ws/2004/08/addressing", 'w': "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"} for text in root.findall('s:Body/s:Fault/s:Reason/s:Text', ns): error_message += "\n%s" % text.text raise WinRMTransportError('http', error_message)
def _send_message_request(self, prepared_request, message): try: response = self.session.send(prepared_request, timeout=self.read_timeout_sec) response.raise_for_status() return response except requests.HTTPError as ex: if ex.response.status_code == 401: raise InvalidCredentialsError("the specified credentials were rejected by the server") if ex.response.content: response_text = self._get_message_response_text(ex.response) else: response_text = '' # Per http://msdn.microsoft.com/en-us/library/cc251676.aspx rule 3, # should handle this 500 error and retry receiving command output. if b'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive' in message and b'Code="2150858793"' in response_text: raise WinRMOperationTimeoutError() error_message = 'Bad HTTP response returned from server. Code {0}'.format(ex.response.status_code) raise WinRMTransportError('http', error_message)