S3のadd_event_notificationのハマりポイント

2024/02/27に公開

CDKでS3のPubObjectイベントをLambdaで受け取ろうとCDKを書いた時にいくつかハマりポイントがありました。ハマりポイントの紹介とその対応方法を残しておきます。

環境

確認したバージョンは下記です。

  • Python3.9以上
  • aws-cdk-lib=2.128.0

1. サンプルコードに書かれている通りに書いても動かない

まずは書いてみます。ちなみにこのコードは正しくないです。

import aws_cdk as cdk
from aws_cdk import aws_lambda
from aws_cdk import aws_s3_notifications
from aws_cdk import aws_s3

class FooStack(cdk.Stack):
    def __init__(self, scope, id, **kwargs):
        super().__init__(scope, id, **kwargs)

        bucket = aws_s3.Bucket.from_bucket_name(
            self,
            "hoo",
            bucket_name="test-bucket",
        )

        lambda_function = aws_lambda.Function(
            self,
            "s3_monitoring_lambda",
            function_name="fn_monitoring",
            # 詳細は省略
        )

        bucket.add_event_notification(
            aws_s3.EventType.OBJECT_CREATED,
            aws_s3_notifications.LambdaDestination(lambda_function),
            prefix="/home/myusername/*",
        )

bucketのadd_event_notificationには下記のドキュメントがありますが、このサンプルコードは誤っています。

# my_lambda: lambda.Function

bucket = s3.Bucket(self, "MyBucket")
bucket.add_event_notification(s3.EventType.OBJECT_CREATED, s3n.LambdaDestination(my_lambda), prefix="home/myusername/*")

公式のissueでも言及されています。
https://github.com/aws/aws-cdk/issues/27038
なぜそうなってしまったかは分かりますが、そのままにするのは理解できません。

正しくは下記のように書く必要があります。

bucket.add_event_notification(
    aws_s3.EventType.OBJECT_CREATED,
    aws_s3_notifications.LambdaDestination(lambda_function),
    aws_s3.NotificationKeyFilter(
        prefix="/home/myusername/*",
    ),
)

2. prefixとsuffixはurlエンコードする必要がある

タイトルそのままです。URLエンコードしましょう。

bucket.add_event_notification(
    aws_s3.EventType.OBJECT_CREATED,
    aws_s3_notifications.LambdaDestination(lambda_function),
    aws_s3.NotificationKeyFilter(
        prefix=urllib.parse.quote("/hoge=111/data/*"),
    ),
)

Note
A wildcard character ("*") can't be used in filters as a prefix or suffix. If your prefix or suffix contains a space, you must replace it with the "+" character. If you use any other special characters in the value of the prefix or suffix, you must enter them in URL-encoded (percent-encoded) format. For a complete list of special characters that must be converted to URL-encoded format when used in a prefix or suffix for event notifications, see Safe characters.

https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-filtering.html#notification-how-to-filtering-example-valid

参考

https://github.com/aws/aws-cdk/issues/27038
https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-filtering.html#notification-how-to-filtering-example-valid
https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html#object-key-guidelines-safe-characters

Discussion