mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Merge pull request #13573 from ansible/ssl-context-with-proxy
Fix a few problems with url handling.
This commit is contained in:
commit
7d519127fe
1 changed files with 46 additions and 30 deletions
|
@ -310,36 +310,45 @@ class NoSSLError(SSLValidationError):
|
||||||
"""Needed to connect to an HTTPS url but no ssl library available to verify the certificate"""
|
"""Needed to connect to an HTTPS url but no ssl library available to verify the certificate"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Some environments (Google Compute Engine's CoreOS deploys) do not compile
|
||||||
|
# against openssl and thus do not have any HTTPS support.
|
||||||
|
CustomHTTPSConnection = CustomHTTPSHandler = None
|
||||||
|
if hasattr(httplib, 'HTTPSConnection') and hasattr(urllib2, 'HTTPSHandler'):
|
||||||
|
class CustomHTTPSConnection(httplib.HTTPSConnection):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
httplib.HTTPSConnection.__init__(self, *args, **kwargs)
|
||||||
|
if HAS_SSLCONTEXT:
|
||||||
|
self.context = create_default_context()
|
||||||
|
if self.cert_file:
|
||||||
|
self.context.load_cert_chain(self.cert_file, self.key_file)
|
||||||
|
|
||||||
class CustomHTTPSConnection(httplib.HTTPSConnection):
|
def connect(self):
|
||||||
def __init__(self, *args, **kwargs):
|
"Connect to a host on a given (SSL) port."
|
||||||
httplib.HTTPSConnection.__init__(self, *args, **kwargs)
|
|
||||||
if HAS_SSLCONTEXT:
|
|
||||||
self.context = create_default_context()
|
|
||||||
if self.cert_file:
|
|
||||||
self.context.load_cert_chain(self.cert_file, self.key_file)
|
|
||||||
|
|
||||||
def connect(self):
|
if hasattr(self, 'source_address'):
|
||||||
"Connect to a host on a given (SSL) port."
|
sock = socket.create_connection((self.host, self.port), self.timeout, self.source_address)
|
||||||
|
else:
|
||||||
|
sock = socket.create_connection((self.host, self.port), self.timeout)
|
||||||
|
|
||||||
if hasattr(self, 'source_address'):
|
server_hostname = self.host
|
||||||
sock = socket.create_connection((self.host, self.port), self.timeout, self.source_address)
|
# Note: self._tunnel_host is not available on py < 2.6 but this code
|
||||||
else:
|
# isn't used on py < 2.6 (lack of create_connection)
|
||||||
sock = socket.create_connection((self.host, self.port), self.timeout)
|
if self._tunnel_host:
|
||||||
if self._tunnel_host:
|
self.sock = sock
|
||||||
self.sock = sock
|
self._tunnel()
|
||||||
self._tunnel()
|
server_hostname = self._tunnel_host
|
||||||
if HAS_SSLCONTEXT:
|
|
||||||
self.sock = self.context.wrap_socket(sock, server_hostname=self.host)
|
|
||||||
else:
|
|
||||||
self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=PROTOCOL)
|
|
||||||
|
|
||||||
class CustomHTTPSHandler(urllib2.HTTPSHandler):
|
if HAS_SSLCONTEXT:
|
||||||
|
self.sock = self.context.wrap_socket(sock, server_hostname=server_hostname)
|
||||||
|
else:
|
||||||
|
self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=PROTOCOL)
|
||||||
|
|
||||||
def https_open(self, req):
|
class CustomHTTPSHandler(urllib2.HTTPSHandler):
|
||||||
return self.do_open(CustomHTTPSConnection, req)
|
|
||||||
|
|
||||||
https_request = urllib2.AbstractHTTPHandler.do_request_
|
def https_open(self, req):
|
||||||
|
return self.do_open(CustomHTTPSConnection, req)
|
||||||
|
|
||||||
|
https_request = urllib2.AbstractHTTPHandler.do_request_
|
||||||
|
|
||||||
def generic_urlparse(parts):
|
def generic_urlparse(parts):
|
||||||
'''
|
'''
|
||||||
|
@ -373,7 +382,10 @@ def generic_urlparse(parts):
|
||||||
# get the username, password, etc.
|
# get the username, password, etc.
|
||||||
try:
|
try:
|
||||||
netloc_re = re.compile(r'^((?:\w)+(?::(?:\w)+)?@)?([A-Za-z0-9.-]+)(:\d+)?$')
|
netloc_re = re.compile(r'^((?:\w)+(?::(?:\w)+)?@)?([A-Za-z0-9.-]+)(:\d+)?$')
|
||||||
(auth, hostname, port) = netloc_re.match(parts[1])
|
match = netloc_re.match(parts[1])
|
||||||
|
auth = match.group(1)
|
||||||
|
hostname = match.group(2)
|
||||||
|
port = match.group(3)
|
||||||
if port:
|
if port:
|
||||||
# the capture group for the port will include the ':',
|
# the capture group for the port will include the ':',
|
||||||
# so remove it and convert the port to an integer
|
# so remove it and convert the port to an integer
|
||||||
|
@ -383,6 +395,8 @@ def generic_urlparse(parts):
|
||||||
# and then split it up based on the first ':' found
|
# and then split it up based on the first ':' found
|
||||||
auth = auth[:-1]
|
auth = auth[:-1]
|
||||||
username, password = auth.split(':', 1)
|
username, password = auth.split(':', 1)
|
||||||
|
else:
|
||||||
|
username = password = None
|
||||||
generic_parts['username'] = username
|
generic_parts['username'] = username
|
||||||
generic_parts['password'] = password
|
generic_parts['password'] = password
|
||||||
generic_parts['hostname'] = hostname
|
generic_parts['hostname'] = hostname
|
||||||
|
@ -390,7 +404,7 @@ def generic_urlparse(parts):
|
||||||
except:
|
except:
|
||||||
generic_parts['username'] = None
|
generic_parts['username'] = None
|
||||||
generic_parts['password'] = None
|
generic_parts['password'] = None
|
||||||
generic_parts['hostname'] = None
|
generic_parts['hostname'] = parts[1]
|
||||||
generic_parts['port'] = None
|
generic_parts['port'] = None
|
||||||
return generic_parts
|
return generic_parts
|
||||||
|
|
||||||
|
@ -532,7 +546,8 @@ class SSLValidationHandler(urllib2.BaseHandler):
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
if https_proxy:
|
if https_proxy:
|
||||||
proxy_parts = generic_urlparse(urlparse.urlparse(https_proxy))
|
proxy_parts = generic_urlparse(urlparse.urlparse(https_proxy))
|
||||||
s.connect((proxy_parts.get('hostname'), proxy_parts.get('port')))
|
port = proxy_parts.get('port') or 443
|
||||||
|
s.connect((proxy_parts.get('hostname'), port))
|
||||||
if proxy_parts.get('scheme') == 'http':
|
if proxy_parts.get('scheme') == 'http':
|
||||||
s.sendall(self.CONNECT_COMMAND % (self.hostname, self.port))
|
s.sendall(self.CONNECT_COMMAND % (self.hostname, self.port))
|
||||||
if proxy_parts.get('username'):
|
if proxy_parts.get('username'):
|
||||||
|
@ -542,7 +557,7 @@ class SSLValidationHandler(urllib2.BaseHandler):
|
||||||
connect_result = s.recv(4096)
|
connect_result = s.recv(4096)
|
||||||
self.validate_proxy_response(connect_result)
|
self.validate_proxy_response(connect_result)
|
||||||
if context:
|
if context:
|
||||||
ssl_s = context.wrap_socket(s, server_hostname=proxy_parts.get('hostname'))
|
ssl_s = context.wrap_socket(s, server_hostname=self.hostname)
|
||||||
else:
|
else:
|
||||||
ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL)
|
ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL)
|
||||||
match_hostname(ssl_s.getpeercert(), self.hostname)
|
match_hostname(ssl_s.getpeercert(), self.hostname)
|
||||||
|
@ -661,8 +676,9 @@ def open_url(url, data=None, headers=None, method=None, use_proxy=True,
|
||||||
handlers.append(proxyhandler)
|
handlers.append(proxyhandler)
|
||||||
|
|
||||||
# pre-2.6 versions of python cannot use the custom https
|
# pre-2.6 versions of python cannot use the custom https
|
||||||
# handler, since the socket class is lacking this method
|
# handler, since the socket class is lacking create_connection.
|
||||||
if hasattr(socket, 'create_connection'):
|
# Some python builds lack HTTPS support.
|
||||||
|
if hasattr(socket, 'create_connection') and CustomHTTPSHandler:
|
||||||
handlers.append(CustomHTTPSHandler)
|
handlers.append(CustomHTTPSHandler)
|
||||||
|
|
||||||
opener = urllib2.build_opener(*handlers)
|
opener = urllib2.build_opener(*handlers)
|
||||||
|
|
Loading…
Reference in a new issue