Example #1
0
 def test_presign_with_spaces_in_param(self):
     request = AWSRequest()
     request.url = 'https://ec2.us-east-1.amazonaws.com/'
     request.data = {'Action': 'MyOperation', 'Description': 'With Spaces'}
     self.auth.add_auth(request)
     # Verify we encode spaces as '%20, and we don't use '+'.
     self.assertIn('Description=With%20Spaces', request.url)
Example #2
0
    def test_destination_region_always_changed(self):
        # If the user provides a destination region, we will still
        # override the DesinationRegion with the region_name from
        # the endpoint object.
        actual_region = 'us-west-1'
        v4query_auth = mock.Mock()

        def add_auth(request):
            request.url += '?PRESIGNED_STUFF'

        v4query_auth.add_auth = add_auth

        request_signer = mock.Mock()
        request_signer._region_name = actual_region
        request_signer.get_auth.return_value = v4query_auth

        endpoint = mock.Mock()
        request = AWSRequest()
        request.method = 'POST'
        request.url = 'https://ec2.us-east-1.amazonaws.com'
        request = request.prepare()
        endpoint.create_request.return_value = request

        # The user provides us-east-1, but we will override this to
        # endpoint.region_name, of 'us-west-1' in this case.
        params = {'SourceRegion': 'us-west-2', 'DestinationRegion': 'us-east-1'}
        handlers.copy_snapshot_encrypted({'body': params},
                                         request_signer,
                                         endpoint)
        # Always use the DestinationRegion from the endpoint, regardless of
        # whatever value the user provides.
        self.assertEqual(params['DestinationRegion'], actual_region)
Example #3
0
    def test_copy_snapshot_encrypted(self):
        v4query_auth = mock.Mock()

        def add_auth(request):
            request.url += '?PRESIGNED_STUFF'

        v4query_auth.add_auth = add_auth

        request_signer = mock.Mock()
        request_signer._region_name = 'us-east-1'
        request_signer.get_auth.return_value = v4query_auth

        params = {'SourceRegion': 'us-west-2'}
        endpoint = mock.Mock()
        request = AWSRequest()
        request.method = 'POST'
        request.url = 'https://ec2.us-east-1.amazonaws.com'
        request = request.prepare()
        endpoint.create_request.return_value = request

        handlers.copy_snapshot_encrypted({'body': params},
                                         request_signer,
                                         endpoint)
        self.assertEqual(params['PresignedUrl'],
                         'https://ec2.us-west-2.amazonaws.com?PRESIGNED_STUFF')
        # We should also populate the DestinationRegion with the
        # region_name of the endpoint object.
        self.assertEqual(params['DestinationRegion'], 'us-east-1')
Example #4
0
    def test_auth_header_preserved_from_s3_redirects(self):
        request = AWSRequest()
        request.url = 'https://bucket.s3.amazonaws.com/'
        request.method = 'GET'
        request.headers['Authorization'] = 'original auth header'
        prepared_request = request.prepare()

        fake_response = Mock()
        fake_response.headers = {
            'location': 'https://bucket.s3-us-west-2.amazonaws.com'}
        fake_response.url = request.url
        fake_response.status_code = 307
        fake_response.is_permanent_redirect = False
        # This line is needed to disable the cookie handling
        # code in requests.
        fake_response.raw._original_response = None

        success_response = Mock()
        success_response.raw._original_response = None
        success_response.is_redirect = False
        success_response.status_code = 200
        session = PreserveAuthSession()
        session.send = Mock(return_value=success_response)

        list(session.resolve_redirects(
            fake_response, prepared_request, stream=False))

        redirected_request = session.send.call_args[0][0]
        # The Authorization header for the newly sent request should
        # still have our original Authorization header.
        self.assertEqual(
            redirected_request.headers['Authorization'],
            'original auth header')
Example #5
0
def request(url, method, credentials, service_name, region=None, headers=None, data=None):
    if not region:
        region = os.environ["AWS_REGION"]

    aws_request = AWSRequest(url=url, method=method, headers=headers, data=data)
    SigV4Auth(credentials, service_name, region).add_auth(aws_request)
    return PreserveAuthSession().send(aws_request.prepare())
Example #6
0
 def test_payload_not_signed_if_disabled_in_context(self):
     request = AWSRequest()
     request.data = u'\u2713'.encode('utf-8')
     request.url = 'https://amazonaws.com'
     request.context['payload_signing_enabled'] = False
     auth = self.create_signer()
     payload = auth.payload(request)
     self.assertEqual(payload, 'UNSIGNED-PAYLOAD')
Example #7
0
 def test_strips_default_port_and_http_auth(self):
     request = AWSRequest()
     request.url = 'http://*****:*****@s3.us-west-2.amazonaws.com:80/'
     request.method = 'GET'
     auth = self.create_signer('s3', 'us-west-2')
     actual = auth.headers_to_sign(request)['host']
     expected = 's3.us-west-2.amazonaws.com'
     self.assertEqual(actual, expected)
Example #8
0
 def test_payload_is_bytes_type(self):
     request = AWSRequest()
     request.data = u'\u2713'.encode('utf-8')
     auth = self.create_signer()
     payload = auth.payload(request)
     self.assertEqual(
         payload,
         '1dabba21cdad44541f6b15796f8d22978fc7ea10c46aeceeeeb66c23b3ac7604')
Example #9
0
 def test_operation_params_before_auth_params(self):
     # The spec is picky about this.
     request = AWSRequest()
     request.url = 'https://ec2.us-east-1.amazonaws.com/?Action=MyOperation'
     self.auth.add_auth(request)
     # Verify auth params come after the existing params.
     self.assertIn(
         '?Action=MyOperation&X-Amz', request.url)
Example #10
0
 def test_presign_with_empty_param_value(self):
     request = AWSRequest()
     request.method = 'POST'
     # actual URL format for creating a multipart upload
     request.url = 'https://s3.amazonaws.com/mybucket/mykey?uploads'
     self.auth.add_auth(request)
     # verify that uploads param is still in URL
     self.assertIn('uploads', request.url)
Example #11
0
 def test_operation_params_before_auth_params_in_body(self):
     request = AWSRequest()
     request.url = 'https://ec2.us-east-1.amazonaws.com/'
     request.data = {'Action': 'MyOperation'}
     self.auth.add_auth(request)
     # Same situation, the params from request.data come before the auth
     # params in the query string.
     self.assertIn(
         '?Action=MyOperation&X-Amz', request.url)
Example #12
0
 def test_switch_host_with_param(self):
     request = AWSRequest()
     url = 'https://machinelearning.us-east-1.amazonaws.com'
     new_endpoint = 'https://my-custom-endpoint.amazonaws.com'
     data = '{"PredictEndpoint":"%s"}' % new_endpoint
     request.data = data.encode('utf-8')
     request.url = url
     handlers.switch_host_with_param(request, 'PredictEndpoint')
     self.assertEqual(request.url, new_endpoint)
Example #13
0
 def test_signature_with_date_headers(self):
     request = AWSRequest()
     request.headers = {'Date': 'Thu, 17 Nov 2005 18:49:58 GMT'}
     request.url = 'https://route53.amazonaws.com'
     self.auth.add_auth(request)
     self.assertEqual(
         request.headers['X-Amzn-Authorization'],
         ('AWS3-HTTPS AWSAccessKeyId=access_key,Algorithm=HmacSHA256,'
          'Signature=M245fo86nVKI8rLpH4HgWs841sBTUKuwciiTpjMDgPs='))
Example #14
0
 def test_payload_is_binary_file(self):
     request = AWSRequest()
     request.data = six.BytesIO(u'\u2713'.encode('utf-8'))
     request.url = 'https://amazonaws.com'
     auth = self.create_signer()
     payload = auth.payload(request)
     self.assertEqual(
         payload,
         '1dabba21cdad44541f6b15796f8d22978fc7ea10c46aeceeeeb66c23b3ac7604')
Example #15
0
 def test_signature_is_not_normalized(self):
     request = AWSRequest()
     request.url = 'https://s3.amazonaws.com/bucket/foo/./bar/../bar'
     request.method = 'GET'
     credentials = botocore.credentials.Credentials('access_key',
                                                    'secret_key')
     auth = botocore.auth.S3SigV4Auth(credentials, 's3', 'us-east-1')
     auth.add_auth(request)
     self.assertTrue(
         request.headers['Authorization'].startswith('AWS4-HMAC-SHA256'))
Example #16
0
 def test_presign_with_security_token(self):
     self.credentials.token = 'security-token'
     auth = botocore.auth.S3SigV4QueryAuth(
         self.credentials, self.service_name, self.region_name, expires=60)
     request = AWSRequest()
     request.url = 'https://ec2.us-east-1.amazonaws.com/'
     self.auth.add_auth(request)
     query_string = self.get_parsed_query_string(request)
     self.assertEqual(
         query_string['X-Amz-Security-Token'], 'security-token')
Example #17
0
 def test_content_sha256_set_if_payload_signing_disabled(self):
     request = AWSRequest()
     request.data = six.BytesIO(u'\u2713'.encode('utf-8'))
     request.url = 'https://amazonaws.com'
     request.context['payload_signing_enabled'] = False
     request.method = 'PUT'
     auth = self.create_signer()
     auth.add_auth(request)
     sha_header = request.headers['X-Amz-Content-SHA256']
     self.assertEqual(sha_header, 'UNSIGNED-PAYLOAD')
Example #18
0
 def _test_blacklist_header(self, header, value):
     request = AWSRequest()
     request.url = 'https://s3.amazonaws.com/bucket/foo'
     request.method = 'PUT'
     request.headers[header] = value
     credentials = botocore.credentials.Credentials('access_key',
                                                    'secret_key')
     auth = botocore.auth.S3SigV4Auth(credentials, 's3', 'us-east-1')
     auth.add_auth(request)
     self.assertNotIn(header, request.headers['Authorization'])
Example #19
0
 def test_discover_endpoint_no_protocol(self):
     request = AWSRequest()
     request.context = {
         'discovery': {'identifiers': {}}
     }
     self.manager.describe_endpoint.return_value = 'new.foo'
     self.handler.discover_endpoint(request, 'TestOperation')
     self.assertEqual(request.url, 'https://new.foo')
     self.manager.describe_endpoint.assert_called_with(
         Operation='TestOperation', Identifiers={}
     )
Example #20
0
 def test_presign_content_type_form_encoded_not_signed(self):
     request = AWSRequest()
     request.method = 'GET'
     request.url = 'https://myservice.us-east-1.amazonaws.com/'
     request.headers['Content-Type'] = (
         'application/x-www-form-urlencoded; charset=utf-8'
     )
     self.auth.add_auth(request)
     query_string = self.get_parsed_query_string(request)
     signed_headers = query_string.get('X-Amz-SignedHeaders')
     self.assertNotIn('content-type', signed_headers)
Example #21
0
 def test_discover_endpoint_fails(self):
     request = AWSRequest()
     request.context = {
         'discovery': {'identifiers': {}}
     }
     request.url = 'old.com'
     self.manager.describe_endpoint.return_value = None
     self.handler.discover_endpoint(request, 'TestOperation')
     self.assertEqual(request.url, 'old.com')
     self.manager.describe_endpoint.assert_called_with(
         Operation='TestOperation', Identifiers={}
     )
Example #22
0
 def test_fields(self):
     request = AWSRequest()
     request.url = '/'
     request.method = 'POST'
     request.data = {'Foo': u'\u2713'}
     self.signer.add_auth(request)
     self.assertEqual(request.data['AWSAccessKeyId'], 'foo')
     self.assertEqual(request.data['Foo'], u'\u2713')
     self.assertEqual(request.data['Timestamp'], '2014-06-20T08:40:23Z')
     self.assertEqual(request.data['Signature'],
                      u'Tiecw+t51tok4dTT8B4bg47zxHEM/KcD55f2/x6K22o=')
     self.assertEqual(request.data['SignatureMethod'], 'HmacSHA256')
     self.assertEqual(request.data['SignatureVersion'], '2')
Example #23
0
 def test_resign(self):
     # Make sure that resigning after e.g. retries works
     request = AWSRequest()
     request.url = '/'
     request.method = 'POST'
     params = {
         'Foo': u'\u2713',
         'Signature': u'VCtWuwaOL0yMffAT8W4y0AFW3W4KUykBqah9S40rB+Q='
     }
     result = self.signer.calc_signature(request, params)
     self.assertEqual(
         result, ('Foo=%E2%9C%93',
                  u'VCtWuwaOL0yMffAT8W4y0AFW3W4KUykBqah9S40rB+Q='))
Example #24
0
 def test_get(self):
     request = AWSRequest()
     request.url = '/'
     request.method = 'GET'
     request.params = {'Foo': u'\u2713'}
     self.signer.add_auth(request)
     self.assertEqual(request.params['AWSAccessKeyId'], 'foo')
     self.assertEqual(request.params['Foo'], u'\u2713')
     self.assertEqual(request.params['Timestamp'], '2014-06-20T08:40:23Z')
     self.assertEqual(request.params['Signature'],
                      u'Un97klqZCONP65bA1+Iv4H3AcB2I40I4DBvw5ZERFPw=')
     self.assertEqual(request.params['SignatureMethod'], 'HmacSHA256')
     self.assertEqual(request.params['SignatureVersion'], '2')
Example #25
0
 def test_presign_no_params(self):
     request = AWSRequest()
     request.url = 'https://ec2.us-east-1.amazonaws.com/'
     self.auth.add_auth(request)
     query_string = self.get_parsed_query_string(request)
     self.assertEqual(
         query_string,
         {'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
          'X-Amz-Credential': 'access_key/20140101/myregion/myservice/aws4_request',
          'X-Amz-Date': '20140101T000000Z',
          'X-Amz-Expires': '60',
          'X-Amz-Signature': 'c70e0bcdb4cd3ee324f71c78195445b8788315af0800bbbdbbb6d05a616fb84c',
          'X-Amz-SignedHeaders': 'host'})
Example #26
0
def create_request_from_raw_request(raw_request):
    raw_request = raw_request.replace('http/1.1', 'HTTP/1.1')
    request = AWSRequest()
    raw = RawHTTPRequest(raw_request)
    if raw.error_code is not None:
        raise Exception(raw.error_message)
    request.method = raw.command
    datetime_now = datetime.datetime(2011, 9, 9, 23, 36)
    request.context['timestamp'] = datetime_now.strftime('%Y%m%dT%H%M%SZ')
    for key, val in raw.headers.items():
        request.headers[key] = val
    request.data = raw.rfile.read()
    host = raw.headers.get('host', '')
    # For whatever reason, the BaseHTTPRequestHandler encodes
    # the first line of the response as 'iso-8859-1',
    # so we need decode this into utf-8.
    if isinstance(raw.path, six.text_type):
        raw.path = raw.path.encode('iso-8859-1').decode('utf-8')
    url = 'https://%s%s' % (host, raw.path)
    if '?' in url:
        split_url = urlsplit(url)
        params = dict(parse_qsl(split_url.query))
        request.url = split_url.path
        request.params = params
    else:
        request.url = url
    return request
Example #27
0
 def test_sign_with_token(self):
     credentials = botocore.credentials.Credentials(
         access_key='foo', secret_key='bar', token='baz')
     auth = botocore.auth.HmacV1Auth(credentials)
     request = AWSRequest()
     request.headers['Date'] = 'Thu, 17 Nov 2005 18:49:58 GMT'
     request.headers['Content-Type'] = 'text/html'
     request.method = 'PUT'
     request.url = 'https://s3.amazonaws.com/bucket/key'
     auth.add_auth(request)
     self.assertIn('Authorization', request.headers)
     # We're not actually checking the signature here, we're
     # just making sure the auth header has the right format.
     self.assertTrue(request.headers['Authorization'].startswith('AWS '))
Example #28
0
    def test_query_string_params_in_urls(self):
        request = AWSRequest()
        request.url = (
            'https://s3.amazonaws.com/bucket?'
            'marker=%C3%A4%C3%B6%C3%BC-01.txt&prefix'
        )
        request.data = {'Action': 'MyOperation'}
        request.method = 'GET'

        # Check that the canonical query string is correct formatting
        # by ensuring that query string paramters that are added to the
        # canonical query string are correctly formatted.
        cqs = self.auth.canonical_query_string(request)
        self.assertEqual('marker=%C3%A4%C3%B6%C3%BC-01.txt&prefix=', cqs)
Example #29
0
 def test_resign_with_token(self):
     credentials = botocore.credentials.Credentials(
         access_key='foo', secret_key='bar', token='baz')
     auth = botocore.auth.SigV3Auth(credentials)
     request = AWSRequest()
     request.headers['Date'] = 'Thu, 17 Nov 2005 18:49:58 GMT'
     request.method = 'PUT'
     request.url = 'https://route53.amazonaws.com/'
     auth.add_auth(request)
     original_auth = request.headers['X-Amzn-Authorization']
     # Resigning the request shouldn't change the authorization
     # header.
     auth.add_auth(request)
     self.assertEqual(request.headers.get_all('X-Amzn-Authorization'),
                      [original_auth])
Example #30
0
 def test_canonical_query_string(self):
     request = AWSRequest()
     request.url = (
         'https://search-testdomain1-j67dwxlet67gf7ghwfmik2c67i.us-west-2.'
         'cloudsearch.amazonaws.com/'
         '2013-01-01/search?format=sdk&pretty=true&'
         'q.options=%7B%22defaultOperator%22%3A%20%22and%22%2C%20%22'
         'fields%22%3A%5B%22directors%5E10%22%5D%7D&q=George%20Lucas'
     )
     request.method = 'GET'
     auth = self.create_signer('cloudsearchdomain', 'us-west-2')
     actual = auth.canonical_query_string(request)
     # Here 'q' should come before 'q.options'.
     expected = ("format=sdk&pretty=true&q=George%20Lucas&q.options=%7B%22"
                 "defaultOperator%22%3A%20%22and%22%2C%20%22fields%22%3A%5B"
                 "%22directors%5E10%22%5D%7D")
     self.assertEqual(actual, expected)
Example #31
0
    def test_empty_fields_and_policy(self):
        self.request = AWSRequest()
        self.request.url = 'https://s3.amazonaws.com/%s' % self.bucket
        self.request.method = 'POST'
        self.auth.add_auth(self.request)

        result_fields = self.request.context['s3-presign-post-fields']
        self.assertEqual(result_fields['x-amz-algorithm'], 'AWS4-HMAC-SHA256')
        self.assertEqual(
            result_fields['x-amz-credential'],
            'access_key/20140101/myregion/myservice/aws4_request')
        self.assertEqual(
            result_fields['x-amz-date'],
            '20140101T000000Z')

        result_policy = json.loads(base64.b64decode(
            result_fields['policy']).decode('utf-8'))
        self.assertEqual(
            result_policy['conditions'],
            [{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
             {"x-amz-credential":
              "access_key/20140101/myregion/myservice/aws4_request"},
             {"x-amz-date": "20140101T000000Z"}])
        self.assertIn('x-amz-signature', result_fields)
    def test_resign_with_token(self):
        credentials = botocore.credentials.Credentials(
            access_key='foo', secret_key='bar', token='baz')
        auth = botocore.auth.HmacV1Auth(credentials)
        request = AWSRequest()
        request.headers['Date'] = 'Thu, 17 Nov 2005 18:49:58 GMT'
        request.headers['Content-Type'] = 'text/html'
        request.method = 'PUT'
        request.url = 'https://s3.amazonaws.com/bucket/key'

        auth.add_auth(request)
        original_auth = request.headers['Authorization']
        # Resigning the request shouldn't change the authorization
        # header.  We are also ensuring that the date stays the same
        # because we're mocking out the formatdate() call.  There's
        # another unit test that verifies we use the latest time
        # when we sign the request.
        auth.add_auth(request)
        self.assertEqual(request.headers.get_all('Authorization'),
                         [original_auth])
Example #33
0
class TestAWSRequest(unittest.TestCase):

    def setUp(self):
        self.tempdir = tempfile.mkdtemp()
        self.request = AWSRequest(url='http://example.com')
        self.prepared_request = self.request.prepare()
        self.filename = os.path.join(self.tempdir, 'foo')

    def tearDown(self):
        shutil.rmtree(self.tempdir)

    def test_should_reset_stream(self):
        with open(self.filename, 'wb') as f:
            f.write(b'foobarbaz')
        with open(self.filename, 'rb') as body:
            self.prepared_request.body = body

            # Now pretend we try to send the request.
            # This means that we read the body:
            body.read()
            # And create a response object that indicates
            # a redirect.
            fake_response = Mock()
            fake_response.status_code = 307

            # Then requests calls our reset_stream hook.
            self.prepared_request.reset_stream_on_redirect(fake_response)

            # The stream should now be reset.
            self.assertEqual(body.tell(), 0)

    def test_cannot_reset_stream_raises_error(self):
        with open(self.filename, 'wb') as f:
            f.write(b'foobarbaz')
        with open(self.filename, 'rb') as body:
            self.prepared_request.body = Unseekable(body)

            # Now pretend we try to send the request.
            # This means that we read the body:
            body.read()
            # And create a response object that indicates
            # a redirect
            fake_response = Mock()
            fake_response.status_code = 307

            # Then requests calls our reset_stream hook.
            with self.assertRaises(UnseekableStreamError):
                self.prepared_request.reset_stream_on_redirect(fake_response)

    def test_duck_type_for_file_check(self):
        # As part of determining whether or not we can rewind a stream
        # we first need to determine if the thing is a file like object.
        # We should not be using an isinstance check.  Instead, we should
        # be using duck type checks.
        class LooksLikeFile(object):
            def __init__(self):
                self.seek_called = False

            def read(self, amount=None):
                pass

            def seek(self, where):
                self.seek_called = True

        looks_like_file = LooksLikeFile()
        self.prepared_request.body = looks_like_file

        fake_response = Mock()
        fake_response.status_code = 307

        # Then requests calls our reset_stream hook.
        self.prepared_request.reset_stream_on_redirect(fake_response)

        # The stream should now be reset.
        self.assertTrue(looks_like_file.seek_called)
Example #34
0
 def test_can_prepare_empty_body(self):
     request = AWSRequest(url='http://example.com/', data=b'')
     prepared_request = request.prepare()
     self.assertEqual(prepared_request.body, None)
     content_length = prepared_request.headers.get('content-length')
     self.assertEqual(content_length, '0')
Example #35
0
 def test_can_prepare_dict_body_unicode_keys(self):
     body = {u'\u30c6\u30b9\u30c8': 'string'}
     expected_body = '%E3%83%86%E3%82%B9%E3%83%88=string'
     request = AWSRequest(url='http://example.com/', data=body)
     prepared_request = request.prepare()
     self.assertEqual(prepared_request.body, expected_body)
Example #36
0
 def test_request_body_is_prepared(self):
     request = AWSRequest(url='http://example.com/', data='body')
     self.assertEqual(request.body, b'body')
Example #37
0
    def send_to_es(self,
                   path="/",
                   method=None,
                   payload=None,
                   extra_headers=None):
        """Low-level POST data to Amazon Elasticsearch Service generating a Sigv4 signed request

        Args:
            path (str): path to send to ES
            method (str, optional): HTTP method default:GET
            payload (dict, optional): additional payload used during POST or PUT

        Returns:
            dict: json answer converted in dict

        Raises:
            #: Error during ES communication
            ESException: Description
        """
        # resolve default kwargs
        payload = payload or {}
        extra_headers = extra_headers or {}
        if not path.startswith("/"):
            path = "/" + path
        method = method if method else self.method
        es_region = self.cfg["es_endpoint"].split(".")[1]

        # send to ES with exponential backoff
        retries = 0
        while retries < int(self.cfg["es_max_retry"]):
            if retries > 0:
                seconds = (2**retries) * .1
                # print('Waiting for %.1f seconds', seconds)
                time.sleep(seconds)

            extra_headers.update({"Host": self.cfg["es_endpoint"]})
            req = AWSRequest(
                method=method,
                url=('https://%s%s?pretty&format=json' %
                     (self.cfg['es_endpoint'], urllib.parse.quote(path))),
                data=payload,
                headers=extra_headers)
            credential_resolver = create_credential_resolver(get_session())
            credentials = credential_resolver.load_credentials()
            SigV4Auth(credentials, 'es', es_region).add_auth(req)

            try:
                preq = req.prepare()
                session = Session()
                res = session.send(preq)
                if res.status_code >= 200 and res.status_code <= 299:
                    LOGGER.debug("%s %s", res.status_code, res.content)
                    return json.loads(res.content)
                else:
                    LOGGER.debug("%s %s", res.status_code, res.content)
                    raise ESException(res.status_code, res.content)

            except ESException as err:
                if (err.status_code >= 500) and (err.status_code <= 599):
                    retries += 1  # Candidate for retry
                else:
                    raise  # Stop retrying, re-raise exception
Example #38
0
class TestAWSRequest(unittest.TestCase):
    def setUp(self):
        self.tempdir = tempfile.mkdtemp()
        self.filename = os.path.join(self.tempdir, 'foo')
        self.request = AWSRequest(method='GET', url='http://example.com')
        self.prepared_request = self.request.prepare()
        self.prepared_request.prepare_headers(self.request.headers)

    def tearDown(self):
        shutil.rmtree(self.tempdir)

    def test_prepared_request_repr(self):
        expected_repr = (
            '<AWSPreparedRequest stream_output=False, method=GET, '
            'url=http://example.com, headers={}>'
        )
        request_repr = repr(self.prepared_request)
        self.assertEqual(request_repr, expected_repr)

    def test_can_prepare_url_params(self):
        request = AWSRequest(url='http://example.com/', params={'foo': 'bar'})
        prepared_request = request.prepare()
        self.assertEqual(prepared_request.url, 'http://example.com/?foo=bar')

    def test_can_prepare_dict_body(self):
        body = {'dead': 'beef'}
        request = AWSRequest(url='http://example.com/', data=body)
        prepared_request = request.prepare()
        self.assertEqual(prepared_request.body, 'dead=beef')

    def test_can_prepare_empty_body(self):
        request = AWSRequest(url='http://example.com/', data=b'')
        prepared_request = request.prepare()
        self.assertEqual(prepared_request.body, None)
        content_length = prepared_request.headers.get('content-length')
        self.assertEqual(content_length, '0')

    def test_request_body_is_prepared(self):
        request = AWSRequest(url='http://example.com/', data='body')
        self.assertEqual(request.body, b'body')

    def test_prepare_body_content_adds_content_length(self):
        content = b'foobarbaz'
        with open(self.filename, 'wb') as f:
            f.write(content)
        with open(self.filename, 'rb') as f:
            data = Seekable(f)
            self.prepared_request.prepare_body(data)
        self.assertEqual(
            self.prepared_request.headers['Content-Length'],
            str(len(content)))

    def test_can_reset_stream_handles_binary(self):
        contents = b'notastream'
        self.prepared_request.body = contents
        self.prepared_request.reset_stream()
        # assert the request body doesn't change after reset_stream is called
        self.assertEqual(self.prepared_request.body, contents)

    def test_can_reset_stream(self):
        contents = b'foobarbaz'
        with open(self.filename, 'wb') as f:
            f.write(contents)
        with open(self.filename, 'rb') as body:
            self.prepared_request.body = body
            # pretend the request body was partially sent
            body.read()
            self.assertNotEqual(body.tell(), 0)
            # have the prepared request reset its stream
            self.prepared_request.reset_stream()
            # the stream should be reset
            self.assertEqual(body.tell(), 0)

    def test_cannot_reset_stream_raises_error(self):
        contents = b'foobarbaz'
        with open(self.filename, 'wb') as f:
            f.write(contents)
        with open(self.filename, 'rb') as body:
            self.prepared_request.body = Unseekable(body)
            # pretend the request body was partially sent
            body.read()
            self.assertNotEqual(body.tell(), 0)
            # reset stream should fail
            with self.assertRaises(UnseekableStreamError):
                self.prepared_request.reset_stream()

    def test_duck_type_for_file_check(self):
        # As part of determining whether or not we can rewind a stream
        # we first need to determine if the thing is a file like object.
        # We should not be using an isinstance check.  Instead, we should
        # be using duck type checks.
        class LooksLikeFile(object):
            def __init__(self):
                self.seek_called = False
            def read(self, amount=None):
                pass
            def seek(self, where):
                self.seek_called = True
        looks_like_file = LooksLikeFile()
        self.prepared_request.body = looks_like_file
        self.prepared_request.reset_stream()
        # The stream should now be reset.
        self.assertTrue(looks_like_file.seek_called)
Example #39
0
 def test_can_prepare_dict_body(self):
     body = {'dead': 'beef'}
     request = AWSRequest(url='http://example.com/', data=body)
     prepared_request = request.prepare()
     self.assertEqual(prepared_request.body, 'dead=beef')
Example #40
0
 def test_inject_no_context(self):
     request = AWSRequest(url='https://original.foo')
     self.handler.discover_endpoint(request, 'TestOperation')
     self.assertEqual(request.url, 'https://original.foo')
     self.manager.describe_endpoint.assert_not_called()
Example #41
0
 def test_signed_host_is_ipv6_with_explicit_port(self):
     endpoint = 'http://[::1]:6789'
     expected_host = '[::1]:6789'
     request = AWSRequest(method='GET', url=endpoint)
     headers_to_sign = self.sigv4.headers_to_sign(request)
     self.assertEqual(expected_host, headers_to_sign.get('host'))
Example #42
0
def handle_method(fragment):
    if fragment["Type"] != "AWS::ApiGateway::Method":
        response_string = "Macro only supports \"AWS::ApiGateway::Method\", user supplied {}"
        raise InvalidTypeException(response_string.format(fragment["Type"]))

    service_name = fragment["Properties"]["Integration"].pop("Service").lower()
    action = fragment["Properties"]["Integration"].pop("Action")
    response_maps = fragment["Properties"]["Integration"].pop("ResponseMaps")
    try:
        fragment.pop("Fn::Transform")
    except:
        pass

    loader = Loader()
    service_description = loader.load_service_model(service_name=service_name, type_name='service-2')
    service_model = ServiceModel(service_description)
    protocol = service_model.protocol
    op_model = service_model.operation_model(action["Name"])

    request_parameters = action.get("Parameters", {})
    params = dict(ChainMap(*request_parameters))
    print("params: {}".format(params))
    serializer = create_serializer(protocol)
    response_parser = create_parser(protocol)

    print(service_model.protocol)
    request = serializer.serialize_to_request(params, op_model)
    request_object = AWSRequest(
        method=request['method'],
        url=get_endpoint(service_model.service_name),
        data=request['body'],
        headers=request['headers'])

    X = request_object.prepare()

    print("Raw request: {}".format(request))
    print("Prepared request: {}".format(X))

    integration = fragment["Properties"]["Integration"]
    new_integration = integration_template()

    # Copy the existing values to the new template
    for entry in integration.keys():
        new_integration[entry] = integration[entry]

    # Add headers to cfn template
    if X.headers is not None and callable(getattr(X.headers, "keys", None)):
        for header in X.headers.keys():
            if header.lower() != 'Content-Length'.lower():
                new_integration["RequestParameters"].update({"integration.request.header.{}".format(header): "'{}'".format(X.headers[header])})

    # Add Query Strings to cfn template
    if 'query_string' in request and callable(getattr(request['query_string'], "keys", None)):
        for query in request['query_string'].keys():
            new_integration["RequestParameters"].update({"integration.request.querystring.{}".format(query): "'{}'".format(request['query_string'][query])})

    # Set the body
    if isinstance(X.body, str):
        new_integration["RequestTemplates"]["application/json"] = X.body
    else:
        new_integration["RequestTemplates"]["application/json"] = str(X.body, "utf-8") if X.body else ''
    new_integration["Uri"] = ":".join([
        "arn",
        "aws",
        "apigateway",
        REGION,
        service_model.endpoint_prefix,
        "path/" + request["url_path"]
    ])
    new_integration["IntegrationHttpMethod"] = X.method

    fragment["Properties"]["Integration"] = new_integration
    print(fragment)
    return fragment
Example #43
0
def signed_request(method, url, data=None, params=None, headers=None, service=None):
    creds = boto3.Session().get_credentials().get_frozen_credentials()
    request = AWSRequest(method=method, url=url, data=data, params=params, headers=headers)
    SigV4Auth(creds, service, boto3.Session().region_name).add_auth(request)
    return requests.request(method=method, url=url, headers=dict(request.headers), data=data)
Example #44
0
 def __call__(self, request: AWSRequest):
     # Method hard coded to 'GET' as this prevents making accidental 'POSTS'
     aws_request = AWSRequest(method='GET', url=self.url, data=request.body)
     S3SigV4Auth(self.credentials, 's3', self.region).add_auth(aws_request)
     request.headers.update(dict(aws_request.headers.items()))
     return request
Example #45
0
 def __call__(self, request):
     aws_request = AWSRequest(method=request.method.upper(),
                              url=request.url, data=request.body)
     SigV4Auth(self.credentials, "es", self.region).add_auth(aws_request)
     request.headers.update(dict(aws_request.headers.items()))
     return request
Example #46
0
 def setUp(self):
     self.original_url = 'https://s3.amazonaws.com/foo/key.txt'
     self.request = AWSRequest(method='PUT',
                               headers={},
                               url=self.original_url)
Example #47
0
 def setUp(self):
     self.tempdir = tempfile.mkdtemp()
     self.request = AWSRequest(url='http://example.com')
     self.prepared_request = self.request.prepare()
     self.filename = os.path.join(self.tempdir, 'foo')
 def test_signed_host_is_lowercase(self):
     endpoint = 'https://S5.Us-WeAsT-2.AmAZonAwS.com'
     expected_host = 's5.us-weast-2.amazonaws.com'
     request = AWSRequest(method='GET', url=endpoint)
     headers_to_sign = self.sigv4.headers_to_sign(request)
     self.assertEqual(expected_host, headers_to_sign.get('host'))
Example #49
0
class TestURLLib3Session(unittest.TestCase):
    def setUp(self):
        self.request = AWSRequest(
            method='GET',
            url='http://example.com/',
            headers={},
            data=b'',
        )

        self.response = Mock()
        self.response.headers = {}
        self.response.stream.return_value = b''

        self.pool_manager = Mock()
        self.connection = Mock()
        self.connection.urlopen.return_value = self.response
        self.pool_manager.connection_from_url.return_value = self.connection

        self.pool_patch = patch('botocore.httpsession.PoolManager')
        self.proxy_patch = patch('botocore.httpsession.proxy_from_url')
        self.pool_manager_cls = self.pool_patch.start()
        self.proxy_manager_fun = self.proxy_patch.start()
        self.pool_manager_cls.return_value = self.pool_manager
        self.proxy_manager_fun.return_value = self.pool_manager

    def tearDown(self):
        self.pool_patch.stop()

    def assert_request_sent(self, headers=None, body=None, url='/'):
        if headers is None:
            headers = {}

        self.connection.urlopen.assert_called_once_with(
            method=self.request.method,
            url=url,
            body=body,
            headers=headers,
            retries=False,
            assert_same_host=False,
            preload_content=False,
            decode_content=False,
        )

    def test_forwards_max_pool_size(self):
        URLLib3Session(max_pool_connections=22)
        self.pool_manager_cls.assert_called_with(
            maxsize=22,
            timeout=ANY,
            strict=True,
            ssl_context=ANY,
        )

    def test_basic_request(self):
        session = URLLib3Session()
        session.send(self.request.prepare())
        self.assert_request_sent()
        self.response.stream.assert_called_once_with()

    def test_basic_streaming_request(self):
        session = URLLib3Session()
        self.request.stream_output = True
        session.send(self.request.prepare())
        self.assert_request_sent()
        self.response.stream.assert_not_called()

    def test_basic_https_request(self):
        session = URLLib3Session()
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_request_sent()

    def test_basic_https_proxy_request(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.proxy_manager_fun.assert_any_call(
            proxies['https'],
            proxy_headers={},
            maxsize=ANY,
            timeout=ANY,
            strict=True,
            ssl_context=ANY,
        )
        self.assert_request_sent()

    def test_basic_proxy_request_caches_manager(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        # assert we created the proxy manager
        self.proxy_manager_fun.assert_any_call(
            proxies['https'],
            proxy_headers={},
            maxsize=ANY,
            timeout=ANY,
            strict=True,
            ssl_context=ANY,
        )
        session.send(self.request.prepare())
        # assert that we did not create another proxy manager
        self.assertEqual(self.proxy_manager_fun.call_count, 1)

    def test_basic_http_proxy_request(self):
        proxies = {'http': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        session.send(self.request.prepare())
        self.proxy_manager_fun.assert_any_call(
            proxies['http'],
            proxy_headers={},
            maxsize=ANY,
            timeout=ANY,
            strict=True,
            ssl_context=ANY,
        )
        self.assert_request_sent(url=self.request.url)

    def test_ssl_context_is_explicit(self):
        session = URLLib3Session()
        session.send(self.request.prepare())
        _, manager_kwargs = self.pool_manager_cls.call_args
        self.assertIsNotNone(manager_kwargs.get('ssl_context'))

    def test_proxy_request_ssl_context_is_explicit(self):
        proxies = {'http': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        session.send(self.request.prepare())
        _, proxy_kwargs = self.proxy_manager_fun.call_args
        self.assertIsNotNone(proxy_kwargs.get('ssl_context'))

    def make_request_with_error(self, error):
        self.connection.urlopen.side_effect = error
        session = URLLib3Session()
        session.send(self.request.prepare())

    @raises(EndpointConnectionError)
    def test_catches_new_connection_error(self):
        error = NewConnectionError(None, None)
        self.make_request_with_error(error)

    @raises(ConnectionClosedError)
    def test_catches_bad_status_line(self):
        error = ProtocolError(None)
        self.make_request_with_error(error)

    def test_aws_connection_classes_are_used(self):
        session = URLLib3Session()
        # ensure the pool manager is using the correct classes
        http_class = self.pool_manager.pool_classes_by_scheme.get('http')
        self.assertIs(http_class, AWSHTTPConnectionPool)
        https_class = self.pool_manager.pool_classes_by_scheme.get('https')
        self.assertIs(https_class, AWSHTTPSConnectionPool)
Example #50
0
def make_request(endpoint, data, method='GET'):
    """
    This function handles a HTTP request to a given elasticsearch domain endpoint and method.
    :param endpoint: The elasticsearch domain endpoint
    :param data:
    :param method: the type of HTTP method to use. eg: 'GET POST DELETE etc'
    :return: The response of the request
    """

    host = endpoint
    endpoint = '{0}/_bulk'.format(host)
    region = endpoint.split('.')[1]
    service = endpoint.split('.')[2]
    credentials = boto3.session.Session().get_credentials()
    request = AWSRequest(method=method,
                         url='https://{0}'.format(endpoint),
                         data=data)
    SigV4Auth(credentials, service, region).add_auth(request)
    headers = dict(request.headers.items())
    opener = urllib2.build_opener(urllib2.HTTPHandler)
    request = urllib2.Request('https://{0}'.format(endpoint), request.data)

    request.add_header('Host', host)
    request.add_header('Content-Type', 'application/json')
    request.add_header('X-Amz-Date', headers['X-Amz-Date'])
    request.add_header('X-Amz-Security-Token', headers['X-Amz-Security-Token'])
    request.add_header('Authorization', headers['Authorization'])
    request.get_method = lambda: method

    print(request.data)

    return opener.open(request).read()
Example #51
0
 def test_can_prepare_url_params(self):
     request = AWSRequest(url='http://example.com/', params={'foo': 'bar'})
     prepared_request = request.prepare()
     self.assertEqual(prepared_request.url, 'http://example.com/?foo=bar')
Example #52
0
class TestURLLib3Session(unittest.TestCase):
    def setUp(self):
        self.request = AWSRequest(
            method='GET',
            url='http://example.com/',
            headers={},
            data=b'',
        )

        self.response = Mock()
        self.response.headers = {}
        self.response.stream.return_value = b''

        self.pool_manager = Mock()
        self.connection = Mock()
        self.connection.urlopen.return_value = self.response
        self.pool_manager.connection_from_url.return_value = self.connection

        self.pool_patch = patch('botocore.httpsession.PoolManager')
        self.proxy_patch = patch('botocore.httpsession.proxy_from_url')
        self.pool_manager_cls = self.pool_patch.start()
        self.proxy_manager_fun = self.proxy_patch.start()
        self.pool_manager_cls.return_value = self.pool_manager
        self.proxy_manager_fun.return_value = self.pool_manager

    def tearDown(self):
        self.pool_patch.stop()
        self.proxy_patch.stop()

    def assert_request_sent(self,
                            headers=None,
                            body=None,
                            url='/',
                            chunked=False):
        if headers is None:
            headers = {}

        self.connection.urlopen.assert_called_once_with(
            method=self.request.method,
            url=url,
            body=body,
            headers=headers,
            retries=False,
            assert_same_host=False,
            preload_content=False,
            decode_content=False,
            chunked=chunked,
        )

    def _assert_manager_call(self, manager, *assert_args, **assert_kwargs):
        call_kwargs = {
            'strict': True,
            'maxsize': ANY,
            'timeout': ANY,
            'ssl_context': ANY,
            'socket_options': [],
            'cert_file': None,
            'key_file': None,
        }
        call_kwargs.update(assert_kwargs)
        manager.assert_called_with(*assert_args, **call_kwargs)

    def assert_pool_manager_call(self, *args, **kwargs):
        self._assert_manager_call(self.pool_manager_cls, *args, **kwargs)

    def assert_proxy_manager_call(self, *args, **kwargs):
        self._assert_manager_call(self.proxy_manager_fun, *args, **kwargs)

    def test_forwards_max_pool_size(self):
        URLLib3Session(max_pool_connections=22)
        self.assert_pool_manager_call(maxsize=22)

    def test_forwards_client_cert(self):
        URLLib3Session(client_cert='/some/cert')
        self.assert_pool_manager_call(cert_file='/some/cert', key_file=None)

    def test_forwards_client_cert_and_key_tuple(self):
        cert = ('/some/cert', '/some/key')
        URLLib3Session(client_cert=cert)
        self.assert_pool_manager_call(cert_file=cert[0], key_file=cert[1])

    def test_basic_https_proxy_with_client_cert(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies, client_cert='/some/cert')
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['https'],
            proxy_headers={},
            cert_file='/some/cert',
            key_file=None,
        )
        self.assert_request_sent()

    def test_basic_https_proxy_with_client_cert_and_key(self):
        cert = ('/some/cert', '/some/key')
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies, client_cert=cert)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['https'],
            proxy_headers={},
            cert_file=cert[0],
            key_file=cert[1],
        )
        self.assert_request_sent()

    def test_basic_request(self):
        session = URLLib3Session()
        session.send(self.request.prepare())
        self.assert_request_sent()
        self.response.stream.assert_called_once_with()

    def test_basic_streaming_request(self):
        session = URLLib3Session()
        self.request.stream_output = True
        session.send(self.request.prepare())
        self.assert_request_sent()
        self.response.stream.assert_not_called()

    def test_basic_https_request(self):
        session = URLLib3Session()
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_request_sent()

    def test_basic_https_proxy_request(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(proxies['https'], proxy_headers={})
        self.assert_request_sent()

    def test_basic_proxy_request_caches_manager(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        # assert we created the proxy manager
        self.assert_proxy_manager_call(proxies['https'], proxy_headers={})
        session.send(self.request.prepare())
        # assert that we did not create another proxy manager
        self.assertEqual(self.proxy_manager_fun.call_count, 1)

    def test_basic_http_proxy_request(self):
        proxies = {'http': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(proxies['http'], proxy_headers={})
        self.assert_request_sent(url=self.request.url)

    def test_ssl_context_is_explicit(self):
        session = URLLib3Session()
        session.send(self.request.prepare())
        _, manager_kwargs = self.pool_manager_cls.call_args
        self.assertIsNotNone(manager_kwargs.get('ssl_context'))

    def test_proxy_request_ssl_context_is_explicit(self):
        proxies = {'http': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        session.send(self.request.prepare())
        _, proxy_kwargs = self.proxy_manager_fun.call_args
        self.assertIsNotNone(proxy_kwargs.get('ssl_context'))

    def test_session_forwards_socket_options_to_pool_manager(self):
        socket_options = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]
        URLLib3Session(socket_options=socket_options)
        self.assert_pool_manager_call(socket_options=socket_options)

    def test_session_forwards_socket_options_to_proxy_manager(self):
        proxies = {'http': 'http://proxy.com'}
        socket_options = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]
        session = URLLib3Session(
            proxies=proxies,
            socket_options=socket_options,
        )
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['http'],
            proxy_headers={},
            socket_options=socket_options,
        )

    def make_request_with_error(self, error):
        self.connection.urlopen.side_effect = error
        session = URLLib3Session()
        session.send(self.request.prepare())

    @raises(EndpointConnectionError)
    def test_catches_new_connection_error(self):
        error = NewConnectionError(None, None)
        self.make_request_with_error(error)

    @raises(ConnectionClosedError)
    def test_catches_bad_status_line(self):
        error = ProtocolError(None)
        self.make_request_with_error(error)

    def test_aws_connection_classes_are_used(self):
        session = URLLib3Session()
        # ensure the pool manager is using the correct classes
        http_class = self.pool_manager.pool_classes_by_scheme.get('http')
        self.assertIs(http_class, AWSHTTPConnectionPool)
        https_class = self.pool_manager.pool_classes_by_scheme.get('https')
        self.assertIs(https_class, AWSHTTPSConnectionPool)

    def test_chunked_encoding_is_set_with_header(self):
        session = URLLib3Session()
        self.request.headers['Transfer-Encoding'] = 'chunked'

        session.send(self.request.prepare())
        self.assert_request_sent(
            chunked=True,
            headers={'Transfer-Encoding': 'chunked'},
        )

    def test_chunked_encoding_is_not_set_without_header(self):
        session = URLLib3Session()

        session.send(self.request.prepare())
        self.assert_request_sent(chunked=False)
Example #53
0
class TestURLLib3Session(unittest.TestCase):
    def setUp(self):
        self.request = AWSRequest(
            method='GET',
            url='http://example.com/',
            headers={},
            data=b'',
        )

        self.response = mock.Mock()
        self.response.headers = {}
        self.response.stream.return_value = b''

        self.pool_manager = mock.Mock()
        self.connection = mock.Mock()
        self.connection.urlopen.return_value = self.response
        self.pool_manager.connection_from_url.return_value = self.connection

        self.pool_patch = mock.patch('botocore.httpsession.PoolManager')
        self.proxy_patch = mock.patch('botocore.httpsession.proxy_from_url')
        self.pool_manager_cls = self.pool_patch.start()
        self.proxy_manager_fun = self.proxy_patch.start()
        self.pool_manager_cls.return_value = self.pool_manager
        self.proxy_manager_fun.return_value = self.pool_manager

    def tearDown(self):
        self.pool_patch.stop()
        self.proxy_patch.stop()

    def assert_request_sent(self, headers=None, body=None, url='/', chunked=False):
        if headers is None:
            headers = {}

        self.connection.urlopen.assert_called_once_with(
            method=self.request.method,
            url=url,
            body=body,
            headers=headers,
            retries=mock.ANY,
            assert_same_host=False,
            preload_content=False,
            decode_content=False,
            chunked=chunked,
        )

    def _assert_manager_call(self, manager, *assert_args, **assert_kwargs):
        call_kwargs = {
            'strict': True,
            'maxsize': mock.ANY,
            'timeout': mock.ANY,
            'ssl_context': mock.ANY,
            'socket_options': [],
            'cert_file': None,
            'key_file': None,
        }
        call_kwargs.update(assert_kwargs)
        manager.assert_called_with(*assert_args, **call_kwargs)

    def assert_pool_manager_call(self, *args, **kwargs):
        self._assert_manager_call(self.pool_manager_cls, *args, **kwargs)

    def assert_proxy_manager_call(self, *args, **kwargs):
        self._assert_manager_call(self.proxy_manager_fun, *args, **kwargs)

    def test_forwards_max_pool_size(self):
        URLLib3Session(max_pool_connections=22)
        self.assert_pool_manager_call(maxsize=22)

    def test_forwards_client_cert(self):
        URLLib3Session(client_cert='/some/cert')
        self.assert_pool_manager_call(cert_file='/some/cert', key_file=None)

    def test_forwards_client_cert_and_key_tuple(self):
        cert = ('/some/cert', '/some/key')
        URLLib3Session(client_cert=cert)
        self.assert_pool_manager_call(cert_file=cert[0], key_file=cert[1])

    def test_proxies_config_settings(self):
        proxies = {'http': 'http://proxy.com'}
        proxies_config = {
            'proxy_ca_bundle': 'path/to/bundle',
            'proxy_client_cert': ('path/to/cert', 'path/to/key'),
            'proxy_use_forwarding_for_https': False,
        }
        use_forwarding = proxies_config['proxy_use_forwarding_for_https']
        with mock.patch('botocore.httpsession.create_urllib3_context'):
            session = URLLib3Session(
                proxies=proxies,
                proxies_config=proxies_config
            )
            self.request.url = 'http://example.com/'
            session.send(self.request.prepare())
            self.assert_proxy_manager_call(
                proxies['http'],
                proxy_headers={},
                proxy_ssl_context=mock.ANY,
                use_forwarding_for_https=use_forwarding
            )
        self.assert_request_sent(url=self.request.url)

    def test_proxies_config_settings_unknown_config(self):
        proxies = {'http': 'http://proxy.com'}
        proxies_config = {
            'proxy_ca_bundle': None,
            'proxy_client_cert': None,
            'proxy_use_forwarding_for_https': True,
            'proxy_not_a_real_arg': 'do not pass'
        }
        use_forwarding = proxies_config['proxy_use_forwarding_for_https']
        session = URLLib3Session(
            proxies=proxies,
            proxies_config=proxies_config
        )
        self.request.url = 'http://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['http'],
            proxy_headers={},
            use_forwarding_for_https=use_forwarding
        )
        self.assertNotIn(
            'proxy_not_a_real_arg',
            self.proxy_manager_fun.call_args
        )
        self.assert_request_sent(url=self.request.url)

    def test_http_proxy_scheme_with_http_url(self):
        proxies = {'http': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'http://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['http'],
            proxy_headers={},
        )
        self.assert_request_sent(url=self.request.url)

    def test_http_proxy_scheme_with_https_url(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['https'],
            proxy_headers={},
        )
        self.assert_request_sent()

    def test_https_proxy_scheme_with_http_url(self):
        proxies = {'http': 'https://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'http://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['http'],
            proxy_headers={},
        )
        self.assert_request_sent(url=self.request.url)

    def test_https_proxy_scheme_tls_in_tls(self):
        proxies = {'https': 'https://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['https'],
            proxy_headers={},
        )
        self.assert_request_sent()

    def test_https_proxy_scheme_forwarding_https_url(self):
        proxies = {'https': 'https://proxy.com'}
        proxies_config = {"proxy_use_forwarding_for_https": True}
        session = URLLib3Session(proxies=proxies, proxies_config=proxies_config)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['https'],
            proxy_headers={},
            use_forwarding_for_https=True,
        )
        self.assert_request_sent(url=self.request.url)

    def test_basic_https_proxy_with_client_cert(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies, client_cert='/some/cert')
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['https'],
            proxy_headers={},
            cert_file='/some/cert',
            key_file=None,
        )
        self.assert_request_sent()

    def test_basic_https_proxy_with_client_cert_and_key(self):
        cert = ('/some/cert', '/some/key')
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies, client_cert=cert)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['https'],
            proxy_headers={},
            cert_file=cert[0],
            key_file=cert[1],
        )
        self.assert_request_sent()

    def test_urllib3_proxies_kwargs_included(self):
        cert = ('/some/cert', '/some/key')
        proxies = {'https': 'https://proxy.com'}
        proxies_config = {'proxy_client_cert': "path/to/cert"}
        with mock.patch('botocore.httpsession.create_urllib3_context'):
            session = URLLib3Session(
                proxies=proxies, client_cert=cert,
                proxies_config=proxies_config
            )
            self.request.url = 'https://example.com/'
            session.send(self.request.prepare())
            self.assert_proxy_manager_call(
                proxies['https'],
                proxy_headers={},
                cert_file=cert[0],
                key_file=cert[1],
                proxy_ssl_context=mock.ANY
            )
            self.assert_request_sent()

    def test_proxy_ssl_context_uses_check_hostname(self):
        cert = ('/some/cert', '/some/key')
        proxies = {'https': 'https://proxy.com'}
        proxies_config = {'proxy_client_cert': "path/to/cert"}
        with mock.patch('botocore.httpsession.create_urllib3_context'):
            session = URLLib3Session(
                proxies=proxies, client_cert=cert,
                proxies_config=proxies_config
            )
            self.request.url = 'https://example.com/'
            session.send(self.request.prepare())
            last_call = self.proxy_manager_fun.call_args[-1]
            self.assertIs(last_call['ssl_context'].check_hostname, True)

    def test_basic_request(self):
        session = URLLib3Session()
        session.send(self.request.prepare())
        self.assert_request_sent()
        self.response.stream.assert_called_once_with()

    def test_basic_streaming_request(self):
        session = URLLib3Session()
        self.request.stream_output = True
        session.send(self.request.prepare())
        self.assert_request_sent()
        self.response.stream.assert_not_called()

    def test_basic_https_request(self):
        session = URLLib3Session()
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_request_sent()

    def test_basic_https_proxy_request(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(proxies['https'], proxy_headers={})
        self.assert_request_sent()

    def test_basic_proxy_request_caches_manager(self):
        proxies = {'https': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        self.request.url = 'https://example.com/'
        session.send(self.request.prepare())
        # assert we created the proxy manager
        self.assert_proxy_manager_call(proxies['https'], proxy_headers={})
        session.send(self.request.prepare())
        # assert that we did not create another proxy manager
        self.assertEqual(self.proxy_manager_fun.call_count, 1)

    def test_basic_http_proxy_request(self):
        proxies = {'http': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(proxies['http'], proxy_headers={})
        self.assert_request_sent(url=self.request.url)

    def test_ssl_context_is_explicit(self):
        session = URLLib3Session()
        session.send(self.request.prepare())
        _, manager_kwargs = self.pool_manager_cls.call_args
        self.assertIsNotNone(manager_kwargs.get('ssl_context'))

    def test_proxy_request_ssl_context_is_explicit(self):
        proxies = {'http': 'http://proxy.com'}
        session = URLLib3Session(proxies=proxies)
        session.send(self.request.prepare())
        _, proxy_kwargs = self.proxy_manager_fun.call_args
        self.assertIsNotNone(proxy_kwargs.get('ssl_context'))

    def test_session_forwards_socket_options_to_pool_manager(self):
        socket_options = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]
        URLLib3Session(socket_options=socket_options)
        self.assert_pool_manager_call(socket_options=socket_options)

    def test_session_forwards_socket_options_to_proxy_manager(self):
        proxies = {'http': 'http://proxy.com'}
        socket_options = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]
        session = URLLib3Session(
            proxies=proxies,
            socket_options=socket_options,
        )
        session.send(self.request.prepare())
        self.assert_proxy_manager_call(
            proxies['http'],
            proxy_headers={},
            socket_options=socket_options,
        )

    def make_request_with_error(self, error):
        self.connection.urlopen.side_effect = error
        session = URLLib3Session()
        session.send(self.request.prepare())

    def test_catches_new_connection_error(self):
        error = NewConnectionError(None, None)
        with pytest.raises(EndpointConnectionError):
            self.make_request_with_error(error)

    def test_catches_bad_status_line(self):
        error = ProtocolError(None)
        with pytest.raises(ConnectionClosedError):
            self.make_request_with_error(error)

    def test_catches_proxy_error(self):
        self.connection.urlopen.side_effect = ProxyError('test', None)
        session = URLLib3Session(proxies={'http': 'http://*****:*****@proxy.com'})
        with pytest.raises(ProxyConnectionError) as e:
            session.send(self.request.prepare())
        assert 'user:pass' not in str(e.value)
        assert 'http://***:***@proxy.com' in str(e.value)

    def test_aws_connection_classes_are_used(self):
        session = URLLib3Session() # noqa
        # ensure the pool manager is using the correct classes
        http_class = self.pool_manager.pool_classes_by_scheme.get('http')
        self.assertIs(http_class, AWSHTTPConnectionPool)
        https_class = self.pool_manager.pool_classes_by_scheme.get('https')
        self.assertIs(https_class, AWSHTTPSConnectionPool)

    def test_chunked_encoding_is_set_with_header(self):
        session = URLLib3Session()
        self.request.headers['Transfer-Encoding'] = 'chunked'

        session.send(self.request.prepare())
        self.assert_request_sent(
            chunked=True,
            headers={'Transfer-Encoding': 'chunked'},
        )

    def test_chunked_encoding_is_not_set_without_header(self):
        session = URLLib3Session()

        session.send(self.request.prepare())
        self.assert_request_sent(chunked=False)