Skip to content

Commit 310934b

Browse files
authored
refactor: improve HttpApi authorizer validation (#3899)
1 parent 4ffd7a7 commit 310934b

3 files changed

Lines changed: 48 additions & 55 deletions

File tree

samtranslator/model/apigatewayv2.py

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -240,54 +240,48 @@ def _get_auth_type(self) -> str:
240240
return "JWT"
241241
return "REQUEST"
242242

243+
# Maps each authorizer type to the set of properties it accepts
244+
ALLOWED_PROPERTIES = {
245+
"JWT": {"authorization_scopes", "jwt_configuration", "id_source"},
246+
"REQUEST": {
247+
"function_arn",
248+
"function_invoke_role",
249+
"identity",
250+
"authorizer_payload_format_version",
251+
"enable_simple_responses",
252+
"enable_function_default_permissions",
253+
},
254+
"AWS_IAM": set(),
255+
}
256+
257+
# Maps internal attr name to (display name, error hint)
258+
PROPERTY_DISPLAY = {
259+
"authorization_scopes": ("AuthorizationScopes", "OAuth2 Authorizer"),
260+
"jwt_configuration": ("JwtConfiguration", "OAuth2 Authorizer"),
261+
"id_source": (
262+
"IdentitySource",
263+
"OAuth2 Authorizer. For Lambda Authorizer, use the 'Identity' property instead",
264+
),
265+
"function_arn": ("FunctionArn", "Lambda Authorizer"),
266+
"function_invoke_role": ("FunctionInvokeRole", "Lambda Authorizer"),
267+
"identity": ("Identity", "Lambda Authorizer"),
268+
"authorizer_payload_format_version": ("AuthorizerPayloadFormatVersion", "Lambda Authorizer"),
269+
"enable_simple_responses": ("EnableSimpleResponses", "Lambda Authorizer"),
270+
"enable_function_default_permissions": ("EnableFunctionDefaultPermissions", "Lambda Authorizer"),
271+
}
272+
243273
def _validate_input_parameters(self) -> None:
244274
authorizer_type = self._get_auth_type()
245275

246276
if self.authorization_scopes is not None and not isinstance(self.authorization_scopes, list):
247277
raise InvalidResourceException(self.api_logical_id, "AuthorizationScopes must be a list.")
248278

249-
if self.authorization_scopes is not None and not authorizer_type == "JWT":
250-
raise InvalidResourceException(
251-
self.api_logical_id, "AuthorizationScopes must be defined only for OAuth2 Authorizer."
252-
)
253-
254-
if self.jwt_configuration is not None and not authorizer_type == "JWT":
255-
raise InvalidResourceException(
256-
self.api_logical_id, "JwtConfiguration must be defined only for OAuth2 Authorizer."
257-
)
258-
259-
if self.id_source is not None and not authorizer_type == "JWT":
260-
raise InvalidResourceException(
261-
self.api_logical_id, "IdentitySource must be defined only for OAuth2 Authorizer."
262-
)
263-
264-
if self.function_arn is not None and not authorizer_type == "REQUEST":
265-
raise InvalidResourceException(
266-
self.api_logical_id, "FunctionArn must be defined only for Lambda Authorizer."
267-
)
268-
269-
if self.function_invoke_role is not None and not authorizer_type == "REQUEST":
270-
raise InvalidResourceException(
271-
self.api_logical_id, "FunctionInvokeRole must be defined only for Lambda Authorizer."
272-
)
273-
274-
if self.identity is not None and not authorizer_type == "REQUEST":
275-
raise InvalidResourceException(self.api_logical_id, "Identity must be defined only for Lambda Authorizer.")
276-
277-
if self.authorizer_payload_format_version is not None and not authorizer_type == "REQUEST":
278-
raise InvalidResourceException(
279-
self.api_logical_id, "AuthorizerPayloadFormatVersion must be defined only for Lambda Authorizer."
280-
)
281-
282-
if self.enable_simple_responses is not None and not authorizer_type == "REQUEST":
283-
raise InvalidResourceException(
284-
self.api_logical_id, "EnableSimpleResponses must be defined only for Lambda Authorizer."
285-
)
286-
287-
if self.enable_function_default_permissions is not None and authorizer_type != "REQUEST":
288-
raise InvalidResourceException(
289-
self.api_logical_id, "EnableFunctionDefaultPermissions must be defined only for Lambda Authorizer."
290-
)
279+
allowed = self.ALLOWED_PROPERTIES.get(authorizer_type, set())
280+
for attr, (display_name, allowed_for) in self.PROPERTY_DISPLAY.items():
281+
if getattr(self, attr) is not None and attr not in allowed:
282+
raise InvalidResourceException(
283+
self.api_logical_id, f"{display_name} is only supported for {allowed_for}."
284+
)
291285

292286
def _validate_jwt_authorizer(self) -> None:
293287
if not self.jwt_configuration:

tests/model/test_api_v2.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_create_authorizer_fails_with_authorization_scopes_non_oauth2(self):
6464
self.assertEqual(
6565
e.value.message,
6666
"Resource with id [logicalId] is invalid. "
67-
+ "AuthorizationScopes must be defined only for OAuth2 Authorizer.",
67+
+ "AuthorizationScopes is only supported for OAuth2 Authorizer.",
6868
)
6969

7070
@mock.patch(
@@ -79,8 +79,7 @@ def test_create_authorizer_fails_with_jtw_configuration_non_oauth2(self):
7979
)
8080
self.assertEqual(
8181
e.value.message,
82-
"Resource with id [logicalId] is invalid. "
83-
+ "JwtConfiguration must be defined only for OAuth2 Authorizer.",
82+
"Resource with id [logicalId] is invalid. " + "JwtConfiguration is only supported for OAuth2 Authorizer.",
8483
)
8584

8685
def test_create_authorizer_fails_with_id_source_non_oauth2(self):
@@ -92,7 +91,8 @@ def test_create_authorizer_fails_with_id_source_non_oauth2(self):
9291
)
9392
self.assertEqual(
9493
e.value.message,
95-
"Resource with id [logicalId] is invalid. " + "IdentitySource must be defined only for OAuth2 Authorizer.",
94+
"Resource with id [logicalId] is invalid. " + "IdentitySource is only supported for OAuth2 Authorizer."
95+
" For Lambda Authorizer, use the 'Identity' property instead.",
9696
)
9797

9898
def test_create_authorizer_fails_with_function_arn_non_lambda(self):
@@ -106,7 +106,7 @@ def test_create_authorizer_fails_with_function_arn_non_lambda(self):
106106
)
107107
self.assertEqual(
108108
e.value.message,
109-
"Resource with id [logicalId] is invalid. " + "FunctionArn must be defined only for Lambda Authorizer.",
109+
"Resource with id [logicalId] is invalid. " + "FunctionArn is only supported for Lambda Authorizer.",
110110
)
111111

112112
def test_create_authorizer_fails_with_function_invoke_role_non_lambda(self):
@@ -120,8 +120,7 @@ def test_create_authorizer_fails_with_function_invoke_role_non_lambda(self):
120120
)
121121
self.assertEqual(
122122
e.value.message,
123-
"Resource with id [logicalId] is invalid. "
124-
+ "FunctionInvokeRole must be defined only for Lambda Authorizer.",
123+
"Resource with id [logicalId] is invalid. " + "FunctionInvokeRole is only supported for Lambda Authorizer.",
125124
)
126125

127126
def test_create_authorizer_fails_with_identity_non_lambda(self):
@@ -135,7 +134,7 @@ def test_create_authorizer_fails_with_identity_non_lambda(self):
135134
)
136135
self.assertEqual(
137136
e.value.message,
138-
"Resource with id [logicalId] is invalid. " + "Identity must be defined only for Lambda Authorizer.",
137+
"Resource with id [logicalId] is invalid. " + "Identity is only supported for Lambda Authorizer.",
139138
)
140139

141140
def test_create_authorizer_fails_with_authorizer_payload_format_version_non_lambda(self):
@@ -150,7 +149,7 @@ def test_create_authorizer_fails_with_authorizer_payload_format_version_non_lamb
150149
self.assertEqual(
151150
e.value.message,
152151
"Resource with id [logicalId] is invalid. "
153-
+ "AuthorizerPayloadFormatVersion must be defined only for Lambda Authorizer.",
152+
+ "AuthorizerPayloadFormatVersion is only supported for Lambda Authorizer.",
154153
)
155154

156155
def test_create_authorizer_fails_with_enable_simple_responses_non_lambda(self):
@@ -165,7 +164,7 @@ def test_create_authorizer_fails_with_enable_simple_responses_non_lambda(self):
165164
self.assertEqual(
166165
e.value.message,
167166
"Resource with id [logicalId] is invalid. "
168-
+ "EnableSimpleResponses must be defined only for Lambda Authorizer.",
167+
+ "EnableSimpleResponses is only supported for Lambda Authorizer.",
169168
)
170169

171170
def test_create_authorizer_fails_with_enable_function_default_permissions_non_lambda(self):
@@ -180,7 +179,7 @@ def test_create_authorizer_fails_with_enable_function_default_permissions_non_la
180179
self.assertEqual(
181180
e.value.message,
182181
"Resource with id [logicalId] is invalid. "
183-
+ "EnableFunctionDefaultPermissions must be defined only for Lambda Authorizer.",
182+
+ "EnableFunctionDefaultPermissions is only supported for Lambda Authorizer.",
184183
)
185184

186185
@mock.patch(

tests/translator/output/error_http_api_invalid_lambda_auth.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"Resource with id [MyApi3] is invalid. ",
1010
"Property 'Authorizers.LambdaAuth.EnableFunctionDefaultPermissions' should be a boolean. ",
1111
"Resource with id [MyApi4] is invalid. ",
12-
"EnableFunctionDefaultPermissions must be defined only for Lambda Authorizer."
12+
"EnableFunctionDefaultPermissions is only supported for Lambda Authorizer."
1313
],
14-
"errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 4. Resource with id [MyApi1] is invalid. LambdaAuth Lambda Authorizer must define 'AuthorizerPayloadFormatVersion'. Resource with id [MyApi2] is invalid. LambdaAuth Lambda Authorizer must define 'FunctionArn'. Resource with id [MyApi3] is invalid. Property 'Authorizers.LambdaAuth.EnableFunctionDefaultPermissions' should be a boolean. Resource with id [MyApi4] is invalid. EnableFunctionDefaultPermissions must be defined only for Lambda Authorizer."
14+
"errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 4. Resource with id [MyApi1] is invalid. LambdaAuth Lambda Authorizer must define 'AuthorizerPayloadFormatVersion'. Resource with id [MyApi2] is invalid. LambdaAuth Lambda Authorizer must define 'FunctionArn'. Resource with id [MyApi3] is invalid. Property 'Authorizers.LambdaAuth.EnableFunctionDefaultPermissions' should be a boolean. Resource with id [MyApi4] is invalid. EnableFunctionDefaultPermissions is only supported for Lambda Authorizer."
1515
}

0 commit comments

Comments
 (0)