-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
s3-notifications: Unable to update the s3 event notifications on an existing S3 bucket. #31303
s3-notifications: Unable to update the s3 event notifications on an existing S3 bucket. #31303
Comments
Yes this is reproducible. class IssueTriagePyStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
my_lambda = _lambda.Function(
self, 'HelloHandler',
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.from_asset('lambda'),
handler='hello.handler',
)
bucket = s3.Bucket.from_bucket_name(self, "Bucket", "my-existing-bucket-name")
notification = s3_notify.LambdaDestination(my_lambda)
notificationfilter1 = s3.NotificationKeyFilter(prefix="foo/", suffix="bar/")
bucket.add_event_notification(s3.EventType.OBJECT_CREATED, notification, notificationfilter1)
notificationfilter2 = s3.NotificationKeyFilter(prefix="fo1/",suffix="ba1/",)
bucket.add_event_notification(s3.EventType.OBJECT_CREATED, notification, notificationfilter2) On
BucketNotifications8F2E257D:
Type: Custom::S3BucketNotifications
Properties:
ServiceToken:
Fn::GetAtt:
- BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691
- Arn
BucketName: pahud-foo-bar
NotificationConfiguration:
LambdaFunctionConfigurations:
- Events:
- s3:ObjectCreated:*
Filter:
Key:
FilterRules:
- Name: suffix
Value: bar/
- Name: prefix
Value: foo/
LambdaFunctionArn:
Fn::GetAtt:
- HelloHandler2E4FBA4D
- Arn
- Events:
- s3:ObjectCreated:*
Filter:
Key:
FilterRules:
- Name: suffix
Value: ba1/
- Name: prefix
Value: fo1/
LambdaFunctionArn:
Fn::GetAtt:
- HelloHandler2E4FBA4D
- Arn
Managed: false
SkipDestinationValidation: false As I can't figure out any workaround. Making this a p1 bug. |
Facing the same issue: I previously defined two notifications, one with another with This configuration worked with 2.146.0, results in same issue by simply updating cdk to 2.155.0 |
I’ve been tracking down this same issue, and can confirm that I see an identical error when attempting to update to a new Lambda function ARN on an existing notification configured for an externally-defined bucket. Abbreviated version of my reproduction, first deployment succeeds: log_function = aws_lambda.Function(self, "Function1", …)
bucket.add_event_notification(
aws_s3.EventType.OBJECT_CREATED,
aws_s3_notifications.LambdaDestination(log_function),
aws_s3.NotificationKeyFilter(prefix="logs/resource-cdn/", suffix=".gz"),
) Second deployment fails: log_function = aws_lambda.Function(self, "Function2", …)
bucket.add_event_notification(
aws_s3.EventType.OBJECT_CREATED,
aws_s3_notifications.LambdaDestination(log_function),
aws_s3.NotificationKeyFilter(prefix="logs/resource-cdn/", suffix=".gz"),
) |
Looks like the the same issue #28915. I was able to reproduce in v2.147+ and it works fine in v2.146.0. However I don't see any related change in the diff. Need to look further into it. |
Hello everyone, here are my 2 cents. THIS IS NOT A SORTING PROBLEM. In CDK v2.3 the method used to verify if a notification configuration was external was based on the following check (this is from the Custom Resource behind aws_s3_notifications.LambdaDestination resource): In CDK v2.136 the method is this one (not checked when this change was introduced):
The function with_id(n) is this one:
The built-in function hash does not return the same value across different instances of python even if the input is the same. The Custom Resource will treat as external_notifications even the ones that are not, leading to duplicates EDIT: for versions older than Python 3.2 (included) the hash function generates the same value for the same input across different python instances. Starting from Python 3.3, the hash function starts with a random seed for each python instance. |
@xenonlcs Thanks for adding more context here. From the description, it looks like a different issue from the original issue. Do you mean |
Hi @xazhao, I will attach this screenshot to explain better what I mean: As you can see, stopping and restarting a new process of Python leads to the re-initialization of the built-in hash function with another seed. This behavior is introduced starting from version 3.3 of Python. I think that this is not a different issue cause as far as I can see in the code of the custom resource, no code could break due to some sorting problems (the checks are performed with Since the fact that So, in the Lambda function we can see that there are 3 different kinds of notification configurations:
The check to identify The Since the The final notification configuration is created merging the You can also verify the different hashes on the CloudTrail event for the event named Let me know if I can further explain my point, |
Thanks for the explanation. The sorting I added is not for This is why sorting matters -- objects will have different hash values:
and
When the lambda function is invoked, it will re-run hashing on those 2 lists (because it will not save the hashing value). No matter what seed it's using, the seed should be the same for calculating hashes for those 2 lists within one single lambda execution. |
Yep I agree, i got misled by a previous version of cdk (v2.136.0) in which there was no get_id function. |
…3 bucket (#31431) ### Issue # (if applicable) Closes #31303. ### Reason for this change During the update S3 bucket notifications, if there are multiple filter rules involved, the order of filter rules is different from CFN event notifications and S3 get notifications call. This will result different hash value which makes CDK unable to recognize s3 notifications created by the stack itself. ### Description of changes Sort the notifications filter rules by key when calculating the hash value. ### Description of how you validated changes Manually tested and integration tests. ### Checklist - [ ] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Comments on closed issues and PRs are hard for our team to see. |
Describe the bug
I am facing an error when trying to update the s3 event notification configuration on an existing S3 bucket using CDK.
Created a stack to add s3 event notification on an existing s3 bucket. Create operation goes through successfully.
When I update the cdk stack to add event notifications on the same s3 bucket, the Update operation fails with below error.
Error:
Here the lambda code backing the BucketNotifications custom resource is unable to identify that the existing event notifications were also managed by the same cdk stack thereby creating duplicate notifications resulting in error.
Regression Issue
Last Known Working CDK Version
No response
Expected Behavior
Should be able to add additional notification configuration on the existing s3 bucket.
Current Behavior
Issue
Created a cdk stack and added an event notification on an existing s3 bucket. Create operation is successful.
Updated the same stack to add a new event notification along with the existing ones. The update operation fails with below error.
Error:
Reproduction Steps
Steps:
1. Create a stack by commenting out the 2nd event notification (notificationfilter2)
2. once stack is created, update the stack after uncommenting the 2nd event notification.
Possible Solution
Analysis details:
Create a cdk stack to add below event notification to an existing s3 bucket. The Create operation is successful.
In the notifications-resource-handler code
For unmanaged buckets, there is a get_id function used to evaluate the hash for each event notification to confirm if this is created by the stack or is an existing external configuration:
During creation, this goes fine as it treats all existing configurations as external.
Then it appends incoming + external and creates the final notification configuration as expected.
During an update operation, the lambda code will first get the existing event notifications on the s3 bucket.
Then it validates if the existing event notifications matches the notification in the incoming request from Cloudformation.
It does this by evaluating the hash for each existing event notification and validating if this matches with the hash of the incoming event notifications from Cloudformation.
When there is a match, it identifies this existing event configuration as managed by the stack.
This helps in eliminating the duplicates.
There is an issue with this hash evaluation, due to a change in order of the prefix and suffix within the filter rules between the existing notification and the notification coming from Cloudformation.
Sample event notification from Cloudformation request
Sample existing S3 event notification:
Note: Even though the content of the above jsons are the same, the order of the filter rules (prefix and suffix) are different.
Due to this, the hash evaluated will also be different. So, it is unable to identify that the existing configuration was also added by the stack itself.
This ends up in a configuration which includes the duplicates (existing configurations on s3 + incoming event configuration from Cloudformation stack)
resulting in below error:
This can be workaround by changing the order of filters in the cdk synthesized stack template, by passing the prefix first and then suffix within the filter rules array.
Additional Information/Context
No response
CDK CLI Version
2.152.0
Framework Version
No response
Node.js Version
v20.16.0
OS
Linux
Language
Python
Language Version
No response
Other information
No response
The text was updated successfully, but these errors were encountered: