summaryrefslogtreecommitdiff
path: root/lib/ansible/module_utils/urls.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/module_utils/urls.py')
-rw-r--r--lib/ansible/module_utils/urls.py82
1 files changed, 49 insertions, 33 deletions
diff --git a/lib/ansible/module_utils/urls.py b/lib/ansible/module_utils/urls.py
index 979d5943dd..41613f6cb6 100644
--- a/lib/ansible/module_utils/urls.py
+++ b/lib/ansible/module_utils/urls.py
@@ -310,36 +310,45 @@ class NoSSLError(SSLValidationError):
"""Needed to connect to an HTTPS url but no ssl library available to verify the certificate"""
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)
+
+ def connect(self):
+ "Connect to a host on a given (SSL) port."
+
+ if hasattr(self, 'source_address'):
+ sock = socket.create_connection((self.host, self.port), self.timeout, self.source_address)
+ else:
+ sock = socket.create_connection((self.host, self.port), self.timeout)
+
+ server_hostname = self.host
+ # Note: self._tunnel_host is not available on py < 2.6 but this code
+ # isn't used on py < 2.6 (lack of create_connection)
+ if self._tunnel_host:
+ self.sock = sock
+ self._tunnel()
+ server_hostname = self._tunnel_host
+
+ 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)
-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)
-
- def connect(self):
- "Connect to a host on a given (SSL) port."
-
- if hasattr(self, 'source_address'):
- 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 self._tunnel_host:
- self.sock = sock
- self._tunnel()
- 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):
+ class CustomHTTPSHandler(urllib2.HTTPSHandler):
- def https_open(self, req):
- return self.do_open(CustomHTTPSConnection, req)
+ def https_open(self, req):
+ return self.do_open(CustomHTTPSConnection, req)
- https_request = urllib2.AbstractHTTPHandler.do_request_
+ https_request = urllib2.AbstractHTTPHandler.do_request_
def generic_urlparse(parts):
'''
@@ -373,7 +382,10 @@ def generic_urlparse(parts):
# get the username, password, etc.
try:
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:
# the capture group for the port will include the ':',
# 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
auth = auth[:-1]
username, password = auth.split(':', 1)
+ else:
+ username = password = None
generic_parts['username'] = username
generic_parts['password'] = password
generic_parts['hostname'] = hostname
@@ -390,7 +404,7 @@ def generic_urlparse(parts):
except:
generic_parts['username'] = None
generic_parts['password'] = None
- generic_parts['hostname'] = None
+ generic_parts['hostname'] = parts[1]
generic_parts['port'] = None
return generic_parts
@@ -532,7 +546,8 @@ class SSLValidationHandler(urllib2.BaseHandler):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if 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':
s.sendall(self.CONNECT_COMMAND % (self.hostname, self.port))
if proxy_parts.get('username'):
@@ -542,7 +557,7 @@ class SSLValidationHandler(urllib2.BaseHandler):
connect_result = s.recv(4096)
self.validate_proxy_response(connect_result)
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:
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)
@@ -661,8 +676,9 @@ def open_url(url, data=None, headers=None, method=None, use_proxy=True,
handlers.append(proxyhandler)
# pre-2.6 versions of python cannot use the custom https
- # handler, since the socket class is lacking this method
- if hasattr(socket, 'create_connection'):
+ # handler, since the socket class is lacking create_connection.
+ # Some python builds lack HTTPS support.
+ if hasattr(socket, 'create_connection') and CustomHTTPSHandler:
handlers.append(CustomHTTPSHandler)
opener = urllib2.build_opener(*handlers)