def _get_server_api_version(self): """ Fetches the Galaxy API current version to ensure the API server is up and reachable. """ url = '%s/api/' % self._api_server try: return_data = open_url(url, validate_certs=self._validate_certs) except Exception as e: raise exceptions.GalaxyClientError( "Failed to get data from the API server (%s): %s " % (url, to_native(e))) try: data = json.loads( to_text(return_data.read(), errors='surrogate_or_strict')) except Exception as e: raise exceptions.GalaxyClientError( "Could not process data from the API server (%s): %s " % (url, to_native(e))) if 'current_version' not in data: raise exceptions.GalaxyClientError( "missing required 'current_version' from server response (%s)" % url) self.log.debug('Server API version of URL %s is "%s"', url, data['current_version']) return data['current_version']
def build_ssl_validation_error(hostname, port, paths, exc=None): '''Inteligently build out the SSLValidationError based on what support you have installed ''' msg = [('Failed to validate the SSL certificate for %s:%s.' ' Make sure your managed systems have a valid CA' ' certificate installed.')] if not HAS_SSLCONTEXT: msg.append('If the website serving the url uses SNI you need' ' python >= 2.7.9 on your managed machine') msg.append(' (the python executable used (%s) is version: %s)' % (sys.executable, ''.join(sys.version.splitlines()))) if not HAS_URLLIB3_PYOPENSSLCONTEXT or not HAS_URLLIB3_SSL_WRAP_SOCKET: msg.append('or you can install the `urllib3`, `pyOpenSSL`,' ' `ndg-httpsclient`, and `pyasn1` python modules') msg.append('to perform SNI verification in python >= 2.6.') msg.append('You can use validate_certs=False if you do' ' not need to confirm the servers identity but this is' ' unsafe and not recommended.' ' Paths checked for this platform: %s.') if exc: msg.append('The exception msg was: %s.' % to_native(exc)) raise SSLValidationError(' '.join(msg) % (hostname, port, ", ".join(paths)))
def _get_server_api_version(self): """ Fetches the Galaxy API current version to ensure the API server is up and reachable. """ url = '%s/api/' % self._api_server try: resp = self.session.get(url, verify=self._validate_certs) except requests.exceptions.RequestException as e: raise exceptions.GalaxyClientError( "Failed to get data from the API server (%s): %s " % (url, to_native(e))) try: # data = json.loads(to_text(return_data.read(), errors='surrogate_or_strict')) data = resp.json() except Exception as e: raise exceptions.GalaxyClientError( "Could not process data from the API server (%s): %s " % (url, to_native(e))) # Don't raise connection indicating errors unless we dont have valid error json try: resp.raise_for_status() except Exception as e: raise exceptions.GalaxyClientError( "Failed to get data from the API server (%s): %s " % (url, to_native(e))) if 'current_version' not in data: raise exceptions.GalaxyClientError( "missing required 'current_version' from server response (%s)" % url) self.log.debug('Server API version of URL %s is "%s"', url, data['current_version']) return data['current_version']
def http_request(self, req): tmp_ca_cert_path, to_add_ca_cert_path, paths_checked = self.get_ca_certs( ) https_proxy = os.environ.get('https_proxy') context = None try: context = self._make_context(to_add_ca_cert_path) except Exception: # We'll make do with no context below pass # Detect if 'no_proxy' environment variable is set and if our URL is included use_proxy = self.detect_no_proxy(req.get_full_url()) if not use_proxy: # ignore proxy settings for this host request if tmp_ca_cert_path: try: os.remove(tmp_ca_cert_path) except OSError: pass if to_add_ca_cert_path: try: os.remove(to_add_ca_cert_path) except OSError: pass return req try: if https_proxy: proxy_parts = generic_urlparse(urlparse(https_proxy)) port = proxy_parts.get('port') or 443 s = socket.create_connection( (proxy_parts.get('hostname'), port)) if proxy_parts.get('scheme') == 'http': s.sendall( to_bytes(self.CONNECT_COMMAND % (self.hostname, self.port), errors='surrogate_or_strict')) if proxy_parts.get('username'): credentials = "%s:%s" % (proxy_parts.get( 'username', ''), proxy_parts.get('password', '')) s.sendall( b'Proxy-Authorization: Basic %s\r\n' % base64.b64encode( to_bytes( credentials, errors='surrogate_or_strict')).strip()) s.sendall(b'\r\n') connect_result = b"" while connect_result.find(b"\r\n\r\n") <= 0: connect_result += s.recv(4096) # 128 kilobytes of headers should be enough for everyone. if len(connect_result) > 131072: raise ProxyError( 'Proxy sent too verbose headers. Only 128KiB allowed.' ) self.validate_proxy_response(connect_result) if context: ssl_s = context.wrap_socket( s, server_hostname=self.hostname) elif HAS_URLLIB3_SSL_WRAP_SOCKET: ssl_s = ssl_wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL, 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) else: raise ProxyError( 'Unsupported proxy scheme: %s. Currently ansible only supports HTTP proxies.' % proxy_parts.get('scheme')) else: s = socket.create_connection((self.hostname, self.port)) if context: ssl_s = context.wrap_socket(s, server_hostname=self.hostname) elif HAS_URLLIB3_SSL_WRAP_SOCKET: ssl_s = ssl_wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL, 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) # close the ssl connection # ssl_s.unwrap() s.close() except (ssl.SSLError, CertificateError) as e: build_ssl_validation_error(self.hostname, self.port, paths_checked, e) except socket.error as e: raise ConnectionError('Failed to connect to %s at port %s: %s' % (self.hostname, self.port, to_native(e))) try: # cleanup the temp file created, don't worry # if it fails for some reason os.remove(tmp_ca_cert_path) except: pass try: # cleanup the temp file created, don't worry # if it fails for some reason if to_add_ca_cert_path: os.remove(to_add_ca_cert_path) except: pass return req
def fetch_url(module, url, data=None, headers=None, method=None, use_proxy=True, force=False, last_mod_time=None, timeout=10): """Sends a request via HTTP(S) or FTP (needs the module as parameter) :arg module: The AnsibleModule (used to get username, password etc. (s.b.). :arg url: The url to use. :kwarg data: The data to be sent (in case of POST/PUT). :kwarg headers: A dict with the request headers. :kwarg method: "POST", "PUT", etc. :kwarg boolean use_proxy: Default: True :kwarg boolean force: If True: Do not get a cached copy (Default: False) :kwarg last_mod_time: Default: None :kwarg int timeout: Default: 10 :returns: A tuple of (**response**, **info**). Use ``response.read()`` to read the data. The **info** contains the 'status' and other meta data. When a HttpError (status > 400) occurred then ``info['body']`` contains the error response data:: Example:: data={...} resp, info = fetch_url(module, "http://example.com", data=module.jsonify(data) header={Content-type': 'application/json'}, method="POST") status_code = info["status"] body = resp.read() if status_code >= 400 : body = info['body'] """ if not HAS_URLPARSE: module.fail_json(msg='urlparse is not installed') # ensure we use proper tempdir old_tempdir = tempfile.tempdir tempfile.tempdir = module.tmpdir # Get validate_certs from the module params validate_certs = module.params.get('validate_certs', True) username = module.params.get('url_username', '') password = module.params.get('url_password', '') http_agent = module.params.get('http_agent', 'ansible-httpget') force_basic_auth = module.params.get('force_basic_auth', '') follow_redirects = module.params.get('follow_redirects', 'urllib2') client_cert = module.params.get('client_cert') client_key = module.params.get('client_key') cookies = cookiejar.LWPCookieJar() r = None info = dict(url=url) try: r = open_url(url, data=data, headers=headers, method=method, use_proxy=use_proxy, force=force, last_mod_time=last_mod_time, timeout=timeout, validate_certs=validate_certs, url_username=username, url_password=password, http_agent=http_agent, force_basic_auth=force_basic_auth, follow_redirects=follow_redirects, client_cert=client_cert, client_key=client_key, cookies=cookies) info.update(r.info()) # parse the cookies into a nice dictionary cookie_dict = dict() for cookie in cookies: cookie_dict[cookie.name] = cookie.value info['cookies'] = cookie_dict # finally update the result with a message about the fetch info.update( dict(msg="OK (%s bytes)" % r.headers.get('Content-Length', 'unknown'), url=r.geturl(), status=r.code)) except NoSSLError as e: # FIXME: can probably use python platform.py for this # distribution = get_distribution() # if distribution is not None and distribution.lower() == 'redhat': # module.fail_json(msg='%s. You can also install python-ssl from EPEL' % to_native(e)) # else: module.fail_json(msg='%s' % to_native(e)) except (ConnectionError, ValueError) as e: module.fail_json(msg=to_native(e)) except urllib_error.HTTPError as e: try: body = e.read() except AttributeError: body = '' # Try to add exception info to the output but don't fail if we can't try: info.update(dict(**e.info())) except: pass info.update({'msg': to_native(e), 'body': body, 'status': e.code}) except urllib_error.URLError as e: code = int(getattr(e, 'code', -1)) info.update(dict(msg="Request failed: %s" % to_native(e), status=code)) except socket.error as e: info.update( dict(msg="Connection failure: %s" % to_native(e), status=-1)) except httplib.BadStatusLine as e: info.update( dict( msg= "Connection failure: connection was closed before a valid response was received: %s" % to_native(e.line), status=-1)) except Exception as e: info.update(dict(msg="An unknown error occurred: %s" % to_native(e), status=-1), exception=traceback.format_exc()) finally: tempfile.tempdir = old_tempdir return r, info