@@ -130,6 +130,78 @@ def test_basic_function_with_url_config(self, file_name, qualifier):
130130 self .assertEqual (function_url_config ["Cors" ], cors_config )
131131 self ._assert_invoke (lambda_client , function_name , qualifier , 200 )
132132
133+
134+ @parameterized .expand (
135+ [
136+ ("single/basic_function_with_function_url_dual_auth" , None ),
137+ ("single/basic_function_with_function_url_with_autopuplishalias_dual_auth" , "live" ),
138+ ]
139+ )
140+ @skipIf (current_region_does_not_support ([LAMBDA_URL ]), "Lambda Url is not supported in this testing region" )
141+ def test_basic_function_with_url_dual_auth (self , file_name , qualifier ):
142+ """
143+ Creates a basic lambda function with Function Url with authtype: None
144+ Verifies that 2 AWS::Lambda::Permission resources are created:
145+ - lambda:InvokeFunctionUrl
146+ - lambda:InvokeFunction with InvokedViaFunctionUrl: True
147+ """
148+ self .create_and_verify_stack (file_name )
149+
150+ # Get Lambda permissions
151+ lambda_permissions = self .get_stack_resources ("AWS::Lambda::Permission" )
152+
153+ # Verify we have exactly 2 permissions
154+ self .assertEqual (len (lambda_permissions ), 2 , "Expected exactly 2 Lambda permissions" )
155+
156+ # Check for the expected permission logical IDs
157+ invoke_function_url_permission = None
158+ invoke_permission = None
159+
160+ for permission in lambda_permissions :
161+ logical_id = permission ["LogicalResourceId" ]
162+ if "MyLambdaFunctionUrlPublicPermissions" in logical_id :
163+ invoke_function_url_permission = permission
164+ elif "MyLambdaFunctionURLInvokeAllowPublicAccess" in logical_id :
165+ invoke_permission = permission
166+
167+ # Verify both permissions exist
168+ self .assertIsNotNone (invoke_function_url_permission , "Expected MyLambdaFunctionUrlPublicPermissions to exist" )
169+ self .assertIsNotNone (invoke_permission , "Expected MyLambdaFunctionURLInvokeAllowPublicAccess to exist" )
170+
171+ # Get the function name and URL
172+ function_name = self .get_physical_id_by_type ("AWS::Lambda::Function" )
173+ lambda_client = self .client_provider .lambda_client
174+
175+
176+
177+ # Get the function URL configuration to verify auth type
178+ function_url_config = (
179+ lambda_client .get_function_url_config (FunctionName = function_name , Qualifier = qualifier )
180+ if qualifier
181+ else lambda_client .get_function_url_config (FunctionName = function_name )
182+ )
183+
184+ # Verify the auth type is NONE
185+ self .assertEqual (function_url_config ["AuthType" ], "NONE" , "Expected AuthType to be NONE" )
186+
187+ # Get the template to check for InvokedViaFunctionUrl property
188+ cfn_client = self .client_provider .cfn_client
189+ template = cfn_client .get_template (StackName = self .stack_name )
190+ template_body = template ["TemplateBody" ]
191+
192+ # Check if the InvokePermission has InvokedViaFunctionUrl: True
193+ # This is a bit hacky but we don't have direct access to the resource properties
194+ # We're checking if the string representation of the template contains this property
195+ template_str = str (template_body )
196+ self .assertIn ("InvokedViaFunctionUrl" , template_str ,
197+ "Expected InvokedViaFunctionUrl property in the template" )
198+
199+ # Get the function URL from stack outputs
200+ function_url = self .get_stack_output ("FunctionUrl" )["OutputValue" ]
201+ # Invoke the function URL and verify the response
202+ self ._verify_get_request (function_url , self .FUNCTION_OUTPUT )
203+
204+
133205 @skipIf (current_region_does_not_support ([CODE_DEPLOY ]), "CodeDeploy is not supported in this testing region" )
134206 def test_function_with_deployment_preference_alarms_intrinsic_if (self ):
135207 self .create_and_verify_stack ("single/function_with_deployment_preference_alarms_intrinsic_if" )
0 commit comments