From 4f6cb708ddfe88b04e5eab6897c1cec813ee0b53 Mon Sep 17 00:00:00 2001 From: Wing Fung Lau <4760060+hawflau@users.noreply.github.com> Date: Mon, 22 Aug 2022 11:41:46 -0700 Subject: [PATCH 1/2] Add validation for S3 NotificationConfiguration in Serverless Functino event source --- samtranslator/model/eventsources/push.py | 9 ++++-- ..._s3_lambda_configuration_invalid_type.yaml | 29 ++++++++++++++++++- ..._s3_lambda_configuration_invalid_type.json | 2 +- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/samtranslator/model/eventsources/push.py b/samtranslator/model/eventsources/push.py index 8c8df6d7e6..2041c01bfd 100644 --- a/samtranslator/model/eventsources/push.py +++ b/samtranslator/model/eventsources/push.py @@ -313,7 +313,7 @@ def to_cloudformation(self, **kwargs): # merging is literally "last one wins", which works fine because we linearly loop through the template once. # The de-dupe happens inside `samtranslator.translator.Translator.translate` method when merging results of # to_cloudformation() to output template. - self._inject_notification_configuration(function, bucket) + self._inject_notification_configuration(function, bucket, bucket_id) resources.append(S3Bucket.from_dict(bucket_id, bucket)) return resources @@ -378,7 +378,7 @@ def _depend_on_lambda_permissions_using_tag(self, bucket, permission): properties["Tags"] = tags + get_tag_list(dep_tag) return bucket - def _inject_notification_configuration(self, function, bucket): + def _inject_notification_configuration(self, function, bucket, bucket_id): base_event_mapping = {"Function": function.get_runtime_attr("arn")} if self.Filter is not None: @@ -407,13 +407,16 @@ def _inject_notification_configuration(self, function, bucket): notification_config = {} properties["NotificationConfiguration"] = notification_config + if not isinstance(notification_config, dict): + raise InvalidResourceException(bucket_id, "Invalid type for NotificationConfiguration. Must be a dict.") + lambda_notifications = notification_config.get("LambdaConfigurations", None) if lambda_notifications is None: lambda_notifications = [] notification_config["LambdaConfigurations"] = lambda_notifications if not isinstance(lambda_notifications, list): - raise InvalidResourceException(self.logical_id, "Invalid type for LambdaConfigurations. Must be a list.") + raise InvalidResourceException(bucket_id, "Invalid type for LambdaConfigurations. Must be a list.") for event_mapping in event_mappings: if event_mapping not in lambda_notifications: diff --git a/tests/translator/input/error_s3_lambda_configuration_invalid_type.yaml b/tests/translator/input/error_s3_lambda_configuration_invalid_type.yaml index 8cbefb041d..85d1a60544 100644 --- a/tests/translator/input/error_s3_lambda_configuration_invalid_type.yaml +++ b/tests/translator/input/error_s3_lambda_configuration_invalid_type.yaml @@ -21,4 +21,31 @@ Resources: NotificationConfiguration: LambdaConfigurations: Event: s3:ObjectCreated:Put - Function: arn:aws:iam::... \ No newline at end of file + Function: arn:aws:iam::... + + AnotherFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://bucket/key + Handler: app.lambdaHandler + Runtime: nodejs14.x + Architectures: + - x86_64 + Events: + S3Event: + Type: S3 + Properties: + Bucket: + Ref: AnotherBucket + Events: s3:ObjectCreated:* + + AnotherBucket: + Type: AWS::S3::Bucket + Properties: + NotificationConfiguration: + - Event: s3:ObjectCreated:* + Function: + Fn::GetAtt: + - AnotherFunction + - Arn + \ No newline at end of file diff --git a/tests/translator/output/error_s3_lambda_configuration_invalid_type.json b/tests/translator/output/error_s3_lambda_configuration_invalid_type.json index 8cab9d0b80..f98b2d99ea 100644 --- a/tests/translator/output/error_s3_lambda_configuration_invalid_type.json +++ b/tests/translator/output/error_s3_lambda_configuration_invalid_type.json @@ -4,5 +4,5 @@ "errorMessage": "Resource with id [AppFunctionS3Event] is invalid. Invalid type for LambdaConfigurations. Must be a list." } ], - "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [AppFunctionS3Event] is invalid. Invalid type for LambdaConfigurations. Must be a list." + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 2. Resource with id [AnotherBucket] is invalid. Invalid type for NotificationConfiguration. Must be a dict. Resource with id [RandomBucket] is invalid. Invalid type for LambdaConfigurations. Must be a list." } \ No newline at end of file From 7a41cbf9cd0c4b967557fc3ebfe3a2c6b0ed27af Mon Sep 17 00:00:00 2001 From: Wing Fung Lau <4760060+hawflau@users.noreply.github.com> Date: Mon, 22 Aug 2022 15:53:27 -0700 Subject: [PATCH 2/2] Update error message --- samtranslator/model/eventsources/push.py | 2 +- .../output/error_s3_lambda_configuration_invalid_type.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samtranslator/model/eventsources/push.py b/samtranslator/model/eventsources/push.py index 2041c01bfd..79c5a9d338 100644 --- a/samtranslator/model/eventsources/push.py +++ b/samtranslator/model/eventsources/push.py @@ -408,7 +408,7 @@ def _inject_notification_configuration(self, function, bucket, bucket_id): properties["NotificationConfiguration"] = notification_config if not isinstance(notification_config, dict): - raise InvalidResourceException(bucket_id, "Invalid type for NotificationConfiguration. Must be a dict.") + raise InvalidResourceException(bucket_id, "Invalid type for NotificationConfiguration.") lambda_notifications = notification_config.get("LambdaConfigurations", None) if lambda_notifications is None: diff --git a/tests/translator/output/error_s3_lambda_configuration_invalid_type.json b/tests/translator/output/error_s3_lambda_configuration_invalid_type.json index f98b2d99ea..e5d7c04809 100644 --- a/tests/translator/output/error_s3_lambda_configuration_invalid_type.json +++ b/tests/translator/output/error_s3_lambda_configuration_invalid_type.json @@ -4,5 +4,5 @@ "errorMessage": "Resource with id [AppFunctionS3Event] is invalid. Invalid type for LambdaConfigurations. Must be a list." } ], - "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 2. Resource with id [AnotherBucket] is invalid. Invalid type for NotificationConfiguration. Must be a dict. Resource with id [RandomBucket] is invalid. Invalid type for LambdaConfigurations. Must be a list." + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 2. Resource with id [AnotherBucket] is invalid. Invalid type for NotificationConfiguration. Resource with id [RandomBucket] is invalid. Invalid type for LambdaConfigurations. Must be a list." } \ No newline at end of file