Skip to content

Commit d059423

Browse files
committed
test
1 parent f859071 commit d059423

4 files changed

Lines changed: 67 additions & 30 deletions

File tree

.cfnlintrc.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
templates:
22
- tests/translator/output/**/*.json
33
ignore_templates:
4+
- tests/translator/output/**/function_with_function_url_config.json
5+
- tests/translator/output/**/function_with_function_url_config_and_autopublishalias.json
6+
- tests/translator/output/**/function_with_function_url_config_without_cors_config.json
47
- tests/translator/output/**/error_*.json # Fail by design
58
- tests/translator/output/**/api_http_paths_with_if_condition.json
69
- tests/translator/output/**/api_http_paths_with_if_condition_no_value_else_case.json

samtranslator/model/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ def validate_properties_and_return_model(self, cls: Type[RT]) -> RT:
345345
"""
346346
try:
347347
return cls.parse_obj(self._generate_resource_dict()["Properties"])
348-
except pydantic.error_wrappers.ValidationError as e:
348+
except pydantic.error_wrappers.ValidationError as e: # type: ignore
349349
error_properties: str = ""
350350
with suppress(KeyError):
351351
error_properties = ".".join(str(x) for x in e.errors()[0]["loc"])

samtranslator/model/sam_resources.py

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,6 @@
133133
from .tags.resource_tagging import get_tag_list
134134

135135
_CONDITION_CHAR_LIMIT = 255
136-
FUNCTION_URL_PUBLIC_PERMISSION_ACTION = "lambda:InvokeFunctionUrl"
137-
FUNCTION_INVOKE_PERMISSION_ACTION = "lambda:InvokeFunction"
138136

139137

140138
class SamFunction(SamResourceMacro):
@@ -322,8 +320,13 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] # noqa: P
322320
if self.FunctionUrlConfig:
323321
lambda_url = self._construct_function_url(lambda_function, lambda_alias, self.FunctionUrlConfig)
324322
resources.append(lambda_url)
325-
url_permissions = self._construct_url_permissions(lambda_function, lambda_alias, self.FunctionUrlConfig)
326-
resources.extend(url_permissions)
323+
url_permission = self._construct_url_permission(lambda_function, lambda_alias, self.FunctionUrlConfig)
324+
invoke_dual_auth_permission = self._construct_invoke_dual_auth_permission(
325+
lambda_function, lambda_alias, self.FunctionUrlConfig
326+
)
327+
if url_permission and invoke_dual_auth_permission:
328+
resources.append(url_permission)
329+
resources.append(invoke_dual_auth_permission)
327330

328331
self._validate_deployment_preference_and_add_update_policy(
329332
kwargs.get("deployment_preference_collection"),
@@ -1213,11 +1216,11 @@ def _validate_cors_config_parameter(
12131216
"{} must be of type {}.".format(prop_name, str(prop_type).split("'")[1]),
12141217
)
12151218

1216-
def _construct_url_permissions(
1219+
def _construct_url_permission(
12171220
self, lambda_function: LambdaFunction, lambda_alias: Optional[LambdaAlias], function_url_config: Dict[str, Any]
1218-
) -> List[LambdaPermission]:
1221+
) -> Optional[LambdaPermission]:
12191222
"""
1220-
Construct the lambda permissions associated with the function url resource in a case
1223+
Construct the lambda permission associated with the function url resource in a case
12211224
for public access when AuthType is NONE
12221225
12231226
Parameters
@@ -1230,45 +1233,62 @@ def _construct_url_permissions(
12301233
12311234
Returns
12321235
-------
1233-
List[LambdaPermission]
1234-
The lambda permission appended to a function url resource with public access and the
1235-
Permission to invoke the function in general.
1236+
LambdaPermission
1237+
The lambda permission appended to a function url resource with public access
12361238
"""
12371239
auth_type = function_url_config.get("AuthType")
12381240

12391241
if auth_type not in ["NONE"] or is_intrinsic(function_url_config):
1240-
return []
1241-
1242-
url_public_permission_logical_id = f"{lambda_function.logical_id}UrlPublicPermissions"
1242+
return None
12431243

1244+
logical_id = f"{lambda_function.logical_id}UrlPublicPermissions"
12441245
lambda_permission_attributes = self.get_passthrough_resource_attributes()
1245-
1246-
lambda_url_public_permission = LambdaPermission(
1247-
logical_id=url_public_permission_logical_id, attributes=lambda_permission_attributes
1248-
)
1249-
lambda_url_public_permission.Action = FUNCTION_URL_PUBLIC_PERMISSION_ACTION
1250-
lambda_url_public_permission.Principal = "*"
1251-
lambda_url_public_permission.FunctionName = (
1246+
lambda_permission = LambdaPermission(logical_id=logical_id, attributes=lambda_permission_attributes)
1247+
lambda_permission.Action = "lambda:InvokeFunctionUrl"
1248+
lambda_permission.FunctionName = (
12521249
lambda_alias.get_runtime_attr("arn") if lambda_alias else lambda_function.get_runtime_attr("name")
12531250
)
1254-
lambda_url_public_permission.FunctionUrlAuthType = auth_type
1251+
lambda_permission.Principal = "*"
1252+
lambda_permission.FunctionUrlAuthType = auth_type
1253+
return lambda_permission
12551254

1256-
url_invoke_permission_logical_id = f"{lambda_function.logical_id}URLInvokeAllowPublicAccess"
1255+
def _construct_invoke_dual_auth_permission(
1256+
self, lambda_function: LambdaFunction, lambda_alias: Optional[LambdaAlias], function_url_config: Dict[str, Any]
1257+
) -> Optional[LambdaPermission]:
1258+
"""
1259+
Construct the lambda permission associated with the function invoke resource in a case
1260+
for public access when AuthType is NONE
12571261
1258-
lambda_permission_attributes = self.get_passthrough_resource_attributes()
1262+
Parameters
1263+
----------
1264+
lambda_function : LambdaUrl
1265+
Lambda Function resource
12591266
1260-
lambda_invoke_permission = LambdaPermission(
1261-
logical_id=url_invoke_permission_logical_id, attributes=lambda_permission_attributes
1262-
)
1263-
lambda_invoke_permission.Action = FUNCTION_INVOKE_PERMISSION_ACTION
1267+
lambda_alias : LambdaAlias
1268+
Lambda Alias resource
1269+
1270+
Returns
1271+
-------
1272+
LambdaPermission
1273+
The lambda permission appended to a function that allow function invoke only from Function URL
1274+
"""
1275+
# create lambda:InvokeFunction with InvokedViaFunctionUrl=True
1276+
auth_type = function_url_config.get("AuthType")
1277+
1278+
if auth_type not in ["NONE"] or is_intrinsic(function_url_config):
1279+
return None
1280+
1281+
logical_id = f"{lambda_function.logical_id}URLInvokeAllowPublicAccess"
1282+
lambda_permission_attributes = self.get_passthrough_resource_attributes()
1283+
lambda_invoke_permission = LambdaPermission(logical_id=logical_id, attributes=lambda_permission_attributes)
1284+
lambda_invoke_permission.Action = "lambda:InvokeFunction"
12641285
lambda_invoke_permission.Principal = "*"
12651286
lambda_invoke_permission.FunctionName = (
12661287
lambda_alias.get_runtime_attr("arn") if lambda_alias else lambda_function.get_runtime_attr("name")
12671288
)
1268-
12691289
lambda_invoke_permission.InvokedViaFunctionUrl = True
12701290

1271-
return [lambda_url_public_permission, lambda_invoke_permission]
1291+
return lambda_invoke_permission
12721292

12731293

12741294
class SamApi(SamResourceMacro):

tests/model/test_sam_resources.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,20 @@ def test_with_valid_function_url_config_with_lambda_permission(self):
593593
if permission.Action == "lambda:InvokeFunction":
594594
self.assertEqual(permission.InvokedViaFunctionUrl, True)
595595

596+
@patch("boto3.session.Session.region_name", "ap-southeast-1")
597+
def test_with_aws_iam_function_url_config_with_lambda_permission(self):
598+
function = SamFunction("foo")
599+
function.CodeUri = "s3://foobar/foo.zip"
600+
function.Runtime = "foo"
601+
function.Handler = "bar"
602+
# When create FURL with AWS_IAM
603+
function.FunctionUrlConfig = {"AuthType": "AWS_IAM"}
604+
605+
cfnResources = function.to_cloudformation(**self.kwargs)
606+
generatedUrlList = [x for x in cfnResources if isinstance(x, LambdaPermission)]
607+
# Then no permisssion should be auto created
608+
self.assertEqual(generatedUrlList.__len__(), 0)
609+
596610
@patch("boto3.session.Session.region_name", "ap-southeast-1")
597611
def test_with_invalid_function_url_config_with_authorization_type_value_as_None(self):
598612
function = SamFunction("foo")

0 commit comments

Comments
 (0)