Exemplo n.º 1
0
 def setUp(self):
     super(TestKinesisListStreams, self).setUp()
     self.stream_name = "kinesis-test-stream"
     self.region = "us-east-1"
     self.client = self.session.create_client("kinesis", self.region)
     self.http_stubber = ClientHTTPStubber(self.client)
     self.http_stubber.add_response()
Exemplo n.º 2
0
class TestDocDBPresignUrlInjection(BaseSessionTest):

    def setUp(self):
        super(TestDocDBPresignUrlInjection, self).setUp()
        self.client = self.session.create_client('docdb', 'us-west-2')
        self.http_stubber = ClientHTTPStubber(self.client)

    def assert_presigned_url_injected_in_request(self, body):
        self.assertIn('PreSignedUrl', body)
        self.assertNotIn('SourceRegion', body)

    def test_copy_db_cluster_snapshot(self):
        params = {
            'SourceDBClusterSnapshotIdentifier': 'source-db',
            'TargetDBClusterSnapshotIdentifier': 'target-db',
            'SourceRegion': 'us-east-1'
        }
        response_body = (
            b'<CopyDBClusterSnapshotResponse>'
            b'<CopyDBClusterSnapshotResult>'
            b'</CopyDBClusterSnapshotResult>'
            b'</CopyDBClusterSnapshotResponse>'
        )
        self.http_stubber.add_response(body=response_body)
        with self.http_stubber:
            self.client.copy_db_cluster_snapshot(**params)
            sent_request = self.http_stubber.requests[0]
            self.assert_presigned_url_injected_in_request(sent_request.body)
    def setUp(self):
        super(TestRegionRedirect, self).setUp()
        self.client = self.session.create_client(
            's3',
            'us-west-2',
            config=Config(
                signature_version='s3v4',
                s3={'addressing_style': 'path'},
            ))
        self.http_stubber = ClientHTTPStubber(self.client)

        self.redirect_response = {
            'status':
            301,
            'headers': {
                'x-amz-bucket-region': 'eu-central-1'
            },
            'body':
            (b'<?xml version="1.0" encoding="UTF-8"?>\n'
             b'<Error>'
             b'    <Code>PermanentRedirect</Code>'
             b'    <Message>The bucket you are attempting to access must be'
             b'        addressed using the specified endpoint. Please send '
             b'        all future requests to this endpoint.'
             b'    </Message>'
             b'    <Bucket>foo</Bucket>'
             b'    <Endpoint>foo.s3.eu-central-1.amazonaws.com</Endpoint>'
             b'</Error>')
        }
        self.bad_signing_region_response = {
            'status':
            400,
            'headers': {
                'x-amz-bucket-region': 'eu-central-1'
            },
            'body': (b'<?xml version="1.0" encoding="UTF-8"?>'
                     b'<Error>'
                     b'  <Code>AuthorizationHeaderMalformed</Code>'
                     b'  <Message>the region us-west-2 is wrong; '
                     b'expecting eu-central-1</Message>'
                     b'  <Region>eu-central-1</Region>'
                     b'  <RequestId>BD9AA1730D454E39</RequestId>'
                     b'  <HostId></HostId>'
                     b'</Error>')
        }
        self.success_response = {
            'status':
            200,
            'headers': {},
            'body': (b'<?xml version="1.0" encoding="UTF-8"?>\n'
                     b'<ListBucketResult>'
                     b'    <Name>foo</Name>'
                     b'    <Prefix></Prefix>'
                     b'    <Marker></Marker>'
                     b'    <MaxKeys>1000</MaxKeys>'
                     b'    <EncodingType>url</EncodingType>'
                     b'    <IsTruncated>false</IsTruncated>'
                     b'</ListBucketResult>')
        }
Exemplo n.º 4
0
class TestCopySnapshotCustomization(BaseSessionTest):
    def setUp(self):
        super(TestCopySnapshotCustomization, self).setUp()
        self.session = botocore.session.get_session()
        self.client = self.session.create_client('ec2', 'us-east-1')
        self.http_stubber = ClientHTTPStubber(self.client)
        self.snapshot_id = 'snap-0123abc'
        self.copy_response = ('<?xml version="1.0" encoding="UTF-8"?>\n'
                              '<CopySnapshotResponse>\n'
                              '<snapshotId>%s</snapshotId>\n'
                              '</CopySnapshotResponse>\n')
        self.now = datetime.datetime(2011, 9, 9, 23, 36)
        self.datetime_patch = mock.patch.object(
            botocore.auth.datetime, 'datetime',
            mock.Mock(wraps=datetime.datetime))
        self.mocked_datetime = self.datetime_patch.start()
        self.mocked_datetime.utcnow.return_value = self.now

    def tearDown(self):
        super(TestCopySnapshotCustomization, self).tearDown()
        self.datetime_patch.stop()

    def add_copy_snapshot_response(self, snapshot_id):
        body = (self.copy_response % snapshot_id).encode('utf-8')
        self.http_stubber.add_response(body=body)

    def test_copy_snapshot_injects_presigned_url(self):
        self.add_copy_snapshot_response(self.snapshot_id)
        with self.http_stubber:
            result = self.client.copy_snapshot(
                SourceRegion='us-west-2',
                SourceSnapshotId=self.snapshot_id,
            )
        self.assertEqual(result['SnapshotId'], self.snapshot_id)
        self.assertEqual(len(self.http_stubber.requests), 1)
        snapshot_request = self.http_stubber.requests[0]
        body = parse_qs(snapshot_request.body)
        self.assertIn('PresignedUrl', body)
        presigned_url = urlparse(body['PresignedUrl'][0])
        self.assertEqual(presigned_url.scheme, 'https')
        self.assertEqual(presigned_url.netloc, 'ec2.us-west-2.amazonaws.com')
        query_args = parse_qs(presigned_url.query)
        self.assertEqual(query_args['Action'], ['CopySnapshot'])
        self.assertEqual(query_args['Version'], ['2016-11-15'])
        self.assertEqual(query_args['SourceRegion'], ['us-west-2'])
        self.assertEqual(query_args['DestinationRegion'], ['us-east-1'])
        self.assertEqual(query_args['SourceSnapshotId'], [self.snapshot_id])
        self.assertEqual(query_args['X-Amz-Algorithm'], ['AWS4-HMAC-SHA256'])
        expected_credential = 'access_key/20110909/us-west-2/ec2/aws4_request'
        self.assertEqual(query_args['X-Amz-Credential'], [expected_credential])
        self.assertEqual(query_args['X-Amz-Date'], ['20110909T233600Z'])
        self.assertEqual(query_args['X-Amz-Expires'], ['3600'])
        self.assertEqual(query_args['X-Amz-SignedHeaders'], ['host'])
        expected_signature = (
            'a94a6b52afdf3daa34c2e2a38a62b72c8dac129c9904c61aa1a5d86e38628537')
        self.assertEqual(query_args['X-Amz-Signature'], [expected_signature])
 def test_content_sha256_not_set_if_config_value_is_false(self):
     config = Config(signature_version='s3v4',
                     s3={'payload_signing_enabled': False})
     self.client = self.session.create_client('s3',
                                              self.region,
                                              config=config)
     self.http_stubber = ClientHTTPStubber(self.client)
     self.http_stubber.add_response()
     with self.http_stubber:
         self.client.put_object(Bucket='foo', Key='bar', Body='baz')
     sent_headers = self.get_sent_headers()
     sha_header = sent_headers.get('x-amz-content-sha256')
     self.assertEqual(sha_header, b'UNSIGNED-PAYLOAD')
 def test_500_error_with_non_xml_body(self):
     # Note: This exact test case may not be applicable from
     # an integration standpoint if the issue is fixed in the future.
     #
     # The issue is that:
     # S3 returns a 200 response but the received response from urllib3 has
     # a 500 status code and the headers are in the body of the
     # the response. Botocore will try to parse out the error body as xml,
     # but the body is invalid xml because it is full of headers.
     # So instead of blowing up on an XML parsing error, we
     # should at least use the 500 status code because that can be
     # retried.
     #
     # We are unsure of what exactly causes the response to be mangled
     # but we expect it to be how 100 continues are handled.
     non_xml_content = ('x-amz-id-2: foo\r\n'
                        'x-amz-request-id: bar\n'
                        'Date: Tue, 06 Oct 2015 03:20:38 GMT\r\n'
                        'ETag: "a6d856bc171fc6aa1b236680856094e2"\r\n'
                        'Content-Length: 0\r\n'
                        'Server: AmazonS3\r\n').encode('utf-8')
     s3 = self.session.create_client('s3')
     with ClientHTTPStubber(s3) as http_stubber:
         http_stubber.add_response(status=500, body=non_xml_content)
         http_stubber.add_response()
         response = s3.put_object(Bucket='mybucket',
                                  Key='mykey',
                                  Body=b'foo')
         # The first response should have been retried even though the xml is
         # invalid and eventually return the 200 response.
         self.assertEqual(response['ResponseMetadata']['HTTPStatusCode'],
                          200)
         self.assertEqual(len(http_stubber.requests), 2)
def _verify_expected_endpoint_url(region,
                                  bucket,
                                  key,
                                  s3_config,
                                  is_secure=True,
                                  customer_provided_endpoint=None,
                                  expected_url=None,
                                  signature_version=None):
    environ = {}
    with mock.patch('os.environ', environ):
        environ['AWS_ACCESS_KEY_ID'] = 'access_key'
        environ['AWS_SECRET_ACCESS_KEY'] = 'secret_key'
        environ['AWS_CONFIG_FILE'] = 'no-exist-foo'
        environ['AWS_SHARED_CREDENTIALS_FILE'] = 'no-exist-foo'
        session = create_session()
        session.config_filename = 'no-exist-foo'
        config = Config(signature_version=signature_version, s3=s3_config)
        s3 = session.create_client('s3',
                                   region_name=region,
                                   use_ssl=is_secure,
                                   config=config,
                                   endpoint_url=customer_provided_endpoint)
        with ClientHTTPStubber(s3) as http_stubber:
            http_stubber.add_response()
            s3.put_object(Bucket=bucket, Key=key, Body=b'bar')
            assert_equal(http_stubber.requests[0].url, expected_url)
Exemplo n.º 8
0
 def setUp(self):
     super(TestCopySnapshotCustomization, self).setUp()
     self.session = botocore.session.get_session()
     self.client = self.session.create_client('ec2', 'us-east-1')
     self.http_stubber = ClientHTTPStubber(self.client)
     self.snapshot_id = 'snap-0123abc'
     self.copy_response = ('<?xml version="1.0" encoding="UTF-8"?>\n'
                           '<CopySnapshotResponse>\n'
                           '<snapshotId>%s</snapshotId>\n'
                           '</CopySnapshotResponse>\n')
     self.now = datetime.datetime(2011, 9, 9, 23, 36)
     self.datetime_patch = mock.patch.object(
         botocore.auth.datetime, 'datetime',
         mock.Mock(wraps=datetime.datetime))
     self.mocked_datetime = self.datetime_patch.start()
     self.mocked_datetime.utcnow.return_value = self.now
Exemplo n.º 9
0
    def _test_amz_sdk_request_header_with_test_case(self, responses,
                                                    utcnow_side_effects,
                                                    expected_headers,
                                                    client_config):
        datetime_patcher = mock.patch.object(
            ibm_botocore.endpoint.datetime, 'datetime',
            mock.Mock(wraps=datetime.datetime))
        mocked_datetime = datetime_patcher.start()
        mocked_datetime.utcnow.side_effect = utcnow_side_effects

        client = self.session.create_client('dynamodb',
                                            self.region,
                                            config=client_config)
        with ClientHTTPStubber(client) as http_stubber:
            for response in responses:
                http_stubber.add_response(headers=response[1],
                                          status=response[0],
                                          body=b'{}')
            client.list_tables()
            amz_sdk_request_headers = [
                request.headers['amz-sdk-request']
                for request in http_stubber.requests
            ]
            self.assertListEqual(amz_sdk_request_headers, expected_headers)
        datetime_patcher.stop()
Exemplo n.º 10
0
def test_old_model_continues_to_work():
    # This test ensures that botocore can load the service models as they exist
    # today.  There's a directory in tests/functional/models that is a
    # snapshot of a service model.  This test ensures that we can continue
    # to stub an API call using this model.  That way if the models ever
    # change we have a mechanism to ensure that the existing models continue
    # to work with botocore.  The test should not change (with the exception
    # of potential changes to the ClientHTTPStubber), and the files in
    # tests/functional/models should not change!
    session = Session()
    loader = session.get_component('data_loader')
    # We're adding our path to the existing search paths so we don't have to
    # copy additional data files such as _retry.json to our TEST_MODELS_DIR.
    # We only care about the service model and endpoints file not changing.
    # This also prevents us from having to make any changes to this models dir
    # if we end up adding a new data file that's needed to create clients.
    # We're adding our TEST_MODELS_DIR as the first element in the list to
    # ensure we load the endpoints.json file from TEST_MODELS_DIR.  For the
    # service model we have an extra safety net where we can choose a custom
    # client name.
    loader.search_paths.insert(0, TEST_MODELS_DIR)

    # The model dir we copied was renamed to 'custom-lambda'
    # to ensure we're loading our version of the model and not
    # the built in one.
    client = session.create_client(
        'custom-acm',
        region_name='us-west-2',
        aws_access_key_id='foo',
        aws_secret_access_key='bar',
    )
    with ClientHTTPStubber(client) as stubber:
        stubber.add_response(url='https://acm.us-west-2.amazonaws.com/',
                             headers={
                                 'x-amzn-RequestId': 'abcd',
                                 'Date': 'Fri, 26 Oct 2018 01:46:30 GMT',
                                 'Content-Length': '29',
                                 'Content-Type': 'application/x-amz-json-1.1'
                             },
                             body=b'{"CertificateSummaryList":[]}')
        response = client.list_certificates()
        assert_equal(
            response, {
                'CertificateSummaryList': [],
                'ResponseMetadata': {
                    'HTTPHeaders': {
                        'content-length': '29',
                        'content-type': 'application/x-amz-json-1.1',
                        'date': 'Fri, 26 Oct 2018 01:46:30 GMT',
                        'x-amzn-requestid': 'abcd'
                    },
                    'HTTPStatusCode': 200,
                    'RequestId': 'abcd',
                    'RetryAttempts': 0
                }
            })

    # Also verify we can use the paginators as well.
    assert_equal(client.can_paginate('list_certificates'), True)
    assert_equal(client.waiter_names, ['certificate_validated'])
Exemplo n.º 11
0
class UnsignedOperationTestCase(object):
    def __init__(self, client, operation_name, parameters):
        self._client = client
        self._operation_name = operation_name
        self._parameters = parameters
        self._http_stubber = ClientHTTPStubber(self._client)

    def run(self):
        operation = getattr(self._client, self._operation_name)

        self._http_stubber.add_response(body=b'{}')
        with self._http_stubber:
            operation(**self._parameters)
            request = self._http_stubber.requests[0]

        assert_false('authorization' in request.headers,
                     'authorization header found in unsigned operation')
Exemplo n.º 12
0
class TestNeptunePresignUrlInjection(BaseSessionTest):

    def setUp(self):
        super(TestNeptunePresignUrlInjection, self).setUp()
        self.client = self.session.create_client('neptune', 'us-west-2')
        self.http_stubber = ClientHTTPStubber(self.client)

    def assert_presigned_url_injected_in_request(self, body):
        self.assertIn('PreSignedUrl', body)
        self.assertNotIn('SourceRegion', body)

    def test_create_db_cluster(self):
        params = {
            'DBClusterIdentifier': 'my-cluster',
            'Engine': 'neptune',
            'SourceRegion': 'us-east-1'
        }
        response_body = (
            b'<CreateDBClusterResponse>'
            b'<CreateDBClusterResult>'
            b'</CreateDBClusterResult>'
            b'</CreateDBClusterResponse>'
        )
        self.http_stubber.add_response(body=response_body)
        with self.http_stubber:
            self.client.create_db_cluster(**params)
            sent_request = self.http_stubber.requests[0]
            self.assert_presigned_url_injected_in_request(sent_request.body)

    def test_copy_db_cluster_snapshot(self):
        params = {
            'SourceDBClusterSnapshotIdentifier': 'source-db',
            'TargetDBClusterSnapshotIdentifier': 'target-db',
            'SourceRegion': 'us-east-1'
        }
        response_body = (
            b'<CopyDBClusterSnapshotResponse>'
            b'<CopyDBClusterSnapshotResult>'
            b'</CopyDBClusterSnapshotResult>'
            b'</CopyDBClusterSnapshotResponse>'
        )
        self.http_stubber.add_response(body=response_body)
        with self.http_stubber:
            self.client.copy_db_cluster_snapshot(**params)
            sent_request = self.http_stubber.requests[0]
            self.assert_presigned_url_injected_in_request(sent_request.body)
Exemplo n.º 13
0
class TestCloudsearchdomain(BaseSessionTest):
    def setUp(self):
        super(TestCloudsearchdomain, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client(
            'cloudsearchdomain', self.region)
        self.http_stubber = ClientHTTPStubber(self.client)

    def test_search(self):
        self.http_stubber.add_response(body=b'{}')
        with self.http_stubber:
            self.client.search(query='foo')
            request = self.http_stubber.requests[0]
            self.assertIn('q=foo', request.body)
            self.assertEqual(request.method, 'POST')
            content_type = b'application/x-www-form-urlencoded'
            self.assertEqual(request.headers.get('Content-Type'), content_type)
Exemplo n.º 14
0
class TestCloudsearchdomain(BaseSessionTest):
    def setUp(self):
        super(TestCloudsearchdomain, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client('cloudsearchdomain',
                                                 self.region)
        self.http_stubber = ClientHTTPStubber(self.client)

    def test_search(self):
        self.http_stubber.add_response(body=b'{}')
        with self.http_stubber:
            self.client.search(query='foo')
            request = self.http_stubber.requests[0]
            self.assertIn('q=foo', request.body)
            self.assertEqual(request.method, 'POST')
            content_type = b'application/x-www-form-urlencoded'
            self.assertEqual(request.headers.get('Content-Type'), content_type)
Exemplo n.º 15
0
class TestMachineLearning(BaseSessionTest):
    def setUp(self):
        super(TestMachineLearning, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client('machinelearning',
                                                 self.region)
        self.http_stubber = ClientHTTPStubber(self.client)

    def test_predict(self):
        self.http_stubber.add_response(body=b'{}')
        with self.http_stubber:
            custom_endpoint = 'https://myendpoint.amazonaws.com/'
            self.client.predict(MLModelId='ml-foo',
                                Record={'Foo': 'Bar'},
                                PredictEndpoint=custom_endpoint)
            sent_request = self.http_stubber.requests[0]
            self.assertEqual(sent_request.url, custom_endpoint)
Exemplo n.º 16
0
class TestRDSPresignUrlInjection(BaseSessionTest):

    def setUp(self):
        super(TestRDSPresignUrlInjection, self).setUp()
        self.client = self.session.create_client('rds', 'us-west-2')
        self.http_stubber = ClientHTTPStubber(self.client)

    def assert_presigned_url_injected_in_request(self, body):
        self.assertIn('PreSignedUrl', body)
        self.assertNotIn('SourceRegion', body)

    def test_copy_snapshot(self):
        params = {
            'SourceDBSnapshotIdentifier': 'source-db',
            'TargetDBSnapshotIdentifier': 'target-db',
            'SourceRegion': 'us-east-1'
        }
        response_body = (
                    b'<CopyDBSnapshotResponse>'
                    b'<CopyDBSnapshotResult></CopyDBSnapshotResult>'
                    b'</CopyDBSnapshotResponse>'
        )
        self.http_stubber.add_response(body=response_body)
        with self.http_stubber:
            self.client.copy_db_snapshot(**params)
            sent_request = self.http_stubber.requests[0]
            self.assert_presigned_url_injected_in_request(sent_request.body)

    def test_create_db_instance_read_replica(self):
        params = {
            'SourceDBInstanceIdentifier': 'source-db',
            'DBInstanceIdentifier': 'target-db',
            'SourceRegion': 'us-east-1'
        }
        response_body = (
            b'<CreateDBInstanceReadReplicaResponse>'
            b'<CreateDBInstanceReadReplicaResult>'
            b'</CreateDBInstanceReadReplicaResult>'
            b'</CreateDBInstanceReadReplicaResponse>'
        )
        self.http_stubber.add_response(body=response_body)
        with self.http_stubber:
            self.client.create_db_instance_read_replica(**params)
            sent_request = self.http_stubber.requests[0]
            self.assert_presigned_url_injected_in_request(sent_request.body)
Exemplo n.º 17
0
 def get_prepared_request(self, operation, params, force_hmacv1=False):
     if force_hmacv1:
         self.session.register('choose-signer', self.enable_hmacv1)
     client = self.session.create_client('s3', self.region_name)
     with ClientHTTPStubber(client) as http_stubber:
         http_stubber.add_response()
         getattr(client, operation)(**params)
         # Return the request that was sent over the wire.
         return http_stubber.requests[0]
Exemplo n.º 18
0
 def assert_will_retry_n_times(self, client, num_retries):
     num_responses = num_retries + 1
     with ClientHTTPStubber(client) as http_stubber:
         for _ in range(num_responses):
             http_stubber.add_response(status=500, body=b'{}')
         with self.assertRaisesRegexp(
                 ClientError, 'reached max retries: %s' % num_retries):
             yield
         self.assertEqual(len(http_stubber.requests), num_responses)
Exemplo n.º 19
0
class TestMachineLearning(BaseSessionTest):
    def setUp(self):
        super(TestMachineLearning, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client(
            'machinelearning', self.region)
        self.http_stubber = ClientHTTPStubber(self.client)

    def test_predict(self):
        self.http_stubber.add_response(body=b'{}')
        with self.http_stubber:
            custom_endpoint = 'https://myendpoint.amazonaws.com/'
            self.client.predict(
                MLModelId='ml-foo',
                Record={'Foo': 'Bar'},
                PredictEndpoint=custom_endpoint
            )
            sent_request = self.http_stubber.requests[0]
            self.assertEqual(sent_request.url, custom_endpoint)
Exemplo n.º 20
0
class UnsignedOperationTestCase(object):
    def __init__(self, client, operation_name, parameters):
        self._client = client
        self._operation_name = operation_name
        self._parameters = parameters
        self._http_stubber = ClientHTTPStubber(self._client)

    def run(self):
        operation = getattr(self._client, self._operation_name)

        self._http_stubber.add_response(body=b'{}')
        with self._http_stubber:
            operation(**self._parameters)
            request = self._http_stubber.requests[0]

        assert_false(
            'authorization' in request.headers,
            'authorization header found in unsigned operation'
        )
Exemplo n.º 21
0
class TestLex(BaseSessionTest):
    def setUp(self):
        super(TestLex, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client('lex-runtime', self.region)
        self.http_stubber = ClientHTTPStubber(self.client)

    def test_unsigned_payload(self):
        params = {
            'botName': 'foo',
            'botAlias': 'bar',
            'userId': 'baz',
            'contentType': 'application/octet-stream',
            'inputStream': b''
        }

        timestamp = datetime(2017, 3, 22, 0, 0)

        with mock.patch('botocore.auth.datetime') as _datetime:
            _datetime.datetime.utcnow.return_value = timestamp
            self.http_stubber.add_response(body=b'{}')
            with self.http_stubber:
                self.client.post_content(**params)
                request = self.http_stubber.requests[0]

        # The payload gets added to the string to sign, and then part of the
        # signature. The signature will be part of the authorization header.
        # Since we don't have direct access to the payload signature,
        # we compare the authorization instead.
        authorization = request.headers.get('authorization')

        expected_authorization = (
            b'AWS4-HMAC-SHA256 '
            b'Credential=access_key/20170322/us-west-2/lex/aws4_request, '
            b'SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date,'
            b' Signature='
            b'7f93fde5c36163dce6ee116fcfebab13474ab903782fea04c00bb1dedc3fc4cc'
        )
        self.assertEqual(authorization, expected_authorization)

        content_header = request.headers.get('x-amz-content-sha256')
        self.assertEqual(content_header, b'UNSIGNED-PAYLOAD')
Exemplo n.º 22
0
class TestLex(BaseSessionTest):
    def setUp(self):
        super(TestLex, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client('lex-runtime', self.region)
        self.http_stubber = ClientHTTPStubber(self.client)

    def test_unsigned_payload(self):
        params = {
            'botName': 'foo',
            'botAlias': 'bar',
            'userId': 'baz',
            'contentType': 'application/octet-stream',
            'inputStream': b''
        }

        timestamp = datetime(2017, 3, 22, 0, 0)

        with mock.patch('botocore.auth.datetime') as _datetime:
            _datetime.datetime.utcnow.return_value = timestamp
            self.http_stubber.add_response(body=b'{}')
            with self.http_stubber:
                self.client.post_content(**params)
                request = self.http_stubber.requests[0]

        # The payload gets added to the string to sign, and then part of the
        # signature. The signature will be part of the authorization header.
        # Since we don't have direct access to the payload signature,
        # we compare the authorization instead.
        authorization = request.headers.get('authorization')

        expected_authorization = (
            b'AWS4-HMAC-SHA256 '
            b'Credential=access_key/20170322/us-west-2/lex/aws4_request, '
            b'SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date,'
            b' Signature='
            b'7f93fde5c36163dce6ee116fcfebab13474ab903782fea04c00bb1dedc3fc4cc'
        )
        self.assertEqual(authorization, expected_authorization)

        content_header = request.headers.get('x-amz-content-sha256')
        self.assertEqual(content_header, b'UNSIGNED-PAYLOAD')
Exemplo n.º 23
0
def _make_client_call_with_errors(client, operation_name, kwargs):
    operation = getattr(client, xform_name(operation_name))
    exception = ConnectionClosedError(endpoint_url='https://mock.eror')
    with ClientHTTPStubber(client) as http_stubber:
        http_stubber.responses.append(exception)
        http_stubber.responses.append(None)
        try:
            response = operation(**kwargs)
        except ClientError as e:
            assert False, ('Request was not retried properly, '
                           'received error:\n%s' % pformat(e))
Exemplo n.º 24
0
def _make_client_call_with_errors(client, operation_name, kwargs):
    operation = getattr(client, xform_name(operation_name))
    exception = ConnectionClosedError(endpoint_url='https://mock.eror')
    with ClientHTTPStubber(client, strict=False) as http_stubber:
        http_stubber.responses.append(exception)
        try:
            response = operation(**kwargs)
        except ClientError as e:
            assert False, ('Request was not retried properly, '
                           'received error:\n%s' % pformat(e))
        # Ensure we used the stubber as we're not using it in strict mode
        assert len(http_stubber.responses) == 0, 'Stubber was not used!'
Exemplo n.º 25
0
 def assert_will_retry_n_times(self, client, num_retries,
                               status=500, body=b'{}'):
     num_responses = num_retries + 1
     if not isinstance(body, bytes):
         body = json.dumps(body).encode()
     with ClientHTTPStubber(client) as http_stubber:
         for _ in range(num_responses):
             http_stubber.add_response(status=status, body=body)
         with self.assertRaisesRegexp(
                 ClientError, 'reached max retries: %s' % num_retries):
             yield
         self.assertEqual(len(http_stubber.requests), num_responses)
Exemplo n.º 26
0
def test_unsigned_operations(operation_name, parameters):
    environ = {
        'AWS_ACCESS_KEY_ID': 'access_key',
        'AWS_SECRET_ACCESS_KEY': 'secret_key',
        'AWS_CONFIG_FILE': 'no-exist-foo',
    }

    with mock.patch('os.environ', environ):
        session = create_session()
        session.config_filename = 'no-exist-foo'
        client = session.create_client('cognito-idp', 'us-west-2')
        http_stubber = ClientHTTPStubber(client)

        operation = getattr(client, operation_name)

        http_stubber.add_response(body=b'{}')
        with http_stubber:
            operation(**parameters)
            request = http_stubber.requests[0]

        assert 'authorization' not in request.headers, (
            'authorization header found in unsigned operation')
 def setUp(self):
     super(TestRecordStatementsInjections, self).setUp()
     self.client = self.session.create_client('s3', 'us-west-2')
     self.http_stubber = ClientHTTPStubber(self.client)
     self.s3_response_body = (
         '<ListAllMyBucketsResult '
         '    xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'
         '  <Owner>'
         '    <ID>d41d8cd98f00b204e9800998ecf8427e</ID>'
         '    <DisplayName>foo</DisplayName>'
         '  </Owner>'
         '  <Buckets>'
         '    <Bucket>'
         '      <Name>bar</Name>'
         '      <CreationDate>1912-06-23T22:57:02.000Z</CreationDate>'
         '    </Bucket>'
         '  </Buckets>'
         '</ListAllMyBucketsResult>').encode('utf-8')
     self.recording_handler = RecordingHandler()
     history_recorder = get_global_history_recorder()
     history_recorder.enable()
     history_recorder.add_handler(self.recording_handler)
Exemplo n.º 28
0
class TestApiGateway(BaseSessionTest):
    def setUp(self):
        super(TestApiGateway, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client('apigateway', self.region)
        self.http_stubber = ClientHTTPStubber(self.client)

    def test_get_export(self):
        params = {
            'restApiId': 'foo',
            'stageName': 'bar',
            'exportType': 'swagger',
            'accepts': 'application/yaml'
        }

        self.http_stubber.add_response(body=b'{}')
        with self.http_stubber:
            self.client.get_export(**params)
            request = self.http_stubber.requests[0]
            self.assertEqual(request.method, 'GET')
            self.assertEqual(request.headers.get('Accept'),
                             b'application/yaml')
Exemplo n.º 29
0
class TestApiGateway(BaseSessionTest):
    def setUp(self):
        super(TestApiGateway, self).setUp()
        self.region = 'us-west-2'
        self.client = self.session.create_client(
            'apigateway', self.region)
        self.http_stubber = ClientHTTPStubber(self.client)

    def test_get_export(self):
        params = {
            'restApiId': 'foo',
            'stageName': 'bar',
            'exportType': 'swagger',
            'accepts': 'application/yaml'
        }

        self.http_stubber.add_response(body=b'{}')
        with self.http_stubber:
            self.client.get_export(**params)
            request = self.http_stubber.requests[0]
            self.assertEqual(request.method, 'GET')
            self.assertEqual(request.headers.get('Accept'), b'application/yaml')
Exemplo n.º 30
0
class TestRDSPresignUrlInjection(BaseSessionTest):
    def setUp(self):
        super(TestRDSPresignUrlInjection, self).setUp()
        self.client = self.session.create_client('rds', 'us-west-2')
        self.http_stubber = ClientHTTPStubber(self.client)

    def assert_presigned_url_injected_in_request(self, body):
        self.assertIn('PreSignedUrl', body)
        self.assertNotIn('SourceRegion', body)

    def test_copy_snapshot(self):
        params = {
            'SourceDBSnapshotIdentifier': 'source-db',
            'TargetDBSnapshotIdentifier': 'target-db',
            'SourceRegion': 'us-east-1'
        }
        response_body = (b'<CopyDBSnapshotResponse>'
                         b'<CopyDBSnapshotResult></CopyDBSnapshotResult>'
                         b'</CopyDBSnapshotResponse>')
        self.http_stubber.add_response(body=response_body)
        with self.http_stubber:
            self.client.copy_db_snapshot(**params)
            sent_request = self.http_stubber.requests[0]
            self.assert_presigned_url_injected_in_request(sent_request.body)

    def test_create_db_instance_read_replica(self):
        params = {
            'SourceDBInstanceIdentifier': 'source-db',
            'DBInstanceIdentifier': 'target-db',
            'SourceRegion': 'us-east-1'
        }
        response_body = (b'<CreateDBInstanceReadReplicaResponse>'
                         b'<CreateDBInstanceReadReplicaResult>'
                         b'</CreateDBInstanceReadReplicaResult>'
                         b'</CreateDBInstanceReadReplicaResponse>')
        self.http_stubber.add_response(body=response_body)
        with self.http_stubber:
            self.client.create_db_instance_read_replica(**params)
            sent_request = self.http_stubber.requests[0]
            self.assert_presigned_url_injected_in_request(sent_request.body)

    def test_start_db_instance_automated_backups_replication(self):
        params = {
            'SourceDBInstanceArn':
            'arn:aws:rds:us-east-1:123456789012:db:source-db-instance',
            'SourceRegion': 'us-east-1',
        }
        response_body = (
            b'<StartDBInstanceAutomatedBackupsReplicationResponse>'
            b'<StartDBInstanceAutomatedBackupsReplicationResult>'
            b'</StartDBInstanceAutomatedBackupsReplicationResult>'
            b'</StartDBInstanceAutomatedBackupsReplicationResponse>')
        self.http_stubber.add_response(body=response_body)
        with self.http_stubber:
            self.client.start_db_instance_automated_backups_replication(
                **params)
            sent_request = self.http_stubber.requests[0]
            self.assert_presigned_url_injected_in_request(sent_request.body)
Exemplo n.º 31
0
    def create_client(self,
                      service_name='dynamodb',
                      region=None,
                      config=None,
                      endpoint_url=None):
        if region is None:
            region = self.region
        client = self.session.create_client(service_name,
                                            region,
                                            config=config,
                                            endpoint_url=endpoint_url)
        http_stubber = ClientHTTPStubber(client)

        return client, http_stubber
Exemplo n.º 32
0
    def test_resign_request_in_us_east_1_fails(self):
        region_headers = {'x-amz-bucket-region': 'eu-central-1'}

        # Verify that the final 400 response is propagated
        # back to the user.
        client = self.session.create_client('s3', 'us-east-1')
        with ClientHTTPStubber(client) as http_stubber:
            http_stubber.add_response(status=400)
            http_stubber.add_response(status=400, headers=region_headers)
            http_stubber.add_response(headers=region_headers)
            # The final request still fails with a 400.
            http_stubber.add_response(status=400)
            with self.assertRaises(ClientError) as e:
                client.head_object(Bucket='foo', Key='bar')
            self.assertEqual(len(http_stubber.requests), 4)
Exemplo n.º 33
0
def test_public_apis_will_not_be_signed(client, operation, kwargs):
    with ClientHTTPStubber(client) as http_stubber:
        http_stubber.responses.append(EarlyExit())
        try:
            operation(**kwargs)
        except EarlyExit:
            pass
        request = http_stubber.requests[0]

    sig_v2_disabled = 'SignatureVersion=2' not in request.url
    assert sig_v2_disabled, "SigV2 is incorrectly enabled"
    sig_v3_disabled = 'X-Amzn-Authorization' not in request.headers
    assert sig_v3_disabled, "SigV3 is incorrectly enabled"
    sig_v4_disabled = 'Authorization' not in request.headers
    assert sig_v4_disabled, "SigV4 is incorrectly enabled"
Exemplo n.º 34
0
 def test_can_exhaust_default_retry_quota(self):
     # Quota of 500 / 5 retry costs == 100 retry attempts
     # 100 retry attempts / 2 retries per API call == 50 client calls
     client = self.create_client_with_retry_mode('dynamodb',
                                                 retry_mode='standard')
     for i in range(50):
         with self.assert_will_retry_n_times(client, 2, status=502):
             client.list_tables()
     # Now on the 51th attempt we should see quota errors, which we can
     # verify by looking at the request metadata.
     with ClientHTTPStubber(client) as http_stubber:
         http_stubber.add_response(status=502, body=b'{}')
         with self.assertRaises(ClientError) as e:
             client.list_tables()
     self.assertTrue(
         e.exception.response['ResponseMetadata'].get('RetryQuotaReached'))
Exemplo n.º 35
0
 def test_int_values_with_sigv4(self):
     s3 = self.session.create_client(
         's3', config=Config(signature_version='s3v4'))
     with ClientHTTPStubber(s3) as http_stubber:
         http_stubber.add_response()
         s3.upload_part(Bucket='foo',
                        Key='bar',
                        Body=b'foo',
                        UploadId='bar',
                        PartNumber=1,
                        ContentLength=3)
         headers = http_stubber.requests[0].headers
         # Verify that the request integer value of 3 has been converted to
         # string '3'.  This also means we've made it pass the signer which
         # expects string values in order to sign properly.
         self.assertEqual(headers['Content-Length'], b'3')
Exemplo n.º 36
0
class TestS3SigV4(BaseS3OperationTest):
    def setUp(self):
        super(TestS3SigV4, self).setUp()
        self.client = self.session.create_client(
            's3', self.region, config=Config(signature_version='s3v4'))
        self.http_stubber = ClientHTTPStubber(self.client)
        self.http_stubber.add_response()

    def get_sent_headers(self):
        return self.http_stubber.requests[0].headers

    def test_content_md5_set(self):
        with self.http_stubber:
            self.client.put_object(Bucket='foo', Key='bar', Body='baz')
        self.assertIn('content-md5', self.get_sent_headers())

    def test_content_sha256_set_if_config_value_is_true(self):
        config = Config(signature_version='s3v4',
                        s3={'payload_signing_enabled': True})
        self.client = self.session.create_client('s3',
                                                 self.region,
                                                 config=config)
        self.http_stubber = ClientHTTPStubber(self.client)
        self.http_stubber.add_response()
        with self.http_stubber:
            self.client.put_object(Bucket='foo', Key='bar', Body='baz')
        sent_headers = self.get_sent_headers()
        sha_header = sent_headers.get('x-amz-content-sha256')
        self.assertNotEqual(sha_header, b'UNSIGNED-PAYLOAD')

    def test_content_sha256_not_set_if_config_value_is_false(self):
        config = Config(signature_version='s3v4',
                        s3={'payload_signing_enabled': False})
        self.client = self.session.create_client('s3',
                                                 self.region,
                                                 config=config)
        self.http_stubber = ClientHTTPStubber(self.client)
        self.http_stubber.add_response()
        with self.http_stubber:
            self.client.put_object(Bucket='foo', Key='bar', Body='baz')
        sent_headers = self.get_sent_headers()
        sha_header = sent_headers.get('x-amz-content-sha256')
        self.assertEqual(sha_header, b'UNSIGNED-PAYLOAD')

    def test_content_sha256_set_if_md5_is_unavailable(self):
        with mock.patch('ibm_botocore.auth.MD5_AVAILABLE', False):
            with mock.patch('ibm_botocore.handlers.MD5_AVAILABLE', False):
                with self.http_stubber:
                    self.client.put_object(Bucket='foo', Key='bar', Body='baz')
        sent_headers = self.get_sent_headers()
        unsigned = 'UNSIGNED-PAYLOAD'
        self.assertNotEqual(sent_headers['x-amz-content-sha256'], unsigned)
        self.assertNotIn('content-md5', sent_headers)
Exemplo n.º 37
0
 def test_multiple_transitions_returns_one(self):
     response_body = ('<?xml version="1.0" ?>'
                      '<LifecycleConfiguration xmlns="http://s3.amazonaws.'
                      'com/doc/2006-03-01/">'
                      '	<Rule>'
                      '		<ID>transitionRule</ID>'
                      '		<Prefix>foo</Prefix>'
                      '		<Status>Enabled</Status>'
                      '		<Transition>'
                      '			<Days>40</Days>'
                      '			<StorageClass>STANDARD_IA</StorageClass>'
                      '		</Transition>'
                      '		<Transition>'
                      '			<Days>70</Days>'
                      '			<StorageClass>GLACIER</StorageClass>'
                      '		</Transition>'
                      '	</Rule>'
                      '	<Rule>'
                      '		<ID>noncurrentVersionRule</ID>'
                      '		<Prefix>bar</Prefix>'
                      '		<Status>Enabled</Status>'
                      '		<NoncurrentVersionTransition>'
                      '			<NoncurrentDays>40</NoncurrentDays>'
                      '			<StorageClass>STANDARD_IA</StorageClass>'
                      '		</NoncurrentVersionTransition>'
                      '		<NoncurrentVersionTransition>'
                      '			<NoncurrentDays>70</NoncurrentDays>'
                      '			<StorageClass>GLACIER</StorageClass>'
                      '		</NoncurrentVersionTransition>'
                      '	</Rule>'
                      '</LifecycleConfiguration>').encode('utf-8')
     s3 = self.session.create_client('s3')
     with ClientHTTPStubber(s3) as http_stubber:
         http_stubber.add_response(body=response_body)
         response = s3.get_bucket_lifecycle(Bucket='mybucket')
     # Each Transition member should have at least one of the
     # transitions provided.
     self.assertEqual(response['Rules'][0]['Transition'], {
         'Days': 40,
         'StorageClass': 'STANDARD_IA'
     })
     self.assertEqual(response['Rules'][1]['NoncurrentVersionTransition'], {
         'NoncurrentDays': 40,
         'StorageClass': 'STANDARD_IA'
     })
Exemplo n.º 38
0
 def setUp(self):
     super(TestRecordStatementsInjections, self).setUp()
     self.client = self.session.create_client('s3', 'us-west-2')
     self.http_stubber = ClientHTTPStubber(self.client)
     self.s3_response_body = (
         '<ListAllMyBucketsResult '
         '    xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'
         '  <Owner>'
         '    <ID>d41d8cd98f00b204e9800998ecf8427e</ID>'
         '    <DisplayName>foo</DisplayName>'
         '  </Owner>'
         '  <Buckets>'
         '    <Bucket>'
         '      <Name>bar</Name>'
         '      <CreationDate>1912-06-23T22:57:02.000Z</CreationDate>'
         '    </Bucket>'
         '  </Buckets>'
         '</ListAllMyBucketsResult>'
     ).encode('utf-8')
     self.recording_handler = RecordingHandler()
     history_recorder = get_global_history_recorder()
     history_recorder.enable()
     history_recorder.add_handler(self.recording_handler)
Exemplo n.º 39
0
class TestRecordStatementsInjections(BaseSessionTest):

    def setUp(self):
        super(TestRecordStatementsInjections, self).setUp()
        self.client = self.session.create_client('s3', 'us-west-2')
        self.http_stubber = ClientHTTPStubber(self.client)
        self.s3_response_body = (
            '<ListAllMyBucketsResult '
            '    xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'
            '  <Owner>'
            '    <ID>d41d8cd98f00b204e9800998ecf8427e</ID>'
            '    <DisplayName>foo</DisplayName>'
            '  </Owner>'
            '  <Buckets>'
            '    <Bucket>'
            '      <Name>bar</Name>'
            '      <CreationDate>1912-06-23T22:57:02.000Z</CreationDate>'
            '    </Bucket>'
            '  </Buckets>'
            '</ListAllMyBucketsResult>'
        ).encode('utf-8')
        self.recording_handler = RecordingHandler()
        history_recorder = get_global_history_recorder()
        history_recorder.enable()
        history_recorder.add_handler(self.recording_handler)

    def _get_all_events_of_type(self, event_type):
        recorded_calls = self.recording_handler.recorded_calls
        matching = [call for call in recorded_calls
                    if call[0] == event_type]
        return matching

    def test_does_record_api_call(self):
        self.http_stubber.add_response(body=self.s3_response_body)
        with self.http_stubber:
            self.client.list_buckets()

        api_call_events = self._get_all_events_of_type('API_CALL')
        self.assertEqual(len(api_call_events), 1)
        event = api_call_events[0]
        event_type, payload, source = event
        self.assertEqual(payload, {
                'operation': u'ListBuckets',
                'params': {},
                'service': 's3'
        })
        self.assertEqual(source, 'BOTOCORE')

    def test_does_record_http_request(self):
        self.http_stubber.add_response(body=self.s3_response_body)
        with self.http_stubber:
            self.client.list_buckets()

        http_request_events = self._get_all_events_of_type('HTTP_REQUEST')
        self.assertEqual(len(http_request_events), 1)
        event = http_request_events[0]
        event_type, payload, source = event

        method = payload['method']
        self.assertEqual(method, u'GET')

        # The header values vary too much per request to verify them here.
        # Instead just check the presense of each expected header.
        headers = payload['headers']
        for expected_header in ['Authorization', 'User-Agent', 'X-Amz-Date',
                                'X-Amz-Content-SHA256']:
            self.assertIn(expected_header, headers)

        body = payload['body']
        self.assertIsNone(body)

        streaming = payload['streaming']
        self.assertEquals(streaming, False)

        url = payload['url']
        self.assertEquals(url, 'https://s3.us-west-2.amazonaws.com/')

        self.assertEqual(source, 'BOTOCORE')

    def test_does_record_http_response(self):
        self.http_stubber.add_response(body=self.s3_response_body)
        with self.http_stubber:
            self.client.list_buckets()

        http_response_events = self._get_all_events_of_type('HTTP_RESPONSE')
        self.assertEqual(len(http_response_events), 1)
        event = http_response_events[0]
        event_type, payload, source = event

        self.assertEqual(payload, {
                'status_code': 200,
                'headers': {},
                'streaming': False,
                'body': self.s3_response_body,
                'context': {'operation_name': 'ListBuckets'}
            }
        )
        self.assertEqual(source, 'BOTOCORE')

    def test_does_record_parsed_response(self):
        self.http_stubber.add_response(body=self.s3_response_body)
        with self.http_stubber:
            self.client.list_buckets()

        parsed_response_events = self._get_all_events_of_type(
            'PARSED_RESPONSE')
        self.assertEqual(len(parsed_response_events), 1)
        event = parsed_response_events[0]
        event_type, payload, source = event

        # Given that the request contains headers with a user agent string
        # a date and a signature we need to disassemble the call and manually
        # assert the interesting bits since mock can only assert if the args
        # all match exactly.
        owner = payload['Owner']
        self.assertEqual(owner, {
            'DisplayName': 'foo',
            'ID': 'd41d8cd98f00b204e9800998ecf8427e'
        })

        buckets = payload['Buckets']
        self.assertEqual(len(buckets), 1)
        bucket = buckets[0]
        self.assertEqual(bucket['Name'], 'bar')

        metadata = payload['ResponseMetadata']
        self.assertEqual(metadata, {
            'HTTPHeaders': {},
            'HTTPStatusCode': 200,
            'RetryAttempts': 0
        })
Exemplo n.º 40
0
 def setUp(self):
     super(TestRDSPresignUrlInjection, self).setUp()
     self.client = self.session.create_client('rds', 'us-west-2')
     self.http_stubber = ClientHTTPStubber(self.client)
Exemplo n.º 41
0
 def __init__(self, client, operation_name, parameters):
     self._client = client
     self._operation_name = operation_name
     self._parameters = parameters
     self._http_stubber = ClientHTTPStubber(self._client)
Exemplo n.º 42
0
 def setUp(self):
     super(TestLex, self).setUp()
     self.region = 'us-west-2'
     self.client = self.session.create_client('lex-runtime', self.region)
     self.http_stubber = ClientHTTPStubber(self.client)
Exemplo n.º 43
0
 def setUp(self):
     super(TestMachineLearning, self).setUp()
     self.region = 'us-west-2'
     self.client = self.session.create_client(
         'machinelearning', self.region)
     self.http_stubber = ClientHTTPStubber(self.client)
Exemplo n.º 44
0
 def setUp(self):
     super(TestCloudsearchdomain, self).setUp()
     self.region = 'us-west-2'
     self.client = self.session.create_client(
         'cloudsearchdomain', self.region)
     self.http_stubber = ClientHTTPStubber(self.client)
Exemplo n.º 45
0
 def setUp(self):
     super(TestApiGateway, self).setUp()
     self.region = 'us-west-2'
     self.client = self.session.create_client(
         'apigateway', self.region)
     self.http_stubber = ClientHTTPStubber(self.client)