def get_token(): session = get_aws_session() sts_client = session.client("sts", region_name=REGION) print("caller identity ***####*************" + str(sts_client.get_caller_identity())) service_id = sts_client.meta.service_model.service_id print("service id ######" + service_id) signer = RequestSigner(service_id, session.region_name, 'sts', 'v4', session.get_credentials(), session.events) params = { 'method': 'GET', 'url': 'https://' + STS_END_POINT + '/?' + STS_ACTION, 'body': {}, 'headers': { EKS_HEADER: CLUSTER_NAME }, 'context': {} } signed_url = signer.generate_presigned_url(params, region_name=session.region_name, expires_in=EXPIRES_IN, operation_name='') print("signed url: " + signed_url) return ( EKS_PREFIX + base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8'))
def fetch_access_token_for_cluster(self, eks_cluster_name: str) -> str: session = self.get_session() service_id = self.conn.meta.service_model.service_id sts_url = ( f'https://sts.{session.region_name}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15' ) signer = RequestSigner( service_id=service_id, region_name=session.region_name, signing_name='sts', signature_version='v4', credentials=session.get_credentials(), event_emitter=session.events, ) request_params = { 'method': 'GET', 'url': sts_url, 'body': {}, 'headers': {'x-k8s-aws-id': eks_cluster_name}, 'context': {}, } signed_url = signer.generate_presigned_url( request_dict=request_params, region_name=session.region_name, expires_in=STS_TOKEN_EXPIRES_IN, operation_name='', ) base64_url = base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8') # remove any base64 encoding padding: return 'k8s-aws-v1.' + base64_url.rstrip("=")
def get_token(self): """ Return bearer token """ sess = self.__get_session() signer = RequestSigner('sts', sess.region_name, 'sts', 'v4', sess.get_credentials(), sess.events) params = { 'method': self.METHOD, 'url': 'https://' + self.STS_URL + '/?' + self.STS_ACTION, 'body': {}, 'headers': { self.EKS_HEADER: self.cluster_id }, 'context': {} } signed_url = signer.generate_presigned_url( params, region_name=sess.region_name, expires_in=self.EXPIRES, operation_name='') return (self.EKS_PREFIX + base64.urlsafe_b64encode( signed_url.encode('utf-8')).decode('utf-8'))
def get_auth_token(self): presign_expires = 60 sts_http_action = 'Action=GetCallerIdentity&Version=2011-06-15' sts_http_method = 'GET' eks_header = 'x-k8s-aws-id' eks_prefix = 'k8s-aws-v1.' if self.role_arn: session = NewIdentity(role_arn=self.role_arn).get_session() else: session = boto3.session.Session() client = session.client("sts",region_name="us-east-1") service_id = client.meta.service_model.service_id signer = RequestSigner( service_id, session.region_name, 'sts', 'v4', session.get_credentials(), session.events ) params = { 'method': sts_http_method, 'url': 'https://' + "sts.amazonaws.com" + '/?' + sts_http_action, 'body': {}, 'headers': { eks_header: self.cluster_name }, 'context': {} } signed_url = signer.generate_presigned_url( params, region_name="us-east-1", expires_in=presign_expires, operation_name = '' ) logger.debug("Pre-signed URL: {}".format(signed_url)) logger.info("Caller Identity {}".format(client.get_caller_identity())) # This \/ \/ rstrip wasted 3 hours until I looked at aws cli code. return ( eks_prefix + base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8').rstrip('=') )
def generate_aws_eks_bearer_token(cluster_name, challenge): """Function to generate the AWS EKS bearer Token Arguments: cluster_name {string} -- Cluster name for which the object is generated challenge {Object} -- Challenge Object Returns: {string} -- Generated bearer token """ challenge_pk = challenge.id aws_keys = get_aws_credentials_for_challenge(challenge_pk) session = boto3.Session( aws_access_key_id=aws_keys["AWS_ACCESS_KEY_ID"], aws_secret_access_key=aws_keys["AWS_SECRET_ACCESS_KEY"], ) region = aws_keys["AWS_REGION"] client = session.client("sts", region_name=region) service_id = client.meta.service_model.service_id signer = RequestSigner( service_id, region, "sts", "v4", session.get_credentials(), session.events, ) params = { "method": "GET", "url": "https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15" .format(region), "body": {}, "headers": { "x-k8s-aws-id": cluster_name }, "context": {}, } signed_url = signer.generate_presigned_url(params, region_name=region, expires_in=60, operation_name="") base64_url = base64.urlsafe_b64encode( signed_url.encode("utf-8")).decode("utf-8") # remove any base64 encoding padding bearer_token = "k8s-aws-v1." + re.sub(r"=*", "", base64_url) return bearer_token
def test_generate_presigned_url_fixes_s3_host(self): self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 's3', self.credentials, self.emitter) auth = mock.Mock() auth.REQUIRES_REGION = True request_dict = { 'headers': {}, 'url': 'https://s3.amazonaws.com/mybucket/myobject', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'s3-query': auth}): presigned_url = self.signer.generate_presigned_url( request_dict, expires_in=900) auth.assert_called_with( credentials=self.fixed_credentials, region_name='region_name', expires=900, service_name='signing_name') self.assertEqual(presigned_url, 'https://mybucket.s3.amazonaws.com/myobject')
def test_presigned_url_casing_changed_for_rds(self): operation_model = mock.Mock() operation_model.name = 'CopyDBSnapshot' credentials = Credentials('key', 'secret') event_emitter = HierarchicalEmitter() request_signer = RequestSigner( 'rds', 'us-east-1', 'rds', 'v4', credentials, event_emitter) request_dict = {} params = {'SourceRegion': 'us-west-2'} request_dict['body'] = params request_dict['url'] = 'https://rds.us-east-1.amazonaws.com' request_dict['method'] = 'POST' request_dict['headers'] = {} request_dict['context'] = {} handlers.inject_presigned_url_rds( params=request_dict, request_signer=request_signer, model=operation_model ) self.assertNotIn('PresignedUrl', params) self.assertIn('https://rds.us-west-2.amazonaws.com?', params['PreSignedUrl']) self.assertIn('X-Amz-Signature', params['PreSignedUrl'])
def test_no_credentials_case_is_forwarded_to_signer(self): # If no credentials are given to the RequestSigner, we should # forward that fact on to the Auth class and let them handle # the error (which they already do). self.credentials = None self.signer = RequestSigner(ServiceId('service_name'), 'region_name', 'signing_name', 'v4', self.credentials, self.emitter) auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): self.signer.get_auth_instance('service_name', 'region_name', 'v4') auth_cls.assert_called_with( service_name='service_name', region_name='region_name', credentials=None, )
def test_region_required_for_sigv4(self): self.signer = RequestSigner( 'service_name', None, 'signing_name', 'v4', self.credentials, self.emitter) with self.assertRaises(NoRegionError): self.signer.sign('operation_name', mock.Mock())
def get_client_args(self, service_model, region_name, is_secure, endpoint_url, verify, credentials, scoped_config, client_config, endpoint_bridge): final_args = self.compute_client_args( service_model, client_config, endpoint_bridge, region_name, endpoint_url, is_secure, scoped_config) service_name = final_args['service_name'] parameter_validation = final_args['parameter_validation'] endpoint_config = final_args['endpoint_config'] protocol = final_args['protocol'] config_kwargs = final_args['config_kwargs'] s3_config = final_args['s3_config'] partition = endpoint_config['metadata'].get('partition', None) socket_options = final_args['socket_options'] signing_region = endpoint_config['signing_region'] endpoint_region_name = endpoint_config['region_name'] if signing_region is None and endpoint_region_name is None: signing_region, endpoint_region_name = \ self._get_default_s3_region(service_name, endpoint_bridge) config_kwargs['region_name'] = endpoint_region_name event_emitter = copy.copy(self._event_emitter) signer = RequestSigner( service_model.service_id, signing_region, endpoint_config['signing_name'], endpoint_config['signature_version'], credentials, event_emitter ) config_kwargs['s3'] = s3_config new_config = Config(**config_kwargs) endpoint_creator = EndpointCreator(event_emitter) endpoint = endpoint_creator.create_endpoint( service_model, region_name=endpoint_region_name, endpoint_url=endpoint_config['endpoint_url'], verify=verify, response_parser_factory=self._response_parser_factory, max_pool_connections=new_config.max_pool_connections, proxies=new_config.proxies, timeout=(new_config.connect_timeout, new_config.read_timeout), socket_options=socket_options, client_cert=new_config.client_cert) serializer = botocore.serialize.create_serializer( protocol, parameter_validation) response_parser = botocore.parsers.create_parser(protocol) return { 'serializer': serializer, 'endpoint': endpoint, 'response_parser': response_parser, 'event_emitter': event_emitter, 'request_signer': signer, 'service_model': service_model, 'loader': self._loader, 'client_config': new_config, 'partition': partition, 'exceptions_factory': self._exceptions_factory }
def setUp(self): self.credentials = Credentials('key', 'secret') self.emitter = mock.Mock() self.emitter.emit_until_response.return_value = (None, None) self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'v4', self.credentials, self.emitter)
def get_client_args(self, service_model, region_name, is_secure, endpoint_url, verify, credentials, scoped_config, client_config, endpoint_bridge, http_session): # CUT AND PASTE FROM BOTOCORE final_args = self.compute_client_args(service_model, client_config, endpoint_bridge, region_name, endpoint_url, is_secure, scoped_config) service_name = final_args['service_name'] parameter_validation = final_args['parameter_validation'] endpoint_config = final_args['endpoint_config'] protocol = final_args['protocol'] config_kwargs = final_args['config_kwargs'] s3_config = final_args['s3_config'] partition = endpoint_config['metadata'].get('partition', None) event_emitter = copy.copy(self._event_emitter) signer = RequestSigner(service_name, endpoint_config['signing_region'], endpoint_config['signing_name'], endpoint_config['signature_version'], credentials, event_emitter) # Add any additional s3 configuration for client config_kwargs['s3'] = s3_config #self._conditionally_unregister_fix_s3_host(endpoint_url, event_emitter) # END OF CUT AND PASTE new_config = AsyncConfig(**config_kwargs) endpoint_creator = AsyncEndpointCreator(http_session, event_emitter) # CUT AND PASTE FROM BOTOCORE endpoint = endpoint_creator.create_endpoint( service_model, region_name=endpoint_config['region_name'], endpoint_url=endpoint_config['endpoint_url'], verify=verify, response_parser_factory=self._response_parser_factory, max_pool_connections=new_config.max_pool_connections, timeout=(new_config.connect_timeout, new_config.read_timeout)) serializer = botocore.serialize.create_serializer( protocol, parameter_validation) response_parser = botocore.parsers.create_parser(protocol) return { 'serializer': serializer, 'endpoint': endpoint, 'response_parser': response_parser, 'event_emitter': event_emitter, 'request_signer': signer, 'service_model': service_model, 'loader': self._loader, 'client_config': new_config, 'partition': partition }
def get_client_args(self, service_model, region_name, is_secure, endpoint_url, verify, credentials, scoped_config, client_config, endpoint_bridge): final_args = self.compute_client_args(service_model, client_config, endpoint_bridge, region_name, endpoint_url, is_secure, scoped_config) service_name = final_args['service_name'] parameter_validation = final_args['parameter_validation'] endpoint_config = final_args['endpoint_config'] protocol = final_args['protocol'] config_kwargs = final_args['config_kwargs'] s3_config = final_args['s3_config'] partition = endpoint_config['metadata'].get('partition', None) event_emitter = copy.copy(self._event_emitter) signer = RequestSigner(service_name, endpoint_config['signing_region'], endpoint_config['signing_name'], endpoint_config['signature_version'], credentials, event_emitter) config_kwargs['s3'] = s3_config if isinstance(client_config, AioConfig): connector_args = client_config.connector_args else: connector_args = None new_config = AioConfig(connector_args, **config_kwargs) endpoint_creator = AioEndpointCreator(event_emitter, self._loop) endpoint = endpoint_creator.create_endpoint( service_model, region_name=endpoint_config['region_name'], endpoint_url=endpoint_config['endpoint_url'], verify=verify, response_parser_factory=self._response_parser_factory, max_pool_connections=new_config.max_pool_connections, timeout=(new_config.connect_timeout, new_config.read_timeout), connector_args=new_config.connector_args) serializer = botocore.serialize.create_serializer( protocol, parameter_validation) response_parser = botocore.parsers.create_parser(protocol) return { 'serializer': serializer, 'endpoint': endpoint, 'response_parser': response_parser, 'event_emitter': event_emitter, 'request_signer': signer, 'service_model': service_model, 'loader': self._loader, 'client_config': new_config, 'partition': partition, 'exceptions_factory': self._exceptions_factory }
def sign_botocore(): request = AWSRequest( "POST", URL_STRING, data=json.dumps(PAYLOAD, separators=(",", ":")).encode("utf-8"), ) emitter = HierarchicalEmitter() RequestSigner( ServiceId(SERVICE_NAME), REGION, SERVICE_NAME, "v4", CREDENTIALS, emitter ).sign(ACTION, request)
def get_bearer_token(cluster, region): """Creates the authentication to token required by AWS IAM Authenticator. This is done by creating a base64 encoded string which represents a HTTP call to the STS GetCallerIdentity Query Request (https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html). The AWS IAM Authenticator decodes the base64 string and makes the request on behalf of the user. """ STS_TOKEN_EXPIRES_IN = 60 session = boto3.session.Session() client = session.client('sts', region_name=region) service_id = client.meta.service_model.service_id signer = RequestSigner( service_id, region, 'sts', 'v4', session.get_credentials(), session.events ) params = { 'method': 'GET', 'url': 'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'.format(region), 'body': {}, 'headers': { 'x-k8s-aws-id': cluster }, 'context': {} } signed_url = signer.generate_presigned_url( params, region_name=region, expires_in=STS_TOKEN_EXPIRES_IN, operation_name='' ) base64_url = base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8') # need to remove base64 encoding padding: # https://github.com/kubernetes-sigs/aws-iam-authenticator/issues/202 return 'k8s-aws-v1.' + re.sub(r'=*', '', base64_url)
def test_adds_md5_when_s3v4(self): credentials = Credentials('key', 'secret') request_signer = RequestSigner( 's3', 'us-east-1', 's3', 's3v4', credentials, mock.Mock()) request_dict = {'body': b'bar', 'url': 'https://s3.us-east-1.amazonaws.com', 'method': 'PUT', 'headers': {}} context = self.get_context({'payload_signing_enabled': False}) handlers.conditionally_calculate_md5( request_dict, request_signer=request_signer, context=context) self.assertTrue('Content-MD5' in request_dict['headers'])
def get_bearer_token(cluster, region): """Creates the authentication to token required by AWS IAM Authenticator. This is done by creating a base64 encoded string which represents a HTTP call to the STS GetCallerIdentity Query Request (https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html). The AWS IAM Authenticator decodes the base64 string and makes the request on behalf of the user. """ STS_TOKEN_EXPIRES_IN = 60 session = boto3.session.Session() client = session.client("sts", region_name=region) service_id = client.meta.service_model.service_id signer = RequestSigner(service_id, region, "sts", "v4", session.get_credentials(), session.events) params = { "method": "GET", "url": "https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15" .format(region), "body": {}, "headers": { "x-k8s-aws-id": cluster }, "context": {}, } signed_url = signer.generate_presigned_url(params, region_name=region, expires_in=STS_TOKEN_EXPIRES_IN, operation_name="") base64_url = base64.urlsafe_b64encode( signed_url.encode("utf-8")).decode("utf-8") # need to remove base64 encoding padding: # https://github.com/kubernetes-sigs/aws-iam-authenticator/issues/202 return "k8s-aws-v1." + re.sub(r"=*", "", base64_url)
def _get_presigned_url(self, cluster_name, role_arn): session = self._session_handler.get_session( self._region_name, role_arn ) if self._region_name is None: self._region_name = session.get_config_variable('region') loader = botocore.loaders.create_loader() data = loader.load_data("endpoints") endpoint_resolver = botocore.regions.EndpointResolver(data) endpoint = endpoint_resolver.construct_endpoint( AUTH_SERVICE, self._region_name ) signer = RequestSigner( ServiceId(AUTH_SERVICE), self._region_name, AUTH_SERVICE, AUTH_SIGNING_VERSION, session.get_credentials(), session.get_component('event_emitter') ) action_params='Action=' + AUTH_COMMAND + '&Version=' + AUTH_API_VERSION params = { 'method': 'GET', 'url': 'https://' + endpoint["hostname"] + '/?' + action_params, 'body': {}, 'headers': {CLUSTER_NAME_HEADER: cluster_name}, 'context': {} } url=signer.generate_presigned_url( params, region_name=endpoint["credentialScope"]["region"], operation_name='', expires_in=URL_TIMEOUT ) return url
def test_presigned_url_throws_unsupported_signature_error(self): request_dict = { 'headers': {}, 'url': 'https://s3.amazonaws.com/mybucket/myobject', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'foo', self.credentials, self.emitter) with self.assertRaises(UnsupportedSignatureVersionError): self.signer.generate_presigned_url( request_dict, operation_name='foo')
def test_no_credentials_case_is_forwarded_to_signer(self): # If no credentials are given to the RequestSigner, we should # forward that fact on to the Auth class and let them handle # the error (which they already do). self.credentials = None self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'v4', self.credentials, self.emitter) auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth = self.signer.get_auth_instance( 'service_name', 'region_name', 'v4') auth_cls.assert_called_with( service_name='service_name', region_name='region_name', credentials=None, )
def test_signer_with_refreshable_credentials_gets_credential_set(self): class FakeCredentials(Credentials): def get_frozen_credentials(self): return ReadOnlyCredentials('foo', 'bar', 'baz') self.credentials = FakeCredentials('a', 'b', 'c') self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'v4', self.credentials, self.emitter) auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth = self.signer.get_auth('service_name', 'region_name') self.assertEqual(auth, auth_cls.return_value) # Note we're called with 'foo', 'bar', 'baz', and *not* # 'a', 'b', 'c'. auth_cls.assert_called_with( credentials=ReadOnlyCredentials('foo', 'bar', 'baz'), service_name='service_name', region_name='region_name')
class TestSigner(BaseSignerTest): def test_region_name(self): self.assertEqual(self.signer.region_name, 'region_name') def test_signature_version(self): self.assertEqual(self.signer.signature_version, 'v4') def test_signing_name(self): self.assertEqual(self.signer.signing_name, 'signing_name') def test_region_required_for_sigv4(self): self.signer = RequestSigner( 'service_name', None, 'signing_name', 'v4', self.credentials, self.emitter) with self.assertRaises(NoRegionError): self.signer.sign('operation_name', mock.Mock()) def test_get_auth(self): auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth = self.signer.get_auth('service_name', 'region_name') self.assertEqual(auth, auth_cls.return_value) auth_cls.assert_called_with( credentials=self.fixed_credentials, service_name='service_name', region_name='region_name') def test_get_auth_signature_override(self): auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-custom': auth_cls}): auth = self.signer.get_auth( 'service_name', 'region_name', signature_version='v4-custom') self.assertEqual(auth, auth_cls.return_value) auth_cls.assert_called_with( credentials=self.fixed_credentials, service_name='service_name', region_name='region_name') def test_get_auth_bad_override(self): with self.assertRaises(UnknownSignatureVersionError): self.signer.get_auth('service_name', 'region_name', signature_version='bad') def test_emits_choose_signer(self): request = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': mock.Mock()}): self.signer.sign('operation_name', request) self.emitter.emit_until_response.assert_called_with( 'choose-signer.service_name.operation_name', signing_name='signing_name', region_name='region_name', signature_version='v4') def test_choose_signer_override(self): request = mock.Mock() auth = mock.Mock() auth.REQUIRES_REGION = False self.emitter.emit_until_response.return_value = (None, 'custom') with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'custom': auth}): self.signer.sign('operation_name', request) auth.assert_called_with(credentials=self.fixed_credentials) auth.return_value.add_auth.assert_called_with(request) def test_emits_before_sign(self): request = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': mock.Mock()}): self.signer.sign('operation_name', request) self.emitter.emit.assert_called_with( 'before-sign.service_name.operation_name', request=mock.ANY, signing_name='signing_name', region_name='region_name', signature_version='v4', request_signer=self.signer) def test_disable_signing(self): # Returning botocore.UNSIGNED from choose-signer disables signing! request = mock.Mock() auth = mock.Mock() self.emitter.emit_until_response.return_value = (None, botocore.UNSIGNED) with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth}): self.signer.sign('operation_name', request) auth.assert_not_called() def test_generate_url_emits_choose_signer(self): request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': mock.Mock()}): self.signer.generate_presigned_url(request_dict, 'operation_name') self.emitter.emit_until_response.assert_called_with( 'choose-signer.service_name.operation_name', signing_name='signing_name', region_name='region_name', signature_version='v4-query') def test_generate_url_choose_signer_override(self): request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } auth = mock.Mock() auth.REQUIRES_REGION = False self.emitter.emit_until_response.return_value = (None, 'custom') auth_types_map = {'custom': mock.Mock(), 'custom-query': auth} with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types_map): self.signer.generate_presigned_url(request_dict, 'operation_name') auth.assert_called_with(credentials=self.fixed_credentials, expires=3600) def test_generate_url_unsigned(self): request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } self.emitter.emit_until_response.return_value = ( None, botocore.UNSIGNED) url = self.signer.generate_presigned_url( request_dict, 'operation_name') self.assertEqual(url, 'https://foo.com') def test_generate_presigned_url(self): auth = mock.Mock() auth.REQUIRES_REGION = True request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-query': auth}): presigned_url = self.signer.generate_presigned_url( request_dict, operation_name='operation_name') auth.assert_called_with( credentials=self.fixed_credentials, region_name='region_name', service_name='signing_name', expires=3600) self.assertEqual(presigned_url, 'https://foo.com') def test_generate_presigned_url_with_region_override(self): auth = mock.Mock() auth.REQUIRES_REGION = True request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-query': auth}): presigned_url = self.signer.generate_presigned_url( request_dict, operation_name='operation_name', region_name='us-west-2') auth.assert_called_with( credentials=self.fixed_credentials, region_name='us-west-2', service_name='signing_name', expires=3600) self.assertEqual(presigned_url, 'https://foo.com') def test_generate_presigned_url_with_exipres_in(self): auth = mock.Mock() auth.REQUIRES_REGION = True request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-query': auth}): presigned_url = self.signer.generate_presigned_url( request_dict, operation_name='operation_name', expires_in=900) auth.assert_called_with( credentials=self.fixed_credentials, region_name='region_name', expires=900, service_name='signing_name') self.assertEqual(presigned_url, 'https://foo.com') def test_presigned_url_throws_unsupported_signature_error(self): request_dict = { 'headers': {}, 'url': 'https://s3.amazonaws.com/mybucket/myobject', 'body': b'', 'url_path': '/', 'method': 'GET', 'context': {} } self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'foo', self.credentials, self.emitter) with self.assertRaises(UnsupportedSignatureVersionError): self.signer.generate_presigned_url( request_dict, operation_name='foo') def test_signer_with_refreshable_credentials_gets_credential_set(self): class FakeCredentials(Credentials): def get_frozen_credentials(self): return ReadOnlyCredentials('foo', 'bar', 'baz') self.credentials = FakeCredentials('a', 'b', 'c') self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'v4', self.credentials, self.emitter) auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth = self.signer.get_auth('service_name', 'region_name') self.assertEqual(auth, auth_cls.return_value) # Note we're called with 'foo', 'bar', 'baz', and *not* # 'a', 'b', 'c'. auth_cls.assert_called_with( credentials=ReadOnlyCredentials('foo', 'bar', 'baz'), service_name='service_name', region_name='region_name') def test_no_credentials_case_is_forwarded_to_signer(self): # If no credentials are given to the RequestSigner, we should # forward that fact on to the Auth class and let them handle # the error (which they already do). self.credentials = None self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'v4', self.credentials, self.emitter) auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth = self.signer.get_auth_instance( 'service_name', 'region_name', 'v4') auth_cls.assert_called_with( service_name='service_name', region_name='region_name', credentials=None, ) def test_sign_with_signing_type_standard(self): auth = mock.Mock() post_auth = mock.Mock() query_auth = mock.Mock() request = mock.Mock() auth_types = { 'v4-presign-post': post_auth, 'v4-query': query_auth, 'v4': auth } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types): self.signer.sign('operation_name', request, signing_type='standard') self.assertFalse(post_auth.called) self.assertFalse(query_auth.called) auth.assert_called_with( credentials=ReadOnlyCredentials('key', 'secret', None), service_name='signing_name', region_name='region_name' ) def test_sign_with_signing_type_presign_url(self): auth = mock.Mock() post_auth = mock.Mock() query_auth = mock.Mock() request = mock.Mock() auth_types = { 'v4-presign-post': post_auth, 'v4-query': query_auth, 'v4': auth } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types): self.signer.sign('operation_name', request, signing_type='presign-url') self.assertFalse(post_auth.called) self.assertFalse(auth.called) query_auth.assert_called_with( credentials=ReadOnlyCredentials('key', 'secret', None), service_name='signing_name', region_name='region_name' ) def test_sign_with_signing_type_presign_post(self): auth = mock.Mock() post_auth = mock.Mock() query_auth = mock.Mock() request = mock.Mock() auth_types = { 'v4-presign-post': post_auth, 'v4-query': query_auth, 'v4': auth } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types): self.signer.sign('operation_name', request, signing_type='presign-post') self.assertFalse(auth.called) self.assertFalse(query_auth.called) post_auth.assert_called_with( credentials=ReadOnlyCredentials('key', 'secret', None), service_name='signing_name', region_name='region_name' ) def test_sign_with_region_name(self): request = mock.Mock() auth = mock.Mock() auth_types = { 'v4': auth } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types): self.signer.sign('operation_name', request, region_name='foo') auth.assert_called_with( credentials=ReadOnlyCredentials('key', 'secret', None), service_name='signing_name', region_name='foo' ) def test_sign_with_expires_in(self): request = mock.Mock() auth = mock.Mock() auth_types = { 'v4': auth } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types): self.signer.sign('operation_name', request, expires_in=2) auth.assert_called_with( credentials=ReadOnlyCredentials('key', 'secret', None), service_name='signing_name', region_name='region_name', expires=2 ) def test_unknown_signer_raises_unknown_on_standard(self): request = mock.Mock() auth = mock.Mock() auth_types = { 'v4': auth } self.emitter.emit_until_response.return_value = (None, 'custom') with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types): with self.assertRaises(UnknownSignatureVersionError): self.signer.sign('operation_name', request, signing_type='standard') def test_unknown_signer_raises_unsupported_when_not_standard(self): request = mock.Mock() auth = mock.Mock() auth_types = { 'v4': auth } self.emitter.emit_until_response.return_value = (None, 'custom') with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types): with self.assertRaises(UnsupportedSignatureVersionError): self.signer.sign('operation_name', request, signing_type='presign-url') with self.assertRaises(UnsupportedSignatureVersionError): self.signer.sign('operation_name', request, signing_type='presign-post')
class TestSigner(BaseSignerTest): def test_region_name(self): self.assertEqual(self.signer.region_name, 'region_name') def test_signature_version(self): self.assertEqual(self.signer.signature_version, 'v4') def test_signing_name(self): self.assertEqual(self.signer.signing_name, 'signing_name') def test_region_required_for_sigv4(self): self.signer = RequestSigner( 'service_name', None, 'signing_name', 'v4', self.credentials, self.emitter) with self.assertRaises(NoRegionError): self.signer.sign('operation_name', mock.Mock()) def test_get_auth(self): auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth = self.signer.get_auth('service_name', 'region_name') self.assertEqual(auth, auth_cls.return_value) auth_cls.assert_called_with( credentials=self.credentials, service_name='service_name', region_name='region_name') def test_get_auth_cached(self): def side_effect(*args, **kwargs): return mock.Mock() auth_cls = mock.Mock(side_effect=side_effect) with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth1 = self.signer.get_auth('service_name', 'region_name') auth2 = self.signer.get_auth('service_name', 'region_name') self.assertEqual(auth1, auth2) def test_get_auth_cached_expires(self): def side_effect(*args, **kwargs): return mock.Mock() auth_cls = mock.Mock(side_effect=side_effect) with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth1 = self.signer.get_auth('service_name', 'region_name', expires=60) auth2 = self.signer.get_auth('service_name', 'region_name', expires=90) self.assertNotEqual(auth1, auth2) def test_get_auth_signature_override(self): auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-custom': auth_cls}): auth = self.signer.get_auth( 'service_name', 'region_name', signature_version='v4-custom') self.assertEqual(auth, auth_cls.return_value) auth_cls.assert_called_with( credentials=self.credentials, service_name='service_name', region_name='region_name') def test_get_auth_bad_override(self): with self.assertRaises(UnknownSignatureVersionError): self.signer.get_auth('service_name', 'region_name', signature_version='bad') def test_emits_choose_signer(self): request = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': mock.Mock()}): self.signer.sign('operation_name', request) self.emitter.emit_until_response.assert_called_with( 'choose-signer.service_name.operation_name', signing_name='signing_name', region_name='region_name', signature_version='v4') def test_choose_signer_override(self): request = mock.Mock() auth = mock.Mock() auth.REQUIRES_REGION = False self.emitter.emit_until_response.return_value = (None, 'custom') with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'custom': auth}): self.signer.sign('operation_name', request) auth.assert_called_with(credentials=self.credentials) auth.return_value.add_auth.assert_called_with(request=request) def test_emits_before_sign(self): request = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': mock.Mock()}): self.signer.sign('operation_name', request) self.emitter.emit.assert_called_with( 'before-sign.service_name.operation_name', request=mock.ANY, signing_name='signing_name', region_name='region_name', signature_version='v4', request_signer=self.signer) def test_disable_signing(self): # Returning botocore.UNSIGNED from choose-signer disables signing! request = mock.Mock() auth = mock.Mock() self.emitter.emit_until_response.return_value = (None, botocore.UNSIGNED) with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth}): self.signer.sign('operation_name', request) auth.assert_not_called() def test_generate_presigned_url(self): auth = mock.Mock() auth.REQUIRES_REGION = True request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET' } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-query': auth}): presigned_url = self.signer.generate_presigned_url(request_dict) auth.assert_called_with( credentials=self.credentials, region_name='region_name', service_name='signing_name', expires=3600) self.assertEqual(presigned_url, 'https://foo.com') def test_generate_presigned_url_with_region_override(self): auth = mock.Mock() auth.REQUIRES_REGION = True request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET' } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-query': auth}): presigned_url = self.signer.generate_presigned_url( request_dict, region_name='us-west-2') auth.assert_called_with( credentials=self.credentials, region_name='us-west-2', service_name='signing_name', expires=3600) self.assertEqual(presigned_url, 'https://foo.com') def test_generate_presigned_url_with_exipres_in(self): auth = mock.Mock() auth.REQUIRES_REGION = True request_dict = { 'headers': {}, 'url': 'https://foo.com', 'body': b'', 'url_path': '/', 'method': 'GET' } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-query': auth}): presigned_url = self.signer.generate_presigned_url( request_dict, expires_in=900) auth.assert_called_with( credentials=self.credentials, region_name='region_name', expires=900, service_name='signing_name') self.assertEqual(presigned_url, 'https://foo.com') def test_generate_presigned_url_fixes_s3_host(self): self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 's3', self.credentials, self.emitter) auth = mock.Mock() auth.REQUIRES_REGION = True request_dict = { 'headers': {}, 'url': 'https://s3.amazonaws.com/mybucket/myobject', 'body': b'', 'url_path': '/', 'method': 'GET' } with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'s3-query': auth}): presigned_url = self.signer.generate_presigned_url( request_dict, expires_in=900) auth.assert_called_with( credentials=self.credentials, region_name='region_name', expires=900, service_name='signing_name') self.assertEqual(presigned_url, 'https://mybucket.s3.amazonaws.com/myobject') def test_presigned_url_throws_unsupported_signature_error(self): self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'foo', self.credentials, self.emitter) with self.assertRaises(UnsupportedSignatureVersionError): self.signer.generate_presigned_url({})
def test_presigned_url_throws_unsupported_signature_error(self): self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'foo', self.credentials, self.emitter) with self.assertRaises(UnsupportedSignatureVersionError): self.signer.generate_presigned_url({})
class TestSigner(unittest.TestCase): def setUp(self): self.credentials = Credentials('key', 'secret') self.emitter = mock.Mock() self.emitter.emit_until_response.return_value = (None, None) self.signer = RequestSigner( 'service_name', 'region_name', 'signing_name', 'v4', self.credentials, self.emitter) def test_region_required_for_sigv4(self): self.signer = RequestSigner( 'service_name', None, 'signing_name', 'v4', self.credentials, self.emitter) with self.assertRaises(NoRegionError): self.signer.sign('operation_name', mock.Mock()) def test_get_auth(self): auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth = self.signer.get_auth('service_name', 'region_name') self.assertEqual(auth, auth_cls.return_value) auth_cls.assert_called_with( credentials=self.credentials, service_name='service_name', region_name='region_name') def test_get_auth_cached(self): auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth_cls}): auth1 = self.signer.get_auth('service_name', 'region_name') auth2 = self.signer.get_auth('service_name', 'region_name') self.assertEqual(auth1, auth2) def test_get_auth_signature_override(self): auth_cls = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4-custom': auth_cls}): auth = self.signer.get_auth( 'service_name', 'region_name', signature_version='v4-custom') self.assertEqual(auth, auth_cls.return_value) auth_cls.assert_called_with( credentials=self.credentials, service_name='service_name', region_name='region_name') def test_get_auth_bad_override(self): with self.assertRaises(UnknownSignatureVersionError): self.signer.get_auth('service_name', 'region_name', signature_version='bad') def test_emits_choose_signer(self): request = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': mock.Mock()}): self.signer.sign('operation_name', request) self.emitter.emit_until_response.assert_called_with( 'choose-signer.service_name.operation_name', signing_name='signing_name', region_name='region_name', signature_version='v4') def test_choose_signer_override(self): request = mock.Mock() auth = mock.Mock() auth.REQUIRES_REGION = False self.emitter.emit_until_response.return_value = (None, 'custom') with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'custom': auth}): self.signer.sign('operation_name', request) auth.assert_called_with(credentials=self.credentials) auth.return_value.add_auth.assert_called_with(request=request) def test_emits_before_sign(self): request = mock.Mock() with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': mock.Mock()}): self.signer.sign('operation_name', request) self.emitter.emit.assert_called_with( 'before-sign.service_name.operation_name', request=mock.ANY, signing_name='signing_name', region_name='region_name', signature_version='v4', request_signer=self.signer) def test_disable_signing(self): # Returning botocore.UNSIGNED from choose-signer disables signing! request = mock.Mock() auth = mock.Mock() self.emitter.emit_until_response.return_value = (None, botocore.UNSIGNED) with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, {'v4': auth}): self.signer.sign('operation_name', request) auth.assert_not_called()