diff --git a/integration/combination/test_function_with_http_api.py b/integration/combination/test_function_with_http_api.py index db0bd4a89..fff6a19c5 100644 --- a/integration/combination/test_function_with_http_api.py +++ b/integration/combination/test_function_with_http_api.py @@ -18,9 +18,9 @@ def test_function_with_http_api(self): stack_outputs = self.get_stack_outputs() base_url = stack_outputs["ApiUrl"] - self.verify_get_request_response(base_url + "some/path", 200) - self.verify_get_request_response(base_url + "something", 404) - self.verify_get_request_response(base_url + "another/endpoint", 404) + self.verify_get_request_response_sigv4(base_url + "some/path", 200) + self.verify_get_request_response_sigv4(base_url + "something", 404) + self.verify_get_request_response_sigv4(base_url + "another/endpoint", 404) def test_function_with_http_api_default_path(self): self.create_and_verify_stack("combination/function_with_http_api_default_path") @@ -28,5 +28,5 @@ def test_function_with_http_api_default_path(self): stack_outputs = self.get_stack_outputs() base_url = stack_outputs["ApiUrl"] # The $default route catches requests that don't explicitly match other routes - self.verify_get_request_response(base_url, 200) - self.verify_get_request_response(base_url + "something", 200) + self.verify_get_request_response_sigv4(base_url, 200) + self.verify_get_request_response_sigv4(base_url + "something", 200) diff --git a/integration/combination/test_function_with_implicit_http_api.py b/integration/combination/test_function_with_implicit_http_api.py index 6ccec0c09..f3d278423 100644 --- a/integration/combination/test_function_with_implicit_http_api.py +++ b/integration/combination/test_function_with_implicit_http_api.py @@ -12,6 +12,6 @@ def test_function_with_implicit_api(self): stack_outputs = self.get_stack_outputs() base_url = stack_outputs["ApiUrl"] - self.verify_get_request_response(base_url, 200) - self.verify_get_request_response(base_url + "something", 200) - self.verify_get_request_response(base_url + "another/endpoint", 200) + self.verify_get_request_response_sigv4(base_url, 200) + self.verify_get_request_response_sigv4(base_url + "something", 200) + self.verify_get_request_response_sigv4(base_url + "another/endpoint", 200) diff --git a/integration/helpers/base_test.py b/integration/helpers/base_test.py index b2c9fcf2f..dd284c1cb 100644 --- a/integration/helpers/base_test.py +++ b/integration/helpers/base_test.py @@ -4,11 +4,14 @@ import shutil from pathlib import Path from unittest.case import TestCase +from urllib.parse import urlparse import boto3 import botocore import pytest import requests +from botocore.auth import SigV4Auth +from botocore.awsrequest import AWSRequest from samtranslator.translator.arn_generator import ArnGenerator from samtranslator.yaml_helper import yaml_parse from tenacity import ( @@ -538,6 +541,25 @@ def verify_get_request_response(self, url, expected_status_code, headers=None): ) return response + @retry( + stop=stop_after_attempt(6), + wait=wait_exponential(multiplier=1, min=16, max=64) + wait_random(0, 1), + retry=retry_if_exception_type(StatusCodeError), + after=after_log(LOG, logging.WARNING), + reraise=True, + ) + def verify_get_request_response_sigv4(self, url, expected_status_code, headers=None): + """ + Verify if a SigV4-signed get request to a certain url returns the expected status code. + Use this for APIs with IAM authorization. + """ + response = self.do_get_request_with_sigv4(url, headers) + if response.status_code != expected_status_code: + raise StatusCodeError( + f"SigV4 request to {url} failed with status: {response.status_code}, expected status: {expected_status_code}" + ) + return response + @retry( stop=stop_after_attempt(6), wait=wait_exponential(multiplier=1, min=16, max=64) + wait_random(0, 1), @@ -581,6 +603,22 @@ def verify_post_request(self, url: str, body_obj, expected_status_code: int, hea ) return response + @retry( + stop=stop_after_attempt(6), + wait=wait_exponential(multiplier=1, min=16, max=64) + wait_random(0, 1), + retry=retry_if_exception_type(StatusCodeError), + after=after_log(LOG, logging.WARNING), + reraise=True, + ) + def verify_post_request_sigv4(self, url: str, body_obj, expected_status_code: int, headers=None): + """Return response to SigV4-signed POST request and verify matches expected status code.""" + response = self.do_post_request_with_sigv4(url, body_obj, headers) + if response.status_code != expected_status_code: + raise StatusCodeError( + f"SigV4 POST request to {url} failed with status: {response.status_code}, expected status: {expected_status_code}" + ) + return response + def get_default_test_template_parameters(self): """ get the default template parameters @@ -636,6 +674,29 @@ def do_get_request_with_logging(self, url, headers=None): ) return response + def do_get_request_with_sigv4(self, url, headers=None): + """ + Perform a SigV4-signed GET request to an APIGW endpoint with IAM auth. + """ + parsed = urlparse(url) + request_headers = {"host": parsed.hostname} + if headers: + request_headers.update(headers) + + aws_request = AWSRequest(method="GET", url=url, headers=request_headers) + session = botocore.session.Session() + credentials = session.get_credentials().get_frozen_credentials() + SigV4Auth(credentials, "execute-api", self.my_region).add_auth(aws_request) + + response = requests.get(url, headers=dict(aws_request.headers)) + amazon_headers = RequestUtils(response).get_amazon_headers() + if self.internal: + REQUEST_LOGGER.info( + "SigV4 request made to " + url, + extra={"test": self.testcase, "status": response.status_code, "headers": amazon_headers}, + ) + return response + def do_options_request_with_logging(self, url, headers=None): """ Perform a options request to an APIGW endpoint and log relevant info @@ -669,3 +730,25 @@ def do_post_request_with_logging(self, url: str, body_obj, requestHeaders=None): extra={"test": self.testcase, "status": response.status_code, "headers": amazon_headers}, ) return response + + def do_post_request_with_sigv4(self, url: str, body_obj, headers=None): + """Perform a SigV4-signed POST request to an APIGW endpoint with IAM auth.""" + parsed = urlparse(url) + body = json.dumps(body_obj) + request_headers = {"host": parsed.hostname, "content-type": "application/json"} + if headers: + request_headers.update(headers) + + aws_request = AWSRequest(method="POST", url=url, headers=request_headers, data=body) + session = botocore.session.Session() + credentials = session.get_credentials().get_frozen_credentials() + SigV4Auth(credentials, "execute-api", self.my_region).add_auth(aws_request) + + response = requests.post(url, data=body, headers=dict(aws_request.headers)) + amazon_headers = RequestUtils(response).get_amazon_headers() + if self.internal: + REQUEST_LOGGER.info( + "SigV4 POST request made to " + url, + extra={"test": self.testcase, "status": response.status_code, "headers": amazon_headers}, + ) + return response diff --git a/integration/resources/templates/combination/api_with_binary_media_types.yaml b/integration/resources/templates/combination/api_with_binary_media_types.yaml index 9d9dc9279..793c0b13b 100644 --- a/integration/resources/templates/combination/api_with_binary_media_types.yaml +++ b/integration/resources/templates/combination/api_with_binary_media_types.yaml @@ -17,6 +17,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionUri: ${definitionuri} BinaryMediaTypes: diff --git a/integration/resources/templates/combination/api_with_binary_media_types_with_definition_body.yaml b/integration/resources/templates/combination/api_with_binary_media_types_with_definition_body.yaml index 2f2bc155a..fb88169c5 100644 --- a/integration/resources/templates/combination/api_with_binary_media_types_with_definition_body.yaml +++ b/integration/resources/templates/combination/api_with_binary_media_types_with_definition_body.yaml @@ -22,6 +22,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionBody: # Simple HTTP Proxy API diff --git a/integration/resources/templates/combination/api_with_binary_media_types_with_definition_body_openapi.yaml b/integration/resources/templates/combination/api_with_binary_media_types_with_definition_body_openapi.yaml index 0b2348d8b..2cd2d0d38 100644 --- a/integration/resources/templates/combination/api_with_binary_media_types_with_definition_body_openapi.yaml +++ b/integration/resources/templates/combination/api_with_binary_media_types_with_definition_body_openapi.yaml @@ -26,6 +26,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionBody: # Simple HTTP Proxy API diff --git a/integration/resources/templates/combination/api_with_custom_domains_edge.yaml b/integration/resources/templates/combination/api_with_custom_domains_edge.yaml index 31dfee115..93db88c75 100644 --- a/integration/resources/templates/combination/api_with_custom_domains_edge.yaml +++ b/integration/resources/templates/combination/api_with_custom_domains_edge.yaml @@ -32,6 +32,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM OpenApiVersion: 3.0.1 StageName: Prod Domain: diff --git a/integration/resources/templates/combination/api_with_disable_execute_api_endpoint.yaml b/integration/resources/templates/combination/api_with_disable_execute_api_endpoint.yaml index 506934eb1..eb2a07020 100644 --- a/integration/resources/templates/combination/api_with_disable_execute_api_endpoint.yaml +++ b/integration/resources/templates/combination/api_with_disable_execute_api_endpoint.yaml @@ -12,6 +12,8 @@ Resources: RestApiGateway: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DisableExecuteApiEndpoint: Ref: DisableExecuteApiEndpointValue diff --git a/integration/resources/templates/combination/api_with_disable_execute_api_endpoint_openapi_3.yaml b/integration/resources/templates/combination/api_with_disable_execute_api_endpoint_openapi_3.yaml index 801bea360..a44b574cc 100644 --- a/integration/resources/templates/combination/api_with_disable_execute_api_endpoint_openapi_3.yaml +++ b/integration/resources/templates/combination/api_with_disable_execute_api_endpoint_openapi_3.yaml @@ -12,6 +12,8 @@ Resources: RestApiGateway: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod OpenApiVersion: 3.0 DisableExecuteApiEndpoint: diff --git a/integration/resources/templates/combination/api_with_endpoint_configuration.yaml b/integration/resources/templates/combination/api_with_endpoint_configuration.yaml index 5741b31c3..765a8f27e 100644 --- a/integration/resources/templates/combination/api_with_endpoint_configuration.yaml +++ b/integration/resources/templates/combination/api_with_endpoint_configuration.yaml @@ -13,6 +13,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod EndpointConfiguration: {Ref: Config} DefinitionUri: ${definitionuri} diff --git a/integration/resources/templates/combination/api_with_endpoint_configuration_dict.yaml b/integration/resources/templates/combination/api_with_endpoint_configuration_dict.yaml index 9628eb0e1..bda5cf888 100644 --- a/integration/resources/templates/combination/api_with_endpoint_configuration_dict.yaml +++ b/integration/resources/templates/combination/api_with_endpoint_configuration_dict.yaml @@ -10,6 +10,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod EndpointConfiguration: Type: REGIONAL diff --git a/integration/resources/templates/combination/api_with_fail_on_warnings.yaml b/integration/resources/templates/combination/api_with_fail_on_warnings.yaml index 40c2bc9ae..73b3f69bf 100644 --- a/integration/resources/templates/combination/api_with_fail_on_warnings.yaml +++ b/integration/resources/templates/combination/api_with_fail_on_warnings.yaml @@ -11,6 +11,8 @@ Resources: RestApiGateway: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod FailOnWarnings: Ref: FailOnWarningsValue diff --git a/integration/resources/templates/combination/api_with_method_settings.yaml b/integration/resources/templates/combination/api_with_method_settings.yaml index 95d72c2a6..12d66499d 100644 --- a/integration/resources/templates/combination/api_with_method_settings.yaml +++ b/integration/resources/templates/combination/api_with_method_settings.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionUri: ${definitionuri} MethodSettings: [{LoggingLevel: INFO, MetricsEnabled: true, DataTraceEnabled: true, diff --git a/integration/resources/templates/combination/api_with_request_models.yaml b/integration/resources/templates/combination/api_with_request_models.yaml index 56fe7bfce..20856cfb1 100644 --- a/integration/resources/templates/combination/api_with_request_models.yaml +++ b/integration/resources/templates/combination/api_with_request_models.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod Models: User: diff --git a/integration/resources/templates/combination/api_with_request_models_openapi.yaml b/integration/resources/templates/combination/api_with_request_models_openapi.yaml index 77486926d..a773cf231 100644 --- a/integration/resources/templates/combination/api_with_request_models_openapi.yaml +++ b/integration/resources/templates/combination/api_with_request_models_openapi.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM OpenApiVersion: 3.0.1 StageName: Prod Models: diff --git a/integration/resources/templates/combination/api_with_resource_refs.yaml b/integration/resources/templates/combination/api_with_resource_refs.yaml index 1dc292af5..490f815c1 100644 --- a/integration/resources/templates/combination/api_with_resource_refs.yaml +++ b/integration/resources/templates/combination/api_with_resource_refs.yaml @@ -8,6 +8,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionUri: ${definitionuri} diff --git a/integration/resources/templates/combination/function_with_alias_and_event_sources.yaml b/integration/resources/templates/combination/function_with_alias_and_event_sources.yaml index ea6846439..8e396430d 100644 --- a/integration/resources/templates/combination/function_with_alias_and_event_sources.yaml +++ b/integration/resources/templates/combination/function_with_alias_and_event_sources.yaml @@ -86,6 +86,8 @@ Resources: ExistingRestApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Dev DefinitionUri: ${definitionuri} diff --git a/integration/resources/templates/combination/function_with_api.yaml b/integration/resources/templates/combination/function_with_api.yaml index 2166721b6..548667cfe 100644 --- a/integration/resources/templates/combination/function_with_api.yaml +++ b/integration/resources/templates/combination/function_with_api.yaml @@ -8,6 +8,8 @@ Resources: ExistingRestApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Dev DefinitionUri: ${definitionuri} diff --git a/integration/resources/templates/combination/function_with_http_api.yaml b/integration/resources/templates/combination/function_with_http_api.yaml index 0911ddcc9..07541cbea 100644 --- a/integration/resources/templates/combination/function_with_http_api.yaml +++ b/integration/resources/templates/combination/function_with_http_api.yaml @@ -20,6 +20,9 @@ Resources: MyApi: Type: AWS::Serverless::HttpApi Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM DefinitionBody: info: version: '1.0' diff --git a/integration/resources/templates/combination/function_with_http_api_default_path.yaml b/integration/resources/templates/combination/function_with_http_api_default_path.yaml index bb3234377..d7d27f79b 100644 --- a/integration/resources/templates/combination/function_with_http_api_default_path.yaml +++ b/integration/resources/templates/combination/function_with_http_api_default_path.yaml @@ -20,6 +20,9 @@ Resources: MyApi: Type: AWS::Serverless::HttpApi Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM DefinitionBody: info: version: '1.0' diff --git a/integration/resources/templates/combination/function_with_implicit_http_api.yaml b/integration/resources/templates/combination/function_with_implicit_http_api.yaml index 441217886..8ea3d466f 100644 --- a/integration/resources/templates/combination/function_with_implicit_http_api.yaml +++ b/integration/resources/templates/combination/function_with_implicit_http_api.yaml @@ -1,3 +1,9 @@ +Globals: + HttpApi: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM + Resources: MyLambdaFunction: diff --git a/integration/resources/templates/combination/http_api_with_custom_domains_regional.yaml b/integration/resources/templates/combination/http_api_with_custom_domains_regional.yaml index 72b033eff..d42ebfe0d 100644 --- a/integration/resources/templates/combination/http_api_with_custom_domains_regional.yaml +++ b/integration/resources/templates/combination/http_api_with_custom_domains_regional.yaml @@ -57,6 +57,9 @@ Resources: MyApi: Type: AWS::Serverless::HttpApi Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM StageName: Prod Metadata: SamTransformTest: true diff --git a/integration/resources/templates/combination/http_api_with_custom_domains_regional_ownership_verification.yaml b/integration/resources/templates/combination/http_api_with_custom_domains_regional_ownership_verification.yaml index 24ba30da3..a7f4a9912 100644 --- a/integration/resources/templates/combination/http_api_with_custom_domains_regional_ownership_verification.yaml +++ b/integration/resources/templates/combination/http_api_with_custom_domains_regional_ownership_verification.yaml @@ -61,6 +61,9 @@ Resources: MyApi: Type: AWS::Serverless::HttpApi Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM StageName: Prod Metadata: SamTransformTest: true diff --git a/integration/resources/templates/combination/http_api_with_disable_execute_api_endpoint_false.yaml b/integration/resources/templates/combination/http_api_with_disable_execute_api_endpoint_false.yaml index 451321a5e..6e97dd5d0 100644 --- a/integration/resources/templates/combination/http_api_with_disable_execute_api_endpoint_false.yaml +++ b/integration/resources/templates/combination/http_api_with_disable_execute_api_endpoint_false.yaml @@ -30,6 +30,9 @@ Resources: MyApi: Type: AWS::Serverless::HttpApi Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM DisableExecuteApiEndpoint: false StageName: Prod Outputs: diff --git a/integration/resources/templates/combination/http_api_with_disable_execute_api_endpoint_true.yaml b/integration/resources/templates/combination/http_api_with_disable_execute_api_endpoint_true.yaml index d461b21e7..ea288c88f 100644 --- a/integration/resources/templates/combination/http_api_with_disable_execute_api_endpoint_true.yaml +++ b/integration/resources/templates/combination/http_api_with_disable_execute_api_endpoint_true.yaml @@ -30,6 +30,9 @@ Resources: MyApi: Type: AWS::Serverless::HttpApi Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM DisableExecuteApiEndpoint: true StageName: Prod diff --git a/integration/resources/templates/combination/http_api_with_fail_on_warnings_and_default_stage_name.yaml b/integration/resources/templates/combination/http_api_with_fail_on_warnings_and_default_stage_name.yaml index d54723d42..075a4534e 100644 --- a/integration/resources/templates/combination/http_api_with_fail_on_warnings_and_default_stage_name.yaml +++ b/integration/resources/templates/combination/http_api_with_fail_on_warnings_and_default_stage_name.yaml @@ -7,6 +7,9 @@ Resources: AppApi: Type: AWS::Serverless::HttpApi Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM FailOnWarnings: !Ref FailOnWarningsValue StageName: $default AppFunction: diff --git a/integration/resources/templates/combination/intrinsics_code_definition_uri.yaml b/integration/resources/templates/combination/intrinsics_code_definition_uri.yaml index 2ce724226..fc7e8f61d 100644 --- a/integration/resources/templates/combination/intrinsics_code_definition_uri.yaml +++ b/integration/resources/templates/combination/intrinsics_code_definition_uri.yaml @@ -30,6 +30,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: FancyName DefinitionUri: Bucket: diff --git a/integration/resources/templates/combination/intrinsics_serverless_api.yaml b/integration/resources/templates/combination/intrinsics_serverless_api.yaml index d7aa06c78..4d0caa4c9 100644 --- a/integration/resources/templates/combination/intrinsics_serverless_api.yaml +++ b/integration/resources/templates/combination/intrinsics_serverless_api.yaml @@ -90,6 +90,8 @@ Resources: Type: AWS::Serverless::Api Condition: TrueCondition Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Ref: MyStageName DefinitionUri: @@ -107,6 +109,8 @@ Resources: Type: AWS::Serverless::Api Condition: FalseCondition Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Ref: MyStageName DefinitionUri: diff --git a/integration/resources/templates/combination/state_machine_with_api.yaml b/integration/resources/templates/combination/state_machine_with_api.yaml index 1d8beca26..eadab8c62 100644 --- a/integration/resources/templates/combination/state_machine_with_api.yaml +++ b/integration/resources/templates/combination/state_machine_with_api.yaml @@ -8,6 +8,8 @@ Resources: ExistingRestApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Dev MyStateMachine: diff --git a/integration/resources/templates/combination/websocket_api_basic.yaml b/integration/resources/templates/combination/websocket_api_basic.yaml index a11de573d..97d15f8fb 100644 --- a/integration/resources/templates/combination/websocket_api_basic.yaml +++ b/integration/resources/templates/combination/websocket_api_basic.yaml @@ -8,6 +8,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM Name: MyApi RouteSelectionExpression: $request.body.action Routes: diff --git a/integration/resources/templates/combination/websocket_api_basic_config.yaml b/integration/resources/templates/combination/websocket_api_basic_config.yaml index 99070c6ae..24ba205c2 100644 --- a/integration/resources/templates/combination/websocket_api_basic_config.yaml +++ b/integration/resources/templates/combination/websocket_api_basic_config.yaml @@ -8,6 +8,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM ApiKeySelectionExpression: $request.header.x-api-key Description: Toy API DisableExecuteApiEndpoint: false diff --git a/integration/resources/templates/combination/websocket_api_custom_domains_regional.yaml b/integration/resources/templates/combination/websocket_api_custom_domains_regional.yaml index 56d8e9165..5b0691ef3 100644 --- a/integration/resources/templates/combination/websocket_api_custom_domains_regional.yaml +++ b/integration/resources/templates/combination/websocket_api_custom_domains_regional.yaml @@ -39,6 +39,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM Name: MyApi RouteSelectionExpression: $request.body.action Routes: diff --git a/integration/resources/templates/combination/websocket_api_multiple_api.yaml b/integration/resources/templates/combination/websocket_api_multiple_api.yaml index 456aaf736..8b01c71b2 100644 --- a/integration/resources/templates/combination/websocket_api_multiple_api.yaml +++ b/integration/resources/templates/combination/websocket_api_multiple_api.yaml @@ -8,6 +8,8 @@ Resources: Api1: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM RouteSelectionExpression: $request.body.action Routes: $default: @@ -15,6 +17,8 @@ Resources: Api2: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM Name: Api2 RouteSelectionExpression: $request.body.action Routes: diff --git a/integration/resources/templates/combination/websocket_api_multiple_routes.yaml b/integration/resources/templates/combination/websocket_api_multiple_routes.yaml index ab9237a81..ba324159b 100644 --- a/integration/resources/templates/combination/websocket_api_multiple_routes.yaml +++ b/integration/resources/templates/combination/websocket_api_multiple_routes.yaml @@ -26,6 +26,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM RouteSelectionExpression: $request.body.action Routes: $connect: diff --git a/integration/resources/templates/combination/websocket_api_route_config.yaml b/integration/resources/templates/combination/websocket_api_route_config.yaml index 6dcfe7b9d..1f4f41602 100644 --- a/integration/resources/templates/combination/websocket_api_route_config.yaml +++ b/integration/resources/templates/combination/websocket_api_route_config.yaml @@ -8,6 +8,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM Routes: $connect: ApiKeyRequired: false diff --git a/integration/resources/templates/combination/websocket_api_route_settings.yaml b/integration/resources/templates/combination/websocket_api_route_settings.yaml index 67e00782e..115be141b 100644 --- a/integration/resources/templates/combination/websocket_api_route_settings.yaml +++ b/integration/resources/templates/combination/websocket_api_route_settings.yaml @@ -12,6 +12,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM RouteSelectionExpression: $request.body.action RouteSettings: sendMessage: diff --git a/integration/resources/templates/combination/websocket_api_stage_config.yaml b/integration/resources/templates/combination/websocket_api_stage_config.yaml index c43e97f50..7519fa84c 100644 --- a/integration/resources/templates/combination/websocket_api_stage_config.yaml +++ b/integration/resources/templates/combination/websocket_api_stage_config.yaml @@ -8,6 +8,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM Name: MyApi PropagateTags: true Routes: diff --git a/integration/resources/templates/combination/websocket_api_with_disable_execute_api_endpoint.yaml b/integration/resources/templates/combination/websocket_api_with_disable_execute_api_endpoint.yaml index 2421e8f47..c86623edc 100644 --- a/integration/resources/templates/combination/websocket_api_with_disable_execute_api_endpoint.yaml +++ b/integration/resources/templates/combination/websocket_api_with_disable_execute_api_endpoint.yaml @@ -13,6 +13,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM DisableExecuteApiEndpoint: !Ref DisableExecuteApiEndpointValue Name: MyApi RouteSelectionExpression: $request.body.action diff --git a/integration/resources/templates/combination/websocket_api_with_disable_schema_validation.yaml b/integration/resources/templates/combination/websocket_api_with_disable_schema_validation.yaml index 118ea5434..6173b8390 100644 --- a/integration/resources/templates/combination/websocket_api_with_disable_schema_validation.yaml +++ b/integration/resources/templates/combination/websocket_api_with_disable_schema_validation.yaml @@ -14,6 +14,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM DisableSchemaValidation: true Name: MyApi RouteSelectionExpression: $request.body.action diff --git a/integration/resources/templates/combination/websocket_api_with_ip_address_type.yaml b/integration/resources/templates/combination/websocket_api_with_ip_address_type.yaml index be226be46..f5f518876 100644 --- a/integration/resources/templates/combination/websocket_api_with_ip_address_type.yaml +++ b/integration/resources/templates/combination/websocket_api_with_ip_address_type.yaml @@ -13,6 +13,8 @@ Resources: MyApi: Type: AWS::Serverless::WebSocketApi Properties: + Auth: + AuthType: AWS_IAM IpAddressType: !Ref IpAddressType Name: MyApi RouteSelectionExpression: $request.body.action diff --git a/integration/resources/templates/single/api_with_custom_domain_security_policy_edge.yaml b/integration/resources/templates/single/api_with_custom_domain_security_policy_edge.yaml index b12ed721f..3fc1d902d 100644 --- a/integration/resources/templates/single/api_with_custom_domain_security_policy_edge.yaml +++ b/integration/resources/templates/single/api_with_custom_domain_security_policy_edge.yaml @@ -10,6 +10,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionUri: ${definitionuri} EndpointConfiguration: diff --git a/integration/resources/templates/single/api_with_custom_domain_security_policy_regional.yaml b/integration/resources/templates/single/api_with_custom_domain_security_policy_regional.yaml index 4799cc90f..a8c05704f 100644 --- a/integration/resources/templates/single/api_with_custom_domain_security_policy_regional.yaml +++ b/integration/resources/templates/single/api_with_custom_domain_security_policy_regional.yaml @@ -10,6 +10,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionUri: ${definitionuri} EndpointConfiguration: diff --git a/integration/resources/templates/single/api_with_domain_ipaddresstype.yaml b/integration/resources/templates/single/api_with_domain_ipaddresstype.yaml index 8c2c5377b..5a359c723 100644 --- a/integration/resources/templates/single/api_with_domain_ipaddresstype.yaml +++ b/integration/resources/templates/single/api_with_domain_ipaddresstype.yaml @@ -11,6 +11,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionUri: ${definitionuri} Domain: diff --git a/integration/resources/templates/single/api_with_endpoint_access_mode.yaml b/integration/resources/templates/single/api_with_endpoint_access_mode.yaml index 40b1cb327..64fa3b255 100644 --- a/integration/resources/templates/single/api_with_endpoint_access_mode.yaml +++ b/integration/resources/templates/single/api_with_endpoint_access_mode.yaml @@ -10,6 +10,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionUri: ${definitionuri} SecurityPolicy: !Ref SecurityPolicyValue diff --git a/integration/resources/templates/single/api_with_ipaddresstype.yaml b/integration/resources/templates/single/api_with_ipaddresstype.yaml index 26f17d0ea..d7042f94c 100644 --- a/integration/resources/templates/single/api_with_ipaddresstype.yaml +++ b/integration/resources/templates/single/api_with_ipaddresstype.yaml @@ -7,6 +7,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod DefinitionUri: ${definitionuri} EndpointConfiguration: diff --git a/integration/resources/templates/single/basic_api.yaml b/integration/resources/templates/single/basic_api.yaml index 1d726f625..dc0ca32b1 100644 --- a/integration/resources/templates/single/basic_api.yaml +++ b/integration/resources/templates/single/basic_api.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: MyNewStageName DefinitionUri: ${definitionuri} Metadata: diff --git a/integration/resources/templates/single/basic_api_inline_openapi.yaml b/integration/resources/templates/single/basic_api_inline_openapi.yaml index 3c0a592dd..914d3e359 100644 --- a/integration/resources/templates/single/basic_api_inline_openapi.yaml +++ b/integration/resources/templates/single/basic_api_inline_openapi.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: MyNewStageName DefinitionBody: # Simple HTTP Proxy API diff --git a/integration/resources/templates/single/basic_api_inline_swagger.yaml b/integration/resources/templates/single/basic_api_inline_swagger.yaml index 68111ce2a..466df7992 100644 --- a/integration/resources/templates/single/basic_api_inline_swagger.yaml +++ b/integration/resources/templates/single/basic_api_inline_swagger.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: MyNewStageName DefinitionBody: # Simple HTTP Proxy API diff --git a/integration/resources/templates/single/basic_api_with_mode.yaml b/integration/resources/templates/single/basic_api_with_mode.yaml index 82a962454..7b2c2ed6c 100644 --- a/integration/resources/templates/single/basic_api_with_mode.yaml +++ b/integration/resources/templates/single/basic_api_with_mode.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: MyNewStageName Mode: overwrite diff --git a/integration/resources/templates/single/basic_api_with_mode_update.yaml b/integration/resources/templates/single/basic_api_with_mode_update.yaml index 589fd4d1f..ea2acd12a 100644 --- a/integration/resources/templates/single/basic_api_with_mode_update.yaml +++ b/integration/resources/templates/single/basic_api_with_mode_update.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: MyNewStageName Mode: overwrite diff --git a/integration/resources/templates/single/basic_api_with_tags.yaml b/integration/resources/templates/single/basic_api_with_tags.yaml index 4af4987f7..fda952c2e 100644 --- a/integration/resources/templates/single/basic_api_with_tags.yaml +++ b/integration/resources/templates/single/basic_api_with_tags.yaml @@ -6,6 +6,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: my-new-stage-name DefinitionUri: ${definitionuri} Tags: diff --git a/integration/resources/templates/single/basic_http_api.yaml b/integration/resources/templates/single/basic_http_api.yaml index e5b5f0ff1..c6e85f654 100644 --- a/integration/resources/templates/single/basic_http_api.yaml +++ b/integration/resources/templates/single/basic_http_api.yaml @@ -2,6 +2,9 @@ Resources: MyApi: Type: AWS::Serverless::HttpApi Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM DefinitionBody: info: version: '1.0' diff --git a/integration/resources/templates/single/function_alias_with_http_api_events.yaml b/integration/resources/templates/single/function_alias_with_http_api_events.yaml index 6c5fb449d..6e817207d 100644 --- a/integration/resources/templates/single/function_alias_with_http_api_events.yaml +++ b/integration/resources/templates/single/function_alias_with_http_api_events.yaml @@ -1,6 +1,10 @@ Resources: MyHttpApi: Type: AWS::Serverless::HttpApi + Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM MyLambdaFunction: Type: AWS::Serverless::Function Properties: diff --git a/integration/resources/templates/single/function_with_http_api_events.yaml b/integration/resources/templates/single/function_with_http_api_events.yaml index fa44fd333..5fe2668a6 100644 --- a/integration/resources/templates/single/function_with_http_api_events.yaml +++ b/integration/resources/templates/single/function_with_http_api_events.yaml @@ -1,6 +1,10 @@ Resources: MyHttpApi: Type: AWS::Serverless::HttpApi + Properties: + Auth: + EnableIamAuthorizer: true + DefaultAuthorizer: AWS_IAM MyLambdaFunction: Type: AWS::Serverless::Function Properties: diff --git a/integration/resources/templates/single/state_machine_with_api.yaml b/integration/resources/templates/single/state_machine_with_api.yaml index c72a66098..c1df85e39 100644 --- a/integration/resources/templates/single/state_machine_with_api.yaml +++ b/integration/resources/templates/single/state_machine_with_api.yaml @@ -3,6 +3,8 @@ Resources: MyApi: Type: AWS::Serverless::Api Properties: + Auth: + DefaultAuthorizer: AWS_IAM StageName: Prod EndpointConfiguration: Type: REGIONAL diff --git a/integration/single/test_basic_api.py b/integration/single/test_basic_api.py index c749f9ffd..17093afc3 100644 --- a/integration/single/test_basic_api.py +++ b/integration/single/test_basic_api.py @@ -47,21 +47,21 @@ def test_basic_api_with_mode(self): stack_output = self.get_stack_outputs() api_endpoint = stack_output.get("ApiEndpoint") - self.verify_get_request_response(f"{api_endpoint}/get", 200) + self.verify_get_request_response_sigv4(f"{api_endpoint}/get", 200) # Removes get from the API self.update_and_verify_stack(file_path="single/basic_api_with_mode_update") - # API Gateway by default returns 403 if a path do not exist - self.verify_get_request_response.retry_with( + # With IAM auth, API Gateway returns 404 for non-existent routes (instead of 403 without auth) + self.verify_get_request_response_sigv4.retry_with( stop=stop_after_attempt(20), wait=wait_exponential(multiplier=1, min=4, max=10) + wait_random(0, 1), retry=retry_if_exception_type(StatusCodeError), after=after_log(LOG, logging.WARNING), reraise=True, - )(self, f"{api_endpoint}/get", 403) + )(self, f"{api_endpoint}/get", 404) - LOG.log(msg=f"retry times {self.verify_get_request_response.retry.statistics}", level=logging.WARNING) + LOG.log(msg=f"retry times {self.verify_get_request_response_sigv4.retry.statistics}", level=logging.WARNING) def test_basic_api_inline_openapi(self): """ @@ -134,7 +134,7 @@ def test_state_machine_with_api_single_quotes_input(self): # This will be the wait time before triggering the APIGW request time.sleep(10) - response = self.verify_post_request(api_endpoint, input_json, 200) + response = self.verify_post_request_sigv4(api_endpoint, input_json, 200) LOG.log(msg=f"retry times {self.verify_get_request_response.retry.statistics}", level=logging.WARNING)