Пример #1
0
    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']
Пример #2
0
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)))
Пример #3
0
    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']
Пример #4
0
    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
Пример #5
0
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