예제 #1
0
def test_Request_fallback(urlopen_mock, install_opener_mock, mocker):
    cookies = cookiejar.CookieJar()
    request = Request(
        headers={'foo': 'bar'},
        use_proxy=False,
        force=True,
        timeout=100,
        validate_certs=False,
        url_username='******',
        url_password='******',
        http_agent='ansible-tests',
        force_basic_auth=True,
        follow_redirects='all',
        client_cert='/tmp/client.pem',
        client_key='/tmp/client.key',
        cookies=cookies,
        unix_socket='/foo/bar/baz.sock',
        ca_path='/foo/bar/baz.pem',
    )
    fallback_mock = mocker.spy(request, '_fallback')

    r = request.open('GET', 'https://ansible.com')

    calls = [
        call(None, False),  # use_proxy
        call(None, True),  # force
        call(None, 100),  # timeout
        call(None, False),  # validate_certs
        call(None, 'user'),  # url_username
        call(None, 'passwd'),  # url_password
        call(None, 'ansible-tests'),  # http_agent
        call(None, True),  # force_basic_auth
        call(None, 'all'),  # follow_redirects
        call(None, '/tmp/client.pem'),  # client_cert
        call(None, '/tmp/client.key'),  # client_key
        call(None, cookies),  # cookies
        call(None, '/foo/bar/baz.sock'),  # unix_socket
        call(None, '/foo/bar/baz.pem'),  # ca_path
    ]
    fallback_mock.assert_has_calls(calls)

    assert fallback_mock.call_count == 14  # All but headers use fallback

    args = urlopen_mock.call_args[0]
    assert args[1] is None  # data, this is handled in the Request not urlopen
    assert args[2] == 100  # timeout

    req = args[0]
    assert req.headers == {
        'Authorization': b'Basic dXNlcjpwYXNzd2Q=',
        'Cache-control': 'no-cache',
        'Foo': 'bar',
        'User-agent': 'ansible-tests'
    }
    assert req.data is None
    assert req.get_method() == 'GET'
예제 #2
0
def test_Request_open_custom_method(urlopen_mock, install_opener_mock):
    r = Request().open('DELETE', 'https://ansible.com/')

    args = urlopen_mock.call_args[0]
    req = args[0]

    assert isinstance(req, RequestWithMethod)
예제 #3
0
def test_Request_open_username_force_basic(urlopen_mock, install_opener_mock):
    r = Request().open('GET',
                       'http://ansible.com/',
                       url_username='******',
                       url_password='******',
                       force_basic_auth=True)

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    expected_handlers = (
        urllib_request.HTTPBasicAuthHandler,
        urllib_request.HTTPDigestAuthHandler,
    )

    found_handlers = []
    for handler in handlers:
        if isinstance(handler, expected_handlers):
            found_handlers.append(handler)

    assert len(found_handlers) == 0

    args = urlopen_mock.call_args[0]
    req = args[0]
    assert req.headers.get('Authorization') == b'Basic dXNlcjpwYXNzd2Q='
예제 #4
0
def test_Request_open_ftp(urlopen_mock, install_opener_mock, mocker):
    mocker.patch(
        'ansible_collections.notstdlib.moveitallout.plugins.module_utils.urls.ParseResultDottedDict.as_list',
        side_effect=AssertionError)

    # Using ftp scheme should prevent the AssertionError side effect to fire
    r = Request().open('GET', 'ftp://[email protected]/')
예제 #5
0
def test_Request_open_client_cert(urlopen_mock, install_opener_mock):
    here = os.path.dirname(__file__)

    client_cert = os.path.join(here, 'fixtures/client.pem')
    client_key = os.path.join(here, 'fixtures/client.key')

    r = Request().open('GET',
                       'https://ansible.com/',
                       client_cert=client_cert,
                       client_key=client_key)

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    ssl_handler = None
    for handler in handlers:
        if isinstance(handler, HTTPSClientAuthHandler):
            ssl_handler = handler
            break

    assert ssl_handler is not None

    assert ssl_handler.client_cert == client_cert
    assert ssl_handler.client_key == client_key

    https_connection = ssl_handler._build_https_connection('ansible.com')

    assert https_connection.key_file == client_key
    assert https_connection.cert_file == client_cert
예제 #6
0
def test_Request_open(urlopen_mock, install_opener_mock):
    r = Request().open('GET', 'https://ansible.com/')
    args = urlopen_mock.call_args[0]
    assert args[1] is None  # data, this is handled in the Request not urlopen
    assert args[2] == 10  # timeout

    req = args[0]
    assert req.headers == {}
    assert req.data is None
    assert req.get_method() == 'GET'

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    if not HAS_SSLCONTEXT:
        expected_handlers = (
            SSLValidationHandler,
            RedirectHandlerFactory(),  # factory, get handler
        )
    else:
        expected_handlers = (
            RedirectHandlerFactory(),  # factory, get handler
        )

    found_handlers = []
    for handler in handlers:
        if isinstance(handler, SSLValidationHandler
                      ) or handler.__class__.__name__ == 'RedirectHandler':
            found_handlers.append(handler)

    assert len(found_handlers) == len(expected_handlers)
예제 #7
0
def test_Request_open_invalid_method(urlopen_mock, install_opener_mock):
    r = Request().open('UNKNOWN', 'https://ansible.com/')

    args = urlopen_mock.call_args[0]
    req = args[0]

    assert req.data is None
    assert req.get_method() == 'UNKNOWN'
예제 #8
0
def test_Request_open_user_agent(urlopen_mock, install_opener_mock):
    r = Request().open('GET',
                       'https://ansible.com/',
                       http_agent='ansible-tests')

    args = urlopen_mock.call_args[0]
    req = args[0]

    assert req.headers.get('User-agent') == 'ansible-tests'
예제 #9
0
def test_Request_open_last_mod(urlopen_mock, install_opener_mock):
    now = datetime.datetime.now()
    r = Request().open('GET', 'https://ansible.com/', last_mod_time=now)

    args = urlopen_mock.call_args[0]
    req = args[0]

    assert req.headers.get('If-modified-since') == now.strftime(
        '%a, %d %b %Y %H:%M:%S -0000')
예제 #10
0
def test_methods(method, kwargs, mocker):
    expected = method.upper()
    open_mock = mocker.patch(
        'ansible_collections.notstdlib.moveitallout.plugins.module_utils.urls.Request.open'
    )
    request = Request()
    getattr(request, method)('https://ansible.com')
    open_mock.assert_called_once_with(expected, 'https://ansible.com',
                                      **kwargs)
예제 #11
0
def test_Request_open_netrc(urlopen_mock, install_opener_mock, monkeypatch):
    here = os.path.dirname(__file__)

    monkeypatch.setenv('NETRC', os.path.join(here, 'fixtures/netrc'))
    r = Request().open('GET', 'http://ansible.com/')
    args = urlopen_mock.call_args[0]
    req = args[0]
    assert req.headers.get('Authorization') == b'Basic dXNlcjpwYXNzd2Q='

    r = Request().open('GET', 'http://foo.ansible.com/')
    args = urlopen_mock.call_args[0]
    req = args[0]
    assert 'Authorization' not in req.headers

    monkeypatch.setenv('NETRC', os.path.join(here,
                                             'fixtures/netrc.nonexistant'))
    r = Request().open('GET', 'http://ansible.com/')
    args = urlopen_mock.call_args[0]
    req = args[0]
    assert 'Authorization' not in req.headers
예제 #12
0
def test_Request_open_force(urlopen_mock, install_opener_mock):
    r = Request().open('GET',
                       'https://ansible.com/',
                       force=True,
                       last_mod_time=datetime.datetime.now())

    args = urlopen_mock.call_args[0]
    req = args[0]

    assert req.headers.get('Cache-control') == 'no-cache'
    assert 'If-modified-since' not in req.headers
예제 #13
0
 def __init__(self, headers=None, use_proxy=True, force=False, timeout=120,
              validate_certs=True, url_username=None, url_password=None,
              http_agent=None, force_basic_auth=False, follow_redirects='urllib2',
              client_cert=None, client_key=None, cookies=None):
     self.request = Request(
         headers=headers,
         use_proxy=use_proxy,
         force=force,
         timeout=timeout,
         validate_certs=validate_certs,
         url_username=url_username,
         url_password=url_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
     )
     self.last_url = None
예제 #14
0
def test_Request_open_http(urlopen_mock, install_opener_mock):
    r = Request().open('GET', 'http://ansible.com/')
    args = urlopen_mock.call_args[0]

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    found_handlers = []
    for handler in handlers:
        if isinstance(handler, SSLValidationHandler):
            found_handlers.append(handler)

    assert len(found_handlers) == 0
예제 #15
0
def test_Request_open_no_proxy(urlopen_mock, install_opener_mock, mocker):
    build_opener_mock = mocker.patch(
        'ansible_collections.notstdlib.moveitallout.plugins.module_utils.urls.urllib_request.build_opener'
    )

    r = Request().open('GET', 'http://ansible.com/', use_proxy=False)

    handlers = build_opener_mock.call_args[0]
    found_handlers = []
    for handler in handlers:
        if isinstance(handler, urllib_request.ProxyHandler):
            found_handlers.append(handler)

    assert len(found_handlers) == 1
예제 #16
0
def test_Request_open_unix_socket(urlopen_mock, install_opener_mock):
    r = Request().open('GET',
                       'http://ansible.com/',
                       unix_socket='/foo/bar/baz.sock')
    args = urlopen_mock.call_args[0]

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    found_handlers = []
    for handler in handlers:
        if isinstance(handler, UnixHTTPHandler):
            found_handlers.append(handler)

    assert len(found_handlers) == 1
예제 #17
0
def test_Request_open_cookies(urlopen_mock, install_opener_mock):
    r = Request().open('GET',
                       'https://ansible.com/',
                       cookies=cookiejar.CookieJar())

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    cookies_handler = None
    for handler in handlers:
        if isinstance(handler, urllib_request.HTTPCookieProcessor):
            cookies_handler = handler
            break

    assert cookies_handler is not None
예제 #18
0
def test_Request_open_https_unix_socket(urlopen_mock, install_opener_mock):
    r = Request().open('GET',
                       'https://ansible.com/',
                       unix_socket='/foo/bar/baz.sock')
    args = urlopen_mock.call_args[0]

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    found_handlers = []
    for handler in handlers:
        if isinstance(handler, HTTPSClientAuthHandler):
            found_handlers.append(handler)

    assert len(found_handlers) == 1

    inst = found_handlers[0]._build_https_connection('foo')
    assert isinstance(inst, UnixHTTPSConnection)
예제 #19
0
def test_Request_open_username_in_url(urlopen_mock, install_opener_mock):
    r = Request().open('GET', 'http://[email protected]/')

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    expected_handlers = (
        urllib_request.HTTPBasicAuthHandler,
        urllib_request.HTTPDigestAuthHandler,
    )

    found_handlers = []
    for handler in handlers:
        if isinstance(handler, expected_handlers):
            found_handlers.append(handler)
    assert found_handlers[0].passwd.passwd[None] == {
        (('ansible.com', '/'), ): ('user2', '')
    }
예제 #20
0
def test_Request_open_auth_in_netloc(urlopen_mock, install_opener_mock):
    r = Request().open('GET', 'http://*****:*****@ansible.com/')
    args = urlopen_mock.call_args[0]
    req = args[0]
    assert req.get_full_url() == 'http://ansible.com/'

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    expected_handlers = (
        urllib_request.HTTPBasicAuthHandler,
        urllib_request.HTTPDigestAuthHandler,
    )

    found_handlers = []
    for handler in handlers:
        if isinstance(handler, expected_handlers):
            found_handlers.append(handler)

    assert len(found_handlers) == 2
예제 #21
0
def test_Request_open_no_validate_certs(urlopen_mock, install_opener_mock):
    r = Request().open('GET', 'https://ansible.com/', validate_certs=False)

    opener = install_opener_mock.call_args[0][0]
    handlers = opener.handlers

    ssl_handler = None
    for handler in handlers:
        if isinstance(handler, HTTPSClientAuthHandler):
            ssl_handler = handler
            break

    assert ssl_handler is not None

    inst = ssl_handler._build_https_connection('foo')
    assert isinstance(inst, httplib.HTTPSConnection)

    context = ssl_handler._context
    assert context.protocol == ssl.PROTOCOL_SSLv23
    if ssl.OP_NO_SSLv2:
        assert context.options & ssl.OP_NO_SSLv2
    assert context.options & ssl.OP_NO_SSLv3
    assert context.verify_mode == ssl.CERT_NONE
    assert context.check_hostname is False
예제 #22
0
    def _set_config(self, name, **kwargs):
        headers = {
            "Content-Type": "application/json",
            "Connection": "keep-alive",
        }
        self.request = Request(headers=headers, timeout=60)

        configurators = [self._read_config_vars]
        for configurator in configurators:
            self._config = configurator(name, **kwargs)
            if self._config:
                break
        if self._config is None:
            raise SessionConfigurationException(
                to_native("No Configuration Found."))

        # set up auth if passed
        entrust_api_user = self.get_config("entrust_api_user")
        entrust_api_key = self.get_config("entrust_api_key")
        if entrust_api_user and entrust_api_key:
            self.request.url_username = entrust_api_user
            self.request.url_password = entrust_api_key
        else:
            raise SessionConfigurationException(
                to_native("User and key must be provided."))

        # set up client certificate if passed (support all-in one or cert + key)
        entrust_api_cert = self.get_config("entrust_api_cert")
        entrust_api_cert_key = self.get_config("entrust_api_cert_key")
        if entrust_api_cert:
            self.request.client_cert = entrust_api_cert
            if entrust_api_cert_key:
                self.request.client_key = entrust_api_cert_key
        else:
            raise SessionConfigurationException(
                to_native(
                    "Client certificate for authentication to the API must be provided."
                ))

        # set up the spec
        entrust_api_specification_path = self.get_config(
            "entrust_api_specification_path")

        if not entrust_api_specification_path.startswith(
                "http") and not os.path.isfile(entrust_api_specification_path):
            raise SessionConfigurationException(
                to_native(
                    "OpenAPI specification was not found at location {0}.".
                    format(entrust_api_specification_path)))
        if not valid_file_format.match(entrust_api_specification_path):
            raise SessionConfigurationException(
                to_native(
                    "OpenAPI specification filename must end in .json, .yml or .yaml"
                ))

        self.verify = True

        if entrust_api_specification_path.startswith("http"):
            try:
                http_response = Request().open(
                    method="GET", url=entrust_api_specification_path)
                http_response_contents = http_response.read()
                if entrust_api_specification_path.endswith(".json"):
                    self._spec = json.load(http_response_contents)
                elif entrust_api_specification_path.endswith(
                        ".yml") or entrust_api_specification_path.endswith(
                            ".yaml"):
                    self._spec = yaml.safe_load(http_response_contents)
            except HTTPError as e:
                raise SessionConfigurationException(
                    to_native(
                        "Error downloading specification from address '{0}', received error code '{1}'"
                        .format(entrust_api_specification_path, e.getcode())))
        else:
            with open(entrust_api_specification_path) as f:
                if ".json" in entrust_api_specification_path:
                    self._spec = json.load(f)
                elif ".yml" in entrust_api_specification_path or ".yaml" in entrust_api_specification_path:
                    self._spec = yaml.safe_load(f)
예제 #23
0
    def parse(self, inventory, loader, path, cache=True):
        super(InventoryModule, self).parse(inventory, loader, path)
        if not self.no_config_file_supplied and os.path.isfile(path):
            self._read_config_data(path)
        # Read inventory from tower server.
        # Note the environment variables will be handled automatically by InventoryManager.
        tower_host = self.get_option('host')
        if not re.match('(?:http|https)://', tower_host):
            tower_host = 'https://{tower_host}'.format(tower_host=tower_host)

        request_handler = Request(
            url_username=self.get_option('username'),
            url_password=self.get_option('password'),
            force_basic_auth=True,
            validate_certs=self.get_option('validate_certs'))

        # validate type of inventory_id because we allow two types as special case
        inventory_id = self.get_option('inventory_id')
        if isinstance(inventory_id, int):
            inventory_id = to_text(inventory_id, nonstring='simplerepr')
        else:
            try:
                inventory_id = ensure_type(inventory_id, 'str')
            except ValueError as e:
                raise AnsibleOptionsError(
                    'Invalid type for configuration option inventory_id, '
                    'not integer, and cannot convert to string: {err}'.format(
                        err=to_native(e)))
        inventory_id = inventory_id.replace('/', '')
        inventory_url = '/api/v2/inventories/{inv_id}/script/?hostvars=1&towervars=1&all=1'.format(
            inv_id=inventory_id)
        inventory_url = urljoin(tower_host, inventory_url)

        inventory = self.make_request(request_handler, inventory_url)
        # To start with, create all the groups.
        for group_name in inventory:
            if group_name != '_meta':
                self.inventory.add_group(group_name)

        # Then, create all hosts and add the host vars.
        all_hosts = inventory['_meta']['hostvars']
        for host_name, host_vars in six.iteritems(all_hosts):
            self.inventory.add_host(host_name)
            for var_name, var_value in six.iteritems(host_vars):
                self.inventory.set_variable(host_name, var_name, var_value)

        # Lastly, create to group-host and group-group relationships, and set group vars.
        for group_name, group_content in six.iteritems(inventory):
            if group_name != 'all' and group_name != '_meta':
                # First add hosts to groups
                for host_name in group_content.get('hosts', []):
                    self.inventory.add_host(host_name, group_name)
                # Then add the parent-children group relationships.
                for child_group_name in group_content.get('children', []):
                    self.inventory.add_child(group_name, child_group_name)
            # Set the group vars. Note we should set group var for 'all', but not '_meta'.
            if group_name != '_meta':
                for var_name, var_value in six.iteritems(
                        group_content.get('vars', {})):
                    self.inventory.set_variable(group_name, var_name,
                                                var_value)

        # Fetch extra variables if told to do so
        if self.get_option('include_metadata'):
            config_url = urljoin(tower_host, '/api/v2/config/')
            config_data = self.make_request(request_handler, config_url)
            server_data = {}
            server_data['license_type'] = config_data.get(
                'license_info', {}).get('license_type', 'unknown')
            for key in ('version', 'ansible_version'):
                server_data[key] = config_data.get(key, 'unknown')
            self.inventory.set_variable('all', 'tower_metadata', server_data)

        # Clean up the inventory.
        self.inventory.reconcile_inventory()
예제 #24
0
def test_Request_init_headers_not_dict(urlopen_mock, install_opener_mock):
    with pytest.raises(ValueError):
        Request(headers=['bob'])
예제 #25
0
def test_Request_open_headers_not_dict(urlopen_mock, install_opener_mock):
    with pytest.raises(ValueError):
        Request().open('GET', 'https://ansible.com/', headers=['bob'])
예제 #26
0
def test_Request_open_headers(urlopen_mock, install_opener_mock):
    r = Request().open('GET', 'http://ansible.com/', headers={'Foo': 'bar'})
    args = urlopen_mock.call_args[0]
    req = args[0]
    assert req.headers == {'Foo': 'bar'}
예제 #27
0
class iControlRestSession(object):
    """Represents a session that communicates with a BigIP.

    This acts as a loose wrapper around Ansible's ``Request`` class. We're doing
    this as interim work until we move to the httpapi connector.
    """
    def __init__(self, headers=None, use_proxy=True, force=False, timeout=120,
                 validate_certs=True, url_username=None, url_password=None,
                 http_agent=None, force_basic_auth=False, follow_redirects='urllib2',
                 client_cert=None, client_key=None, cookies=None):
        self.request = Request(
            headers=headers,
            use_proxy=use_proxy,
            force=force,
            timeout=timeout,
            validate_certs=validate_certs,
            url_username=url_username,
            url_password=url_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
        )
        self.last_url = None

    def get_headers(self, result):
        try:
            return dict(result.getheaders())
        except AttributeError:
            return result.headers

    def update_response(self, response, result):
        response.headers = self.get_headers(result)
        response._content = result.read()
        response.status = result.getcode()
        response.url = result.geturl()
        response.msg = "OK (%s bytes)" % response.headers.get('Content-Length', 'unknown')

    def send(self, method, url, **kwargs):
        response = Response()

        # Set the last_url called
        #
        # This is used by the object destructor to erase the token when the
        # ModuleManager exits and destroys the iControlRestSession object
        self.last_url = url

        body = None
        data = kwargs.pop('data', None)
        json = kwargs.pop('json', None)

        if not data and json is not None:
            self.request.headers['Content-Type'] = 'application/json'
            body = _json.dumps(json)
            if not isinstance(body, bytes):
                body = body.encode('utf-8')
        if data:
            body = data
        if body:
            kwargs['data'] = body

        try:
            result = self.request.open(method, url, **kwargs)
        except HTTPError as e:
            # Catch HTTPError delivered from Ansible
            #
            # The structure of this object, in Ansible 2.8 is
            #
            # HttpError {
            #   args
            #   characters_written
            #   close
            #   code
            #   delete
            #   errno
            #   file
            #   filename
            #   filename2
            #   fp
            #   getcode
            #   geturl
            #   hdrs
            #   headers
            #   info
            #   msg
            #   name
            #   reason
            #   strerror
            #   url
            #   with_traceback
            # }
            self.update_response(response, e)
            return response

        self.update_response(response, result)
        return response

    def delete(self, url, **kwargs):
        return self.send('DELETE', url, **kwargs)

    def get(self, url, **kwargs):
        return self.send('GET', url, **kwargs)

    def patch(self, url, data=None, **kwargs):
        return self.send('PATCH', url, data=data, **kwargs)

    def post(self, url, data=None, **kwargs):
        return self.send('POST', url, data=data, **kwargs)

    def put(self, url, data=None, **kwargs):
        return self.send('PUT', url, data=data, **kwargs)

    def __del__(self):
        if self.last_url is None:
            return
        token = self.request.headers.get('X-F5-Auth-Token', None)
        if not token:
            return
        try:
            p = generic_urlparse(urlparse(self.last_url))
            uri = "https://{0}:{1}/mgmt/shared/authz/tokens/{2}".format(
                p['hostname'], p['port'], token
            )
            self.delete(uri)
        except ValueError:
            pass