class WinRM::HTTP::HttpTransport
A generic HTTP
transport that utilized HTTPClient to send messages back and forth. This backend will maintain state for every WinRMWebService instance that is instantiated so it is possible to use GSSAPI with Keep-Alive.
Attributes
Public Class Methods
Source
# File lib/winrm/http/transport.rb, line 26 def initialize(endpoint, options) @endpoint = endpoint.is_a?(String) ? URI.parse(endpoint) : endpoint @httpcli = HTTPClient.new @logger = Logging.logger[self] @httpcli.receive_timeout = options[:receive_timeout] @httpcli.default_header = { 'User-Agent': options[:user_agent] } end
Public Instance Methods
Source
# File lib/winrm/http/transport.rb, line 57 def basic_auth_only! auths = @httpcli.www_auth.instance_variable_get('@authenticator') auths.delete_if { |i| i.scheme !~ /basic/i } end
We’ll need this to force basic authentication if desired
Source
# File lib/winrm/http/transport.rb, line 69 def no_ssl_peer_verification! @httpcli.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE end
Disable SSL Peer Verification
Source
# File lib/winrm/http/transport.rb, line 63 def no_sspi_auth! auths = @httpcli.www_auth.instance_variable_get('@authenticator') auths.delete_if { |i| i.is_a? HTTPClient::SSPINegotiateAuth } end
Disable SSPI Auth
Source
# File lib/winrm/http/transport.rb, line 39 def send_request(message) ssl_peer_fingerprint_verification! log_soap_message(message) hdr = { 'Content-Type' => 'application/soap+xml;charset=UTF-8', 'Content-Length' => message.bytesize } # We need to add this header if using Client Certificate authentication unless @httpcli.ssl_config.client_cert.nil? hdr['Authorization'] = 'http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/https/mutual' end resp = @httpcli.post(@endpoint, message, hdr) log_soap_message(resp.http_body.content) verify_ssl_fingerprint(resp.peer_cert) handler = WinRM::ResponseHandler.new(resp.http_body.content, resp.status) handler.parse_to_xml end
Sends the SOAP payload to the WinRM
service and returns the service’s SOAP response. If an error occurrs an appropriate error is raised.
@param [String] The XML SOAP message @returns [REXML::Document] The parsed response body
Source
# File lib/winrm/http/transport.rb, line 74 def ssl_peer_fingerprint_verification! return unless @ssl_peer_fingerprint && !@ssl_peer_fingerprint_verified with_untrusted_ssl_connection do |connection| connection_cert = connection.peer_cert verify_ssl_fingerprint(connection_cert) end @logger.info("initial ssl fingerprint #{@ssl_peer_fingerprint} verified\n") @ssl_peer_fingerprint_verified = true no_ssl_peer_verification! end
SSL Peer Fingerprint Verification prior to connecting
Source
# File lib/winrm/http/transport.rb, line 101 def verify_ssl_fingerprint(cert) return unless @ssl_peer_fingerprint conn_fingerprint = OpenSSL::Digest::SHA1.new(cert.to_der).to_s return unless @ssl_peer_fingerprint.casecmp(conn_fingerprint) != 0 raise "ssl fingerprint mismatch!!!!\n" end
compare @ssl_peer_fingerprint to current ssl context
Source
# File lib/winrm/http/transport.rb, line 87 def with_untrusted_ssl_connection noverify_peer_context = OpenSSL::SSL::SSLContext.new noverify_peer_context.verify_mode = OpenSSL::SSL::VERIFY_NONE tcp_connection = TCPSocket.new(@endpoint.host, @endpoint.port) begin ssl_connection = OpenSSL::SSL::SSLSocket.new(tcp_connection, noverify_peer_context) ssl_connection.connect yield ssl_connection ensure tcp_connection.close end end
Connect without verification to retrieve untrusted ssl context
Protected Instance Methods
Source
# File lib/winrm/http/transport.rb, line 112 def body(message, length, type = 'application/HTTP-SPNEGO-session-encrypted') [ '--Encrypted Boundary', "Content-Type: #{type}", "OriginalContent: type=application/soap+xml;charset=UTF-8;Length=#{length}", '--Encrypted Boundary', 'Content-Type: application/octet-stream', "#{message}--Encrypted Boundary--" ].join("\r\n").concat("\r\n") end
Source
# File lib/winrm/http/transport.rb, line 123 def log_soap_message(message) return unless @logger.debug? xml_msg = REXML::Document.new(message) formatter = REXML::Formatters::Pretty.new(2) formatter.compact = true formatter.write(xml_msg, @logger) @logger.debug("\n") rescue StandardError => e @logger.debug("Couldn't log SOAP request/response: #{e.message} - #{message}") end