From b2fd0e7ef0d60bc7efae5d49adba31e881e9ed0b Mon Sep 17 00:00:00 2001 From: Or Cohen <351445+lightpriest@users.noreply.github.com> Date: Fri, 22 Jul 2022 17:40:25 +0300 Subject: [PATCH 1/5] feat: Add State Property to Schedule EventSource (#1666) Co-authored-by: Or Cohen Co-authored-by: Jacob Fuss --- samtranslator/model/eventsources/push.py | 9 + .../test_schedule_event_source.py | 39 +++- ..._function_with_invalid_schedule_event.yaml | 18 ++ .../function_with_event_schedule_state.yaml | 35 ++++ .../function_with_event_schedule_state.json | 176 ++++++++++++++++++ .../function_with_event_schedule_state.json | 176 ++++++++++++++++++ ..._function_with_invalid_schedule_event.json | 8 + .../function_with_event_schedule_state.json | 176 ++++++++++++++++++ 8 files changed, 636 insertions(+), 1 deletion(-) create mode 100644 tests/translator/input/error_function_with_invalid_schedule_event.yaml create mode 100644 tests/translator/input/function_with_event_schedule_state.yaml create mode 100644 tests/translator/output/aws-cn/function_with_event_schedule_state.json create mode 100644 tests/translator/output/aws-us-gov/function_with_event_schedule_state.json create mode 100644 tests/translator/output/error_function_with_invalid_schedule_event.json create mode 100644 tests/translator/output/function_with_event_schedule_state.json diff --git a/samtranslator/model/eventsources/push.py b/samtranslator/model/eventsources/push.py index 93ed5592f..8c8df6d7e 100644 --- a/samtranslator/model/eventsources/push.py +++ b/samtranslator/model/eventsources/push.py @@ -96,6 +96,7 @@ class Schedule(PushEventSource): "Schedule": PropertyType(True, is_str()), "Input": PropertyType(False, is_str()), "Enabled": PropertyType(False, is_type(bool)), + "State": PropertyType(False, is_str()), "Name": PropertyType(False, is_str()), "Description": PropertyType(False, is_str()), "DeadLetterConfig": PropertyType(False, is_type(dict)), @@ -122,8 +123,16 @@ def to_cloudformation(self, **kwargs): resources.append(events_rule) events_rule.ScheduleExpression = self.Schedule + + if self.State and self.Enabled is not None: + raise InvalidEventException(self.relative_id, "State and Enabled Properties cannot both be specified.") + + if self.State: + events_rule.State = self.State + if self.Enabled is not None: events_rule.State = "ENABLED" if self.Enabled else "DISABLED" + events_rule.Name = self.Name events_rule.Description = self.Description diff --git a/tests/model/eventsources/test_schedule_event_source.py b/tests/model/eventsources/test_schedule_event_source.py index 2dff522ca..78a9e49e6 100644 --- a/tests/model/eventsources/test_schedule_event_source.py +++ b/tests/model/eventsources/test_schedule_event_source.py @@ -1,9 +1,9 @@ -from unittest.mock import Mock, patch from unittest import TestCase from samtranslator.model.eventsources.push import Schedule from samtranslator.model.lambda_ import LambdaFunction from samtranslator.model.exceptions import InvalidEventException +from parameterized import parameterized class ScheduleEventSource(TestCase): @@ -13,6 +13,27 @@ def setUp(self): self.schedule_event_source.Schedule = "rate(1 minute)" self.func = LambdaFunction("func") + def test_to_cloudformation_returns_permission_and_schedule_resources(self): + resources = self.schedule_event_source.to_cloudformation(function=self.func) + self.assertEqual(len(resources), 2) + self.assertEqual(resources[0].resource_type, "AWS::Events::Rule") + self.assertEqual(resources[1].resource_type, "AWS::Lambda::Permission") + + schedule = resources[0] + self.assertEqual(schedule.ScheduleExpression, "rate(1 minute)") + self.assertIsNone(schedule.State) + + def test_to_cloudformation_transforms_enabled_boolean_to_state(self): + self.schedule_event_source.Enabled = True + resources = self.schedule_event_source.to_cloudformation(function=self.func) + schedule = resources[0] + self.assertEqual(schedule.State, "ENABLED") + + self.schedule_event_source.Enabled = False + resources = self.schedule_event_source.to_cloudformation(function=self.func) + schedule = resources[0] + self.assertEqual(schedule.State, "DISABLED") + def test_to_cloudformation_with_retry_policy(self): retry_policy = {"MaximumRetryAttempts": "10", "MaximumEventAgeInSeconds": "300"} self.schedule_event_source.RetryPolicy = retry_policy @@ -70,3 +91,19 @@ def test_to_cloudformation_with_dlq_generated_with_intrinsic_function_custom_log self.schedule_event_source.DeadLetterConfig = dead_letter_config with self.assertRaises(InvalidEventException): self.schedule_event_source.to_cloudformation(function=self.func) + + @parameterized.expand( + [ + (True, "Enabled"), + (True, "Disabled"), + (True, {"FN:FakeIntrinsic": "something"}), + (False, "Enabled"), + (False, "Disabled"), + (False, {"FN:FakeIntrinsic": "something"}), + ] + ) + def test_to_cloudformation_invalid_defined_both_enabled_and_state_provided(self, enabled_value, state_value): + self.schedule_event_source.Enabled = enabled_value + self.schedule_event_source.State = state_value + with self.assertRaises(InvalidEventException): + self.schedule_event_source.to_cloudformation(function=self.func) diff --git a/tests/translator/input/error_function_with_invalid_schedule_event.yaml b/tests/translator/input/error_function_with_invalid_schedule_event.yaml new file mode 100644 index 000000000..eb6bbffea --- /dev/null +++ b/tests/translator/input/error_function_with_invalid_schedule_event.yaml @@ -0,0 +1,18 @@ +Transform: "AWS::Serverless-2016-10-31" + +Resources: + ScheduledFunction: + Type: 'AWS::Serverless::Function' + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip?versionId=3Tcgv52_0GaDvhDva4YciYeqRyPnpIcO + Handler: hello.handler + Runtime: python3.10 + Events: + Schedule1: + Type: Schedule + Properties: + Schedule: 'rate(1 minute)' + Name: test-schedule + Description: Test Schedule + State: "Enabled" + Enabled: True \ No newline at end of file diff --git a/tests/translator/input/function_with_event_schedule_state.yaml b/tests/translator/input/function_with_event_schedule_state.yaml new file mode 100644 index 000000000..17a13f654 --- /dev/null +++ b/tests/translator/input/function_with_event_schedule_state.yaml @@ -0,0 +1,35 @@ +Transform: "AWS::Serverless-2016-10-31" +Parameters: + ScheduleState: + Type: String + Default: Disabled + +Resources: + ScheduledFunction: + Type: 'AWS::Serverless::Function' + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip?versionId=3Tcgv52_0GaDvhDva4YciYeqRyPnpIcO + Handler: hello.handler + Runtime: python3.10 + Events: + Schedule1: + Type: Schedule + Properties: + Schedule: 'rate(1 minute)' + Name: test-schedule + Description: Test Schedule + State: "Enabled" + Schedule2: + Type: Schedule + Properties: + Schedule: 'rate(1 minute)' + Name: test-schedule + Description: Test Schedule + State: !Sub "Enabled" + Schedule3: + Type: Schedule + Properties: + Schedule: 'rate(1 minute)' + Name: test-schedule + Description: Test Schedule + State: !Ref ScheduleState \ No newline at end of file diff --git a/tests/translator/output/aws-cn/function_with_event_schedule_state.json b/tests/translator/output/aws-cn/function_with_event_schedule_state.json new file mode 100644 index 000000000..7f816444c --- /dev/null +++ b/tests/translator/output/aws-cn/function_with_event_schedule_state.json @@ -0,0 +1,176 @@ +{ + "Parameters": { + "ScheduleState": { + "Type": "String", + "Default": "Disabled" + } + }, + "Resources": { + "ScheduledFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip", + "S3ObjectVersion": "3Tcgv52_0GaDvhDva4YciYeqRyPnpIcO" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "ScheduledFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "ScheduledFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "ScheduledFunctionSchedule1": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": "Enabled", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule1LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule1Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule1", + "Arn" + ] + } + } + }, + "ScheduledFunctionSchedule2": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": { + "Fn::Sub": "Enabled" + }, + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule2LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule2Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule2", + "Arn" + ] + } + } + }, + "ScheduledFunctionSchedule3": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": { + "Ref": "ScheduleState" + }, + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule3LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule3Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule3", + "Arn" + ] + } + } + } + } + } \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/function_with_event_schedule_state.json b/tests/translator/output/aws-us-gov/function_with_event_schedule_state.json new file mode 100644 index 000000000..a49503a4e --- /dev/null +++ b/tests/translator/output/aws-us-gov/function_with_event_schedule_state.json @@ -0,0 +1,176 @@ +{ + "Parameters": { + "ScheduleState": { + "Type": "String", + "Default": "Disabled" + } + }, + "Resources": { + "ScheduledFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip", + "S3ObjectVersion": "3Tcgv52_0GaDvhDva4YciYeqRyPnpIcO" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "ScheduledFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "ScheduledFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "ScheduledFunctionSchedule1": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": "Enabled", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule1LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule1Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule1", + "Arn" + ] + } + } + }, + "ScheduledFunctionSchedule2": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": { + "Fn::Sub": "Enabled" + }, + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule2LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule2Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule2", + "Arn" + ] + } + } + }, + "ScheduledFunctionSchedule3": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": { + "Ref": "ScheduleState" + }, + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule3LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule3Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule3", + "Arn" + ] + } + } + } + } + } \ No newline at end of file diff --git a/tests/translator/output/error_function_with_invalid_schedule_event.json b/tests/translator/output/error_function_with_invalid_schedule_event.json new file mode 100644 index 000000000..8311582e4 --- /dev/null +++ b/tests/translator/output/error_function_with_invalid_schedule_event.json @@ -0,0 +1,8 @@ +{ + "errors": [ + { + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [ScheduledFunction] is invalid. Event with id [Schedule1] is invalid. State and Enabled Properties cannot both be specified." + } + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [ScheduledFunction] is invalid. Event with id [Schedule1] is invalid. State and Enabled Properties cannot both be specified." + } \ No newline at end of file diff --git a/tests/translator/output/function_with_event_schedule_state.json b/tests/translator/output/function_with_event_schedule_state.json new file mode 100644 index 000000000..04f1131b6 --- /dev/null +++ b/tests/translator/output/function_with_event_schedule_state.json @@ -0,0 +1,176 @@ +{ + "Parameters": { + "ScheduleState": { + "Type": "String", + "Default": "Disabled" + } + }, + "Resources": { + "ScheduledFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip", + "S3ObjectVersion": "3Tcgv52_0GaDvhDva4YciYeqRyPnpIcO" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "ScheduledFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "ScheduledFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "ScheduledFunctionSchedule1": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": "Enabled", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule1LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule1Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule1", + "Arn" + ] + } + } + }, + "ScheduledFunctionSchedule2": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": { + "Fn::Sub": "Enabled" + }, + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule2LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule2Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule2", + "Arn" + ] + } + } + }, + "ScheduledFunctionSchedule3": { + "Type": "AWS::Events::Rule", + "Properties": { + "Description": "Test Schedule", + "Name": "test-schedule", + "ScheduleExpression": "rate(1 minute)", + "State": { + "Ref": "ScheduleState" + }, + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "ScheduledFunction", + "Arn" + ] + }, + "Id": "ScheduledFunctionSchedule3LambdaTarget" + } + ] + } + }, + "ScheduledFunctionSchedule3Permission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "ScheduledFunction" + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "ScheduledFunctionSchedule3", + "Arn" + ] + } + } + } + } + } \ No newline at end of file From a62445183294a3019ae82b1aa0868d0083031612 Mon Sep 17 00:00:00 2001 From: Mohamed Elasmar <71043312+moelasmar@users.noreply.github.com> Date: Fri, 22 Jul 2022 11:16:09 -0700 Subject: [PATCH 2/5] chore: Add capability to disable S3 Events integration test cases. (#2454) * chore: Add capability to disable S3 Events integration test cases. * fix black issue --- integration/combination/test_function_with_s3_bucket.py | 5 +++++ integration/config/service_names.py | 1 + 2 files changed, 6 insertions(+) diff --git a/integration/combination/test_function_with_s3_bucket.py b/integration/combination/test_function_with_s3_bucket.py index 90ddb3016..574ee7bc8 100644 --- a/integration/combination/test_function_with_s3_bucket.py +++ b/integration/combination/test_function_with_s3_bucket.py @@ -1,6 +1,11 @@ +from unittest.case import skipIf + from integration.helpers.base_test import BaseTest +from integration.helpers.resource import current_region_does_not_support +from integration.config.service_names import S3_EVENTS +@skipIf(current_region_does_not_support([S3_EVENTS]), "S3 Events feature is not supported in this testing region") class TestFunctionWithS3Bucket(BaseTest): def test_function_with_s3_bucket_trigger(self): self.create_and_verify_stack("combination/function_with_s3") diff --git a/integration/config/service_names.py b/integration/config/service_names.py index f74783f4c..8d5d603dd 100644 --- a/integration/config/service_names.py +++ b/integration/config/service_names.py @@ -23,3 +23,4 @@ CUSTOM_DOMAIN = "CustomDomain" ARM = "ARM" EFS = "EFS" +S3_EVENTS = "S3Events" From 90b55e5a38262d26d7771c8840677de3d5195f75 Mon Sep 17 00:00:00 2001 From: Qingchuan Ma <69653965+qingchm@users.noreply.github.com> Date: Mon, 25 Jul 2022 12:59:42 -0700 Subject: [PATCH 3/5] chore: Add region skip condition and retry for http test (#2455) * Add skip and retry for http test * Black reformatting --- .../test_function_with_http_api_and_auth.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/integration/single/test_function_with_http_api_and_auth.py b/integration/single/test_function_with_http_api_and_auth.py index 22b9baef5..7a1d603fa 100644 --- a/integration/single/test_function_with_http_api_and_auth.py +++ b/integration/single/test_function_with_http_api_and_auth.py @@ -1,11 +1,27 @@ +import logging +from unittest.case import skipIf + +from tenacity import stop_after_attempt, retry_if_exception_type, after_log, wait_exponential, retry, wait_random + from integration.helpers.base_test import BaseTest +from integration.helpers.resource import current_region_does_not_support + +LOG = logging.getLogger(__name__) +@skipIf(current_region_does_not_support(["HttpApi"]), "HttpApi is not supported in this testing region") class TestFunctionWithHttpApiAndAuth(BaseTest): """ AWS::Lambda::Function tests with http api events and auth """ + @retry( + stop=stop_after_attempt(5), + wait=wait_exponential(multiplier=1, min=4, max=10) + wait_random(0, 1), + retry=retry_if_exception_type(AssertionError), + after=after_log(LOG, logging.WARNING), + reraise=True, + ) def test_function_with_http_api_and_auth(self): # If the request is not signed, which none of the below are, IAM will respond with a "Forbidden" message. # We are not testing that IAM auth works here, we are simply testing if it was applied. From 4dfb963317a2ee5fb9c9792352e78d094a761074 Mon Sep 17 00:00:00 2001 From: Wing Fung Lau <4760060+hawflau@users.noreply.github.com> Date: Mon, 25 Jul 2022 13:03:48 -0700 Subject: [PATCH 4/5] Add validation for swagger security when ApiKeyRequired is true (#2456) --- samtranslator/swagger/swagger.py | 13 +++++- ...curity_not_dict_with_api_key_required.yaml | 45 +++++++++++++++++++ .../error_swagger_security_not_dict.json | 2 +- ...curity_not_dict_with_api_key_required.json | 3 ++ 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 tests/translator/input/error_swagger_security_not_dict_with_api_key_required.yaml create mode 100644 tests/translator/output/error_swagger_security_not_dict_with_api_key_required.json diff --git a/samtranslator/swagger/swagger.py b/samtranslator/swagger/swagger.py index 28cf84a4f..934495599 100644 --- a/samtranslator/swagger/swagger.py +++ b/samtranslator/swagger/swagger.py @@ -647,7 +647,10 @@ def set_path_default_authorizer( # We want to ensure only a single Authorizer security entry exists while keeping everything else for security in existing_security: SwaggerEditor.validate_is_dict( - security, "{} in Security for path {} is not a valid dictionary.".format(security, path) + security, + "{} in Security for path {} method {} is not a valid dictionary.".format( + security, path, method_name + ), ) if authorizer_names.isdisjoint(security.keys()): existing_non_authorizer_security.append(security) @@ -703,7 +706,7 @@ def set_path_default_apikey_required(self, path): :param string path: Path name """ - for _, method_definition in self.iter_on_all_methods_for_path(path): + for method_name, method_definition in self.iter_on_all_methods_for_path(path): existing_security = method_definition.get("security", []) apikey_security_names = set(["api_key", "api_key_false"]) existing_non_apikey_security = [] @@ -714,6 +717,12 @@ def set_path_default_apikey_required(self, path): # (e.g. sigv4 (AWS_IAM), authorizers, NONE (marker for ignoring default authorizer)) # We want to ensure only a single ApiKey security entry exists while keeping everything else for security in existing_security: + SwaggerEditor.validate_is_dict( + security, + "{} in Security for path {} method {} is not a valid dictionary.".format( + security, path, method_name + ), + ) if apikey_security_names.isdisjoint(security.keys()): existing_non_apikey_security.append(security) else: diff --git a/tests/translator/input/error_swagger_security_not_dict_with_api_key_required.yaml b/tests/translator/input/error_swagger_security_not_dict_with_api_key_required.yaml new file mode 100644 index 000000000..85b4dea6d --- /dev/null +++ b/tests/translator/input/error_swagger_security_not_dict_with_api_key_required.yaml @@ -0,0 +1,45 @@ +transformId: AWS::Serverless-2016-10-31 +AWSTemplateFormatVersion: '2010-09-09' +Resources: + AuthFunction: + Type: AWS::Serverless::Function + AccessingPartyAPI: + Type: AWS::Serverless::Api + Properties: + EndpointConfiguration: REGIONAL + StageName: demo + Auth: + ApiKeyRequired: true + + DefinitionBody: + paths: + "/path": + put: + responses: + '201': + content: + application/json: + schema: + "$ref": "abcd" + x-amazon-apigateway-integration: + contentHandling: CONVERT_TO_TEXT + responses: + default: + statusCode: '200' + uri: + Fn::Sub: foobar + httpMethod: POST + passthroughBehavior: when_no_match + type: aws_proxy + requestBody: + content: + application/json: + schema: + required: + - readoutId + - status + type: object + security: + - [] + + openapi: 3.0.3 diff --git a/tests/translator/output/error_swagger_security_not_dict.json b/tests/translator/output/error_swagger_security_not_dict.json index 9f00e5bbf..bcf03cb96 100644 --- a/tests/translator/output/error_swagger_security_not_dict.json +++ b/tests/translator/output/error_swagger_security_not_dict.json @@ -1,3 +1,3 @@ { - "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Structure of the SAM template is invalid. CustomAuthorizer in Security for path /path is not a valid dictionary." + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Structure of the SAM template is invalid. CustomAuthorizer in Security for path /path method put is not a valid dictionary." } \ No newline at end of file diff --git a/tests/translator/output/error_swagger_security_not_dict_with_api_key_required.json b/tests/translator/output/error_swagger_security_not_dict_with_api_key_required.json new file mode 100644 index 000000000..b6fac4d52 --- /dev/null +++ b/tests/translator/output/error_swagger_security_not_dict_with_api_key_required.json @@ -0,0 +1,3 @@ +{ + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Structure of the SAM template is invalid. [] in Security for path /path method put is not a valid dictionary." +} \ No newline at end of file From 1eebf867e06c86759f37c3956df1e0b91d79065f Mon Sep 17 00:00:00 2001 From: aws-sam-cli-bot <46753707+aws-sam-cli-bot@users.noreply.github.com> Date: Mon, 8 Aug 2022 11:08:38 -0700 Subject: [PATCH 5/5] chore: bump version to 1.49.0 --- samtranslator/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samtranslator/__init__.py b/samtranslator/__init__.py index 9730661aa..94b9a2003 100644 --- a/samtranslator/__init__.py +++ b/samtranslator/__init__.py @@ -1 +1 @@ -__version__ = "1.48.0" +__version__ = "1.49.0"