From 438443decbdf5a20e4933875cf23b4e90a2d7239 Mon Sep 17 00:00:00 2001 From: Sam Liu Date: Wed, 14 Dec 2022 15:53:00 -0800 Subject: [PATCH] fix: Raise correct exception when httpapi Auth is null --- samtranslator/model/eventsources/push.py | 20 ++++++++-------- ...nvalid_auth_while_method_auth_is_none.yaml | 23 +++++++++++++++++++ ...nvalid_auth_while_method_auth_is_none.json | 3 +++ 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 tests/translator/input/error_http_api_with_invalid_auth_while_method_auth_is_none.yaml create mode 100644 tests/translator/output/error_http_api_with_invalid_auth_while_method_auth_is_none.json diff --git a/samtranslator/model/eventsources/push.py b/samtranslator/model/eventsources/push.py index 394536b27a..9b767a9e5b 100644 --- a/samtranslator/model/eventsources/push.py +++ b/samtranslator/model/eventsources/push.py @@ -1128,7 +1128,7 @@ def resources_to_link(self, resources): # type: ignore[no-untyped-def] explicit_api = resources[api_id].get("Properties", {}) - return {"explicit_api": explicit_api} + return {"explicit_api": explicit_api, "api_id": api_id} @cw_timer(prefix=FUNCTION_EVETSOURCE_METRIC_PREFIX) def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] @@ -1152,7 +1152,8 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] resources.extend(self._get_permissions(kwargs)) # type: ignore[no-untyped-call] explicit_api = kwargs["explicit_api"] - self._add_openapi_integration(explicit_api, function, explicit_api.get("__MANAGE_SWAGGER")) # type: ignore[no-untyped-call] + api_id = kwargs["api_id"] + self._add_openapi_integration(explicit_api, api_id, function, explicit_api.get("__MANAGE_SWAGGER")) # type: ignore[no-untyped-call] return resources @@ -1218,10 +1219,9 @@ def _get_permission(self, resources_to_link, stage): # type: ignore[no-untyped- return self._construct_permission(resources_to_link["function"], source_arn=source_arn) # type: ignore[no-untyped-call] - def _add_openapi_integration(self, api, function, manage_swagger=False): # type: ignore[no-untyped-def] - """Adds the path and method for this Api event source to the OpenApi body for the provided RestApi. - - :param model.apigateway.ApiGatewayRestApi rest_api: the RestApi to which the path and method should be added. + def _add_openapi_integration(self, api, api_id, function, manage_swagger=False): # type: ignore[no-untyped-def] + """ + Adds the path and method for this Api event source to the OpenApi body for the provided RestApi. """ open_api_body = api.get("DefinitionBody") if open_api_body is None: @@ -1246,7 +1246,7 @@ def _add_openapi_integration(self, api, function, manage_swagger=False): # type editor.add_lambda_integration(self.Path, self.Method, uri, self.Auth, api.get("Auth"), condition=condition) # type: ignore[attr-defined, attr-defined, no-untyped-call] if self.Auth: # type: ignore[attr-defined] - self._add_auth_to_openapi_integration(api, editor) # type: ignore[no-untyped-call] + self._add_auth_to_openapi_integration(api, api_id, editor) if self.TimeoutInMillis: # type: ignore[attr-defined] editor.add_timeout_to_method(api=api, path=self.Path, method_name=self.Method, timeout=self.TimeoutInMillis) # type: ignore[attr-defined, attr-defined, no-untyped-call] path_parameters = re.findall("{(.*?)}", self.Path) # type: ignore[attr-defined] @@ -1261,13 +1261,15 @@ def _add_openapi_integration(self, api, function, manage_swagger=False): # type ) api["DefinitionBody"] = editor.openapi - def _add_auth_to_openapi_integration(self, api, editor): # type: ignore[no-untyped-def] + def _add_auth_to_openapi_integration(self, api: Dict[str, Any], api_id: str, editor: OpenApiEditor) -> None: """Adds authorization to the lambda integration :param api: api object + :param api_id: api logical id :param editor: OpenApiEditor object that contains the OpenApi definition """ method_authorizer = self.Auth.get("Authorizer") # type: ignore[attr-defined] api_auth = api.get("Auth", {}) + sam_expect(api_auth, api_id, "Auth").to_be_a_map() if not method_authorizer: if api_auth.get("DefaultAuthorizer"): self.Auth["Authorizer"] = method_authorizer = api_auth.get("DefaultAuthorizer") # type: ignore[attr-defined] @@ -1328,7 +1330,7 @@ def _add_auth_to_openapi_integration(self, api, editor): # type: ignore[no-unty "'AuthorizationScopes' must be a list of strings.".format(method=self.Method, path=self.Path), # type: ignore[attr-defined] ) - editor.add_auth_to_method(api=api, path=self.Path, method_name=self.Method, auth=self.Auth) # type: ignore[attr-defined, attr-defined] + editor.add_auth_to_method(api=api, path=self.Path, method_name=self.Method, auth=self.Auth) # type: ignore[no-untyped-call, attr-defined, attr-defined] def _build_apigw_integration_uri(function, partition): # type: ignore[no-untyped-def] diff --git a/tests/translator/input/error_http_api_with_invalid_auth_while_method_auth_is_none.yaml b/tests/translator/input/error_http_api_with_invalid_auth_while_method_auth_is_none.yaml new file mode 100644 index 0000000000..9ef9206cd4 --- /dev/null +++ b/tests/translator/input/error_http_api_with_invalid_auth_while_method_auth_is_none.yaml @@ -0,0 +1,23 @@ +Resources: + MyLambdaFunction: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + Runtime: python3.7 + InlineCode: | + def handler(event, context): + return {'body': 'Hello World!', 'statusCode': 200} + Events: + GetApi: + Type: HttpApi + Properties: + Auth: + Authorizer: NONE + ApiId: + Ref: MyApi + Method: GET + Path: /get + MyApi: + Type: AWS::Serverless::HttpApi + Properties: + Auth: diff --git a/tests/translator/output/error_http_api_with_invalid_auth_while_method_auth_is_none.json b/tests/translator/output/error_http_api_with_invalid_auth_while_method_auth_is_none.json new file mode 100644 index 0000000000..cc85b13aa7 --- /dev/null +++ b/tests/translator/output/error_http_api_with_invalid_auth_while_method_auth_is_none.json @@ -0,0 +1,3 @@ +{ + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [MyApi] is invalid. Property 'Auth' should be a map." +}