in samtranslator/model/eventsources/push.py [0:0]
def _get_permission(self, resources_to_link, stage): # type: ignore[no-untyped-def]
# It turns out that APIGW doesn't like trailing slashes in paths (#665)
# and removes as a part of their behaviour, but this isn't documented.
# The regex removes the tailing slash to ensure the permission works as intended
path = re.sub(r"^(.+)/$", r"\1", self._path)
editor = None
if resources_to_link["explicit_api"].get("DefinitionBody"):
try:
editor = OpenApiEditor(resources_to_link["explicit_api"].get("DefinitionBody"))
except InvalidDocumentException as e:
api_logical_id = self.ApiId.get("Ref") if isinstance(self.ApiId, dict) else self.ApiId
# TODO: api_logical_id is never None, try to make it consistent with what mypy thinks
raise InvalidResourceException(
cast(str, api_logical_id), " ".join(ex.message for ex in e.causes)
) from e
# If this is using the new $default path, keep path blank and add a * permission
if path == OpenApiEditor._DEFAULT_PATH:
path = ""
elif editor and editor.is_integration_function_logical_id_match( # type: ignore[no-untyped-call]
OpenApiEditor._DEFAULT_PATH, OpenApiEditor._X_ANY_METHOD, resources_to_link.get("function").logical_id
):
# Case where default exists for this function, and so the permissions for that will apply here as well
# This can save us several CFN resources (not duplicating permissions)
return None
path = OpenApiEditor.get_path_without_trailing_slash(path) # type: ignore[no-untyped-call]
# Handle case where Method is already the ANY ApiGateway extension
method = (
"*"
if self._method.lower() == "any" or self._method.lower() == OpenApiEditor._X_ANY_METHOD
else self._method.upper()
)
api_id = self.ApiId
# when the Method is "ANY" and the path is '/$default' it adds an extra "*" which causes a bug
# the generated ARN for permissions ends with /*/*/$default which causes the path to be invalid
# see this issue: https://github.com/aws/serverless-application-model/issues/1860
resource = "${__ApiId__}/${__Stage__}"
if self._method.lower() == "any" and path == f"/{OpenApiEditor._DEFAULT_PATH}":
resource += path
else:
resource += f"/{method}{path}"
# ApiId can be a simple string or intrinsic function like !Ref. Using Fn::Sub will handle both cases
source_arn = fnSub(
ArnGenerator.generate_arn(partition="${AWS::Partition}", service="execute-api", resource=resource),
{"__ApiId__": api_id, "__Stage__": stage},
)
return self._construct_permission(resources_to_link["function"], source_arn=source_arn) # type: ignore[no-untyped-call]