Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 0 additions & 3 deletions .cfnlintrc.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
templates:
- tests/translator/output/**/*.json
ignore_templates:
- tests/translator/output/**/function_with_function_url_config.json
- tests/translator/output/**/function_with_function_url_config_and_autopublishalias.json
- tests/translator/output/**/function_with_function_url_config_without_cors_config.json
- tests/translator/output/**/error_*.json # Fail by design
- tests/translator/output/**/api_http_paths_with_if_condition.json
- tests/translator/output/**/api_http_paths_with_if_condition_no_value_else_case.json
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

67 changes: 0 additions & 67 deletions integration/single/test_basic_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,73 +130,6 @@ def test_basic_function_with_url_config(self, file_name, qualifier):
self.assertEqual(function_url_config["Cors"], cors_config)
self._assert_invoke(lambda_client, function_name, qualifier, 200)

@parameterized.expand(
[
("single/basic_function_with_function_url_dual_auth", None),
("single/basic_function_with_function_url_with_autopuplishalias_dual_auth", "live"),
]
)
@skipIf(current_region_does_not_support([LAMBDA_URL]), "Lambda Url is not supported in this testing region")
def test_basic_function_with_url_dual_auth(self, file_name, qualifier):
"""
Creates a basic lambda function with Function Url with authtype: None
Verifies that 2 AWS::Lambda::Permission resources are created:
- lambda:InvokeFunctionUrl
- lambda:InvokeFunction with InvokedViaFunctionUrl: True
"""
self.create_and_verify_stack(file_name)

# Get Lambda permissions
lambda_permissions = self.get_stack_resources("AWS::Lambda::Permission")

# Verify we have exactly 2 permissions
self.assertEqual(len(lambda_permissions), 2, "Expected exactly 2 Lambda permissions")

# Check for the expected permission logical IDs
invoke_function_url_permission = None
invoke_permission = None

for permission in lambda_permissions:
logical_id = permission["LogicalResourceId"]
if "MyLambdaFunctionUrlPublicPermissions" in logical_id:
invoke_function_url_permission = permission
elif "MyLambdaFunctionURLInvokeAllowPublicAccess" in logical_id:
invoke_permission = permission

# Verify both permissions exist
self.assertIsNotNone(invoke_function_url_permission, "Expected MyLambdaFunctionUrlPublicPermissions to exist")
self.assertIsNotNone(invoke_permission, "Expected MyLambdaFunctionURLInvokeAllowPublicAccess to exist")

# Get the function name and URL
function_name = self.get_physical_id_by_type("AWS::Lambda::Function")
lambda_client = self.client_provider.lambda_client

# Get the function URL configuration to verify auth type
function_url_config = (
lambda_client.get_function_url_config(FunctionName=function_name, Qualifier=qualifier)
if qualifier
else lambda_client.get_function_url_config(FunctionName=function_name)
)

# Verify the auth type is NONE
self.assertEqual(function_url_config["AuthType"], "NONE", "Expected AuthType to be NONE")

# Get the template to check for InvokedViaFunctionUrl property
cfn_client = self.client_provider.cfn_client
template = cfn_client.get_template(StackName=self.stack_name, TemplateStage="Processed")
template_body = template["TemplateBody"]

# Check if the InvokePermission has InvokedViaFunctionUrl: True
# This is a bit hacky but we don't have direct access to the resource properties
# We're checking if the string representation of the template contains this property
template_str = str(template_body)
self.assertIn("InvokedViaFunctionUrl", template_str, "Expected InvokedViaFunctionUrl property in the template")

# Get the function URL from stack outputs
function_url = self.get_stack_output("FunctionUrl")["OutputValue"]
# Invoke the function URL and verify the response
self._verify_get_request(function_url, self.FUNCTION_OUTPUT)

@skipIf(current_region_does_not_support([CODE_DEPLOY]), "CodeDeploy is not supported in this testing region")
def test_function_with_deployment_preference_alarms_intrinsic_if(self):
self.create_and_verify_stack("single/function_with_deployment_preference_alarms_intrinsic_if")
Expand Down
1 change: 0 additions & 1 deletion samtranslator/model/lambda_.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ class LambdaPermission(Resource):
"SourceArn": GeneratedProperty(),
"EventSourceToken": GeneratedProperty(),
"FunctionUrlAuthType": GeneratedProperty(),
"InvokedViaFunctionUrl": GeneratedProperty(),
}


Expand Down
54 changes: 3 additions & 51 deletions samtranslator/model/sam_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,8 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] # noqa: P
lambda_url = self._construct_function_url(lambda_function, lambda_alias, self.FunctionUrlConfig)
resources.append(lambda_url)
url_permission = self._construct_url_permission(lambda_function, lambda_alias, self.FunctionUrlConfig)
invoke_dual_auth_permission = self._construct_invoke_permission(
lambda_function, lambda_alias, self.FunctionUrlConfig
)
if url_permission and invoke_dual_auth_permission:
if url_permission:
resources.append(url_permission)
resources.append(invoke_dual_auth_permission)

self._validate_deployment_preference_and_add_update_policy(
kwargs.get("deployment_preference_collection"),
Expand All @@ -336,6 +332,7 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] # noqa: P
self.get_passthrough_resource_attributes(),
feature_toggle,
)

event_invoke_policies: List[Dict[str, Any]] = []
if self.EventInvokeConfig:
function_name = lambda_function.logical_id
Expand Down Expand Up @@ -1228,13 +1225,9 @@ def _construct_url_permission(
lambda_function : LambdaUrl
Lambda Function resource

lambda_alias : LambdaAlias
llambda_alias : LambdaAlias
Lambda Alias resource


function_url_config: Dict
Function url config used to create FURL

Returns
-------
LambdaPermission
Expand All @@ -1256,47 +1249,6 @@ def _construct_url_permission(
lambda_permission.FunctionUrlAuthType = auth_type
return lambda_permission

def _construct_invoke_permission(
self, lambda_function: LambdaFunction, lambda_alias: Optional[LambdaAlias], function_url_config: Dict[str, Any]
) -> Optional[LambdaPermission]:
"""
Construct the lambda permission associated with the function invoke resource in a case
for public access when AuthType is NONE

Parameters
----------
lambda_function : LambdaUrl
Lambda Function resource

lambda_alias : LambdaAlias
Lambda Alias resource

function_url_config: Dict
Function url config used to create FURL

Returns
-------
LambdaPermission
The lambda permission appended to a function that allow function invoke only from Function URL
"""
# create lambda:InvokeFunction with InvokedViaFunctionUrl=True
auth_type = function_url_config.get("AuthType")

if auth_type not in ["NONE"] or is_intrinsic(function_url_config):
return None

logical_id = f"{lambda_function.logical_id}URLInvokeAllowPublicAccess"
lambda_permission_attributes = self.get_passthrough_resource_attributes()
lambda_invoke_permission = LambdaPermission(logical_id=logical_id, attributes=lambda_permission_attributes)
lambda_invoke_permission.Action = "lambda:InvokeFunction"
lambda_invoke_permission.Principal = "*"
lambda_invoke_permission.FunctionName = (
lambda_alias.get_runtime_attr("arn") if lambda_alias else lambda_function.get_runtime_attr("name")
)
lambda_invoke_permission.InvokedViaFunctionUrl = True

return lambda_invoke_permission


class SamApi(SamResourceMacro):
"""SAM rest API macro."""
Expand Down
28 changes: 5 additions & 23 deletions tests/model/test_sam_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,29 +583,11 @@ def test_with_valid_function_url_config_with_lambda_permission(self):

cfnResources = function.to_cloudformation(**self.kwargs)
generatedUrlList = [x for x in cfnResources if isinstance(x, LambdaPermission)]
self.assertEqual(generatedUrlList.__len__(), 2)
for permission in generatedUrlList:
self.assertEqual(permission.FunctionName, {"Ref": "foo"})
self.assertEqual(permission.Principal, "*")
self.assertTrue(permission.Action in ["lambda:InvokeFunctionUrl", "lambda:InvokeFunction"])
if permission.Action == "lambda:InvokeFunctionUrl":
self.assertEqual(permission.FunctionUrlAuthType, "NONE")
if permission.Action == "lambda:InvokeFunction":
self.assertEqual(permission.InvokedViaFunctionUrl, True)

@patch("boto3.session.Session.region_name", "ap-southeast-1")
def test_with_aws_iam_function_url_config_with_lambda_permission(self):
function = SamFunction("foo")
function.CodeUri = "s3://foobar/foo.zip"
function.Runtime = "foo"
function.Handler = "bar"
# When create FURL with AWS_IAM
function.FunctionUrlConfig = {"AuthType": "AWS_IAM"}

cfnResources = function.to_cloudformation(**self.kwargs)
generatedUrlList = [x for x in cfnResources if isinstance(x, LambdaPermission)]
# Then no permisssion should be auto created
self.assertEqual(generatedUrlList.__len__(), 0)
self.assertEqual(generatedUrlList.__len__(), 1)
self.assertEqual(generatedUrlList[0].Action, "lambda:InvokeFunctionUrl")
self.assertEqual(generatedUrlList[0].FunctionName, {"Ref": "foo"})
self.assertEqual(generatedUrlList[0].Principal, "*")
self.assertEqual(generatedUrlList[0].FunctionUrlAuthType, "NONE")

@patch("boto3.session.Session.region_name", "ap-southeast-1")
def test_with_invalid_function_url_config_with_authorization_type_value_as_None(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,6 @@
},
"Type": "AWS::IAM::Role"
},
"MyFunctionURLInvokeAllowPublicAccess": {
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Ref": "MyFunction"
},
"InvokedViaFunctionUrl": true,
"Principal": "*"
},
"Type": "AWS::Lambda::Permission"
},
"MyFunctionUrl": {
"Properties": {
"AuthType": "NONE",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,6 @@
},
"Type": "AWS::IAM::Role"
},
"MyFunctionURLInvokeAllowPublicAccess": {
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Ref": "MyFunctionAliaslive"
},
"InvokedViaFunctionUrl": true,
"Principal": "*"
},
"Type": "AWS::Lambda::Permission"
},
"MyFunctionUrl": {
"Properties": {
"AuthType": "NONE",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,6 @@
},
"Type": "AWS::IAM::Role"
},
"MyFunctionURLInvokeAllowPublicAccess": {
"Condition": "MyCondition",
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Ref": "MyFunction"
},
"InvokedViaFunctionUrl": true,
"Principal": "*"
},
"Type": "AWS::Lambda::Permission"
},
"MyFunctionUrl": {
"Condition": "MyCondition",
"Properties": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,6 @@
},
"Type": "AWS::IAM::Role"
},
"MyFunctionURLInvokeAllowPublicAccess": {
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Ref": "MyFunction"
},
"InvokedViaFunctionUrl": true,
"Principal": "*"
},
"Type": "AWS::Lambda::Permission"
},
"MyFunctionUrl": {
"Properties": {
"AuthType": "NONE",
Expand Down
Loading
Loading