S3イベント通知の4つの送信先 – SNS/SQS/Lambda/EventBridge

S3イベント通知の4つの通知先 - SNS/SQS/Lambda/EventBridge

S3イベント通知の4つの送信先 – SNS/SQS/Lambda/EventBridge

以下のページで、S3のイベント通知機能を使用して、アップロードされた画像から、自動的にサムネイル画像を作成する構成をご紹介しました。

https://awstut.com/2023/01/15/trigger-image-upload-to-s3-invokes-lambda-function-to-create-thumbnails

上記ページでは、イベント通知でLambda関数をトリガーする構成でした。

今回はイベント通知の4つの送信先を確認します。

構築する環境

Diagram of 4 destinations for S3 event notifications - SNS/SQS/Lambda/EventBridge

S3バケットを作成します。
イベント通知機能を有効化します。
通知の送信先として、以下の4リソースを指定します。

  • Lambda関数
  • SQS
  • SNS
  • EventBridge

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-fa/tree/main/113

テンプレートファイルのポイント解説

S3バケット

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: Private
      BucketName: !Ref BucketName
      NotificationConfiguration:
        LambdaConfigurations:
          - Event: "s3:ObjectCreated:*"
            Function: !Ref Function1Arn
        QueueConfigurations:
          - Event: "s3:ObjectTagging:*"
            Queue: !Ref QueueArn
        TopicConfigurations:
          - Event: "s3:ObjectRemoved:*"
            Topic: !Ref TopicArn
        EventBridgeConfiguration:
          EventBridgeEnabled: true
Code language: YAML (yaml)

4つの通知先を指定します。

Lambda関数への通知は、LambdaConfigurationsプロパティを使用します。
イベント通知する条件ですが、「s3:ObjectCreated:*」を設定し、バケットにオブジェクトが設置された場合に、関数がトリガーされます。

SQSへの通知は、QueueConfigurationsプロパティを使用します。
イベント通知する条件ですが、「s3:ObjectTagging:*」を設定し、バケット内のオブジェクトにタグ設定(追加など)された場合に、SQSキューにメッセージが送信されます。

SNSへの通知は、TopicConfigurationsプロパティを使用します。
イベント通知する条件ですが、「s3:ObjectRemoved:*」を設定し、バケットからオブジェクトが削除された場合に、SNSトピックにメッセージが送信されます。

EventBridgeへの通知は、EventBridgeConfigurationプロパティを使用します。
このプロパティでEventBridgeへの通知を有効化します。

Lambda関数

Resources:
  Function1:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Code:
        ZipFile: |
          def lambda_handler(event, context):
            print(event)
      FunctionName: !Sub "${Prefix}-Function1"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt Function1Role.Arn
Code language: YAML (yaml)

イベント通知先のLambda関数です。

Lambda関数で実行するコードをインライン形式で記載します。
詳細につきましては、以下のページをご確認ください。

https://awstut.com/2022/02/02/3-patterns-for-creating-lambda-with-cloudformation

実行するコードですが、eventオブジェクトの中身を出力するシンプルな内容です。

ちなみに後述のSQS・SNS・EventBridgeでも、同様の内容の関数を実行します。

通知先をLambda関数にする場合の権限について確認します。
S3イベント通知でLambda関数をトリガーするということは、S3バケットがLambda関数を実行するという意味になります。
これはLambdaのリソースベースポリシーによって設定します。

Resources:
  S3Permission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref Function1
      Action: lambda:InvokeFunction
      Principal: s3.amazonaws.com
      SourceArn: !Sub "arn:aws:s3:::${BucketName}"
Code language: YAML (yaml)

先述のバケットがこの関数を呼び出すことを許可する内容です。

SQS

Resources:
  Queue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: !Sub "${Prefix}-Queue"
      ReceiveMessageWaitTimeSeconds: !Ref ReceiveMessageWaitTimeSeconds
      VisibilityTimeout: !Ref VisibilityTimeout
Code language: YAML (yaml)

イベント通知先のキューです。

SQSに関する基本的な事項については、以下のページをご確認ください。

https://awstut.com/2022/02/05/introduction-to-sqs-data-linkage-between-lambdas

通知先をSQSにする場合の権限について確認します。
S3イベント通知をSQSキューにメッセージングするということは、S3バケットがキューにメッセージを送信するという意味になります。
これはアクセスポリシーによって設定します。

Resources:
  QueuePolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - sqs:SendMessage
            Condition:
              ArnLike:
                aws:SourceArn: !Sub "arn:aws:s3:::${BucketName}"
              StringEquals:
                aws:SourceAccount: !Ref AWS::AccountId
            Effect: Allow
            Resource: !GetAtt Queue.Arn
            Principal:
              Service:
                - s3.amazonaws.com
      Queues:
        - !Ref Queue
Code language: YAML (yaml)

先述のバケットがこのキューにメッセージを送信することを許可する内容です。

今回はSQSキューにメッセージが格納された時に、自動的にLambda関数をトリガーするように設定します。

Resources:
  EventSourceMapping:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: !Ref BatchSize
      Enabled: true
      EventSourceArn: !Ref QueueArn
      FunctionName: !Ref Function2
Code language: YAML (yaml)

詳細につきましては、以下のページをご確認ください。

https://awstut.com/2023/01/22/triggering-lambda-function-from-sqs-queue

SNS

Resources:
  Topic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub "${Prefix}-Topic"
Code language: YAML (yaml)

イベント通知先のトピックです。

SNSに関する基本的な事項については、以下のページをご確認ください。

https://awstut.com/2022/07/30/introduction-to-sns-with-cfn-email

特別な設定は行いません。

通知先をSNSにする場合の権限について確認します。
S3イベント通知をSNSトピックにメッセージングするということは、S3バケットがトピックにメッセージを送信するという意味になります。
これはアクセスポリシーによって設定します。

Resources:
  TopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - sns:Publish
            Condition:
              ArnLike:
                aws:SourceArn: !Sub "arn:aws:s3:::${BucketName}"
              StringEquals:
                aws:SourceAccount: !Ref AWS::AccountId
            Effect: Allow
            Resource: !Ref Topic
            Principal:
              Service:
                - s3.amazonaws.com
      Topics:
        - !Ref Topic
Code language: YAML (yaml)

トピックのサブスクリプションはLambda関数を指定します。

Resources:
  TopicSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint: !GetAtt Function3.Arn
      Protocol: lambda
      TopicArn: !Ref SNSTopicArn
Code language: YAML (yaml)

詳細につきましては、以下のページをご確認ください。

https://awstut.com/2022/12/10/invoking-lambda-from-sns

EventBridge

Resources:
  EventsRule:
    Type: AWS::Events::Rule
    Properties:
      EventBusName: !Ref EventBusName
      EventPattern:
        source:
          - aws.s3
      Name: !Sub "${Prefix}-EventsRule"
      State: ENABLED
      Targets:
        - Arn: !Ref Function4Arn
          Id: !Ref Function4
Code language: YAML (yaml)

EventBridgeルールを作成します。

EventBridgeルールに関する基本的な事項は、以下のページをご確認ください。

https://awstut.com/2022/12/05/integrating-two-lambda-functions-using-eventbridge

今回はsourceの値が「aws.s3」であるルールを設け、これにマッチしたイベントをターゲットであるLambda関数に送信します。

ターゲットにLambda関数を指定する場合、EventBridgeが関数を呼び出すという挙動になります。
そのためEventBridgeに関数を呼び出す権限を与える必要があります。

Resources:
  EventsRulePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref Function4
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt EventsRule.Arn
Code language: YAML (yaml)

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

https://awstut.com/2021/12/02/cloudformation-nested-stacks

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • S3バケット:fa-113
  • SQSキュー:fa-113-Queue
  • SNSトピック:fa-113-Topic
  • EventBridgeルール:fa-113-EventsRule
  • Lambda関数1:fa-113-Function1

AWS Management Consoleから各リソースを確認します。

S3バケットを確認します。

Detail of S3 1.

4つの通知先が有効化されていることがわかります。

SQSを確認します。

Detail of SQS 1.

SQSキューが正常に作成されています。
Lambdaトリガーとして、関数2が指定されていることもわかります。
つまりS3バケットからこのSQSキューに対して、イベント通知が送信されると、自動的に関数2が実行されるということになります。

SNSを確認します。

Detail of SNS 1.

SNSトピックが正常に作成されています。
トピックのサブスクライバーとして、Lambda関数3が指定されていることがわかります。
つまりS3バケットからこのSNSトピックに対して、イベント通知が送信されると、自動的に関数3が実行されるということになります。

EventBridgeを確認します。

Detail of EventBridge 1.
Detail of EventBridge 2.

EventBridgeルールが正常に作成されています。
ルールのターゲットとして、Lambda関数4が指定されていることがわかります。
つまりS3バケットからルールにマッチするイベントが発信されると、自動的に関数4が実行されるということになります。

動作確認

準備が整いましたので、S3イベント通知のテストを行います。

Lambda関数へイベント通知

Lambda関数にイベント通知を行います。
今回、Lambda関数に通知する条件を「s3:ObjectCreated:*」としていますので、オブジェクトを配置します。

Detail of S3 2.

オブジェクトが設置されたことを受けて、関数1が自動的に実行されているはずです。

関数1の実行ログを確認します。

Detail of Lambda 1.

確かに関数1が実行されています。
eventNameの値を見ると、「ObjectCreated:Put」が確認できます。
このようにS3イベント通知を受けて、自動的にLambda関数を実行することができます。

SQSへイベント通知

SQSキューにイベント通知を行います。
今回、キューに通知する条件を「s3:ObjectTagging:*」としていますので、オブジェクトにタグを設定します。

Detail of S3 3.

キーが「foo」、値が「bar」というタグを設定しました。

これを受けてSQSキューにメッセージが送信されたはずです。
そしてこのキューにはLambdaトリガーを設定していますので、Lambda関数2が実行されるはずです。

関数2の実行ログを確認します。

Detail of Lambda 2.

確かに関数2が実行されています。
eventNameの値を見ると「ObjectTagging:Put」、Eventの値を見ると「s3:TestEvent」が確認できます。
このようにS3イベント通知を受けて、自動的にSQSキューにメッセージを通知することができます。

なお「s3:TestEvent」については、AWS公式では、以下の通り説明されています。

通知が最初に有効になったとき、s3:TestEvent が発生します。

Amazon SQS、Amazon SNS、Lambda を使用します

SNSへイベント通知

SNSトピックにイベント通知を行います。
今回、トピックに通知する条件を「s3:ObjectRemoved:*」としていますので、オブジェクトを削除します。

Detail of S3 4.

オブジェクトが削除されました。

これを受けてSNSトピックにメッセージが送信されたはずです。
そしてこのトピックのサブスクリプションにLambda3を設定していますので、Lambda関数3が実行されるはずです。

関数3の実行ログを確認します。

Detail of Lambda 3.

確かに関数3が実行されています。
eventNameの値を見ると、「ObjectRemoved:Delete」が確認できます。
このようにS3イベント通知を受けて、自動的にSNSトピックにメッセージを通知することができます。

EventBridgeへイベント通知

EventBridgeにイベント通知を行います。
今回、EventBridgeへの通知を有効化していますので、今までの操作(オブジェクト追加、タグ設定、オブジェクト削除)の度に通知されているはずです。
そしてEventBridgeルールのターゲットにLambda関数4を設定していますので、Lambda関数4が3回実行されるはずです。

Detail of Lambda 4.
Detail of Lambda 5.

確かに関数4が実行されています。
detail-typeの値を見ると、「Object Created」、「Object Tags Added」、「Object Deleted」が確認できます。
このようにS3イベント通知を受けて、自動的にEventBridgeにメッセージを通知することができます。

まとめ

S3イベント通知の4つの送信先を確認しました。