Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions samcli/local/apigw/authorizers/lambda_authorizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,10 @@ def _is_resource_authorized(self, response: dict, method_arn: str) -> bool:
resource_list = resource if isinstance(resource, list) else [resource]

for resource_arn in resource_list:
# form a regular expression from the possible wildcard resource ARN
regex_method_arn = resource_arn.replace("*", ".*").replace("?", ".")
# form a regular expression from the possible wildcard resource ARN;
# escape it first so that regex syntax in the ARN itself (such as the
# "$" in the HTTP API "$default" stage) is matched literally
regex_method_arn = re.escape(resource_arn).replace(r"\*", ".*").replace(r"\?", ".")
regex_method_arn += "$"

if re.match(regex_method_arn, method_arn):
Expand Down
60 changes: 60 additions & 0 deletions tests/unit/local/apigw/test_lambda_authorizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,66 @@ def test_validate_is_resource_authorized(

self.assertEqual(result, expected_result)

@parameterized.expand(
[
( # HTTP API "$default" stage, wildcard resource
"arn:aws:execute-api:us-east-1:123456789012:1234567890/$default/*",
"arn:aws:execute-api:us-east-1:123456789012:1234567890/$default/GET/hello",
True,
),
( # authorizer echoes the method ARN it was given back verbatim
"arn:aws:execute-api:us-east-1:123456789012:1234567890/$default/GET/hello",
"arn:aws:execute-api:us-east-1:123456789012:1234567890/$default/GET/hello",
True,
),
( # a "[" in the path must not be read as a character set
"arn:aws:execute-api:us-east-1:123456789012:1234567890/prod/GET/a[b",
"arn:aws:execute-api:us-east-1:123456789012:1234567890/prod/GET/a[b",
True,
),
( # a "(" in the path must not be read as a group
"arn:aws:execute-api:us-east-1:123456789012:1234567890/prod/GET/x(y",
"arn:aws:execute-api:us-east-1:123456789012:1234567890/prod/GET/x(y",
True,
),
( # "." is a literal, not a wildcard
"arn:aws:execute-api:us-east-1:123456789012:1234567890/prod/GET/a.c",
"arn:aws:execute-api:us-east-1:123456789012:1234567890/prod/GET/abc",
False,
),
( # a different stage is still denied
"arn:aws:execute-api:us-east-1:123456789012:1234567890/$default/*",
"arn:aws:execute-api:us-east-1:123456789012:1234567890/prod/GET/hello",
False,
),
]
)
def test_is_resource_authorized_treats_arn_as_literal(self, resource_arn, method_arn, expected_result):
auth = LambdaAuthorizer(
"my auth",
Mock(),
Mock(),
[],
Mock(),
Mock(),
Mock(),
)
response = {
"policyDocument": {
"Statement": [
{
"Action": ["execute-api:Invoke"],
"Effect": "Allow",
"Resource": resource_arn,
}
]
},
}

result = auth._is_resource_authorized(response, method_arn)

self.assertEqual(result, expected_result)


class TestLambdaAuthorizerIamPolicyValidator(TestCase):
@parameterized.expand(
Expand Down