AWS CloudFormation を使用して、既存の S3 バケットに Lambda の Amazon S3 通知設定を作成する方法を教えてください。

最終更新日: 2020 年 7 月 8 日

AWS CloudFormation を使用して、既存の Amazon Simple Storage Service (Amazon S3) バケットに、AWS Lambda 関数の Amazon S3 通知設定を作成したいと考えています。

簡単な説明

Amazon S3 通知設定を作成するには、AWS CloudFormation を使用して新しい S3 バケットを作成します。次に、NotificationConfiguration プロパティを使用してそのバケットに通知設定を追加します。または、手動で既存の S3 バケットに通知設定を追加します。

ここに示す手順では、Python 3.6 で作成した Lambda-backed カスタムリソースにょり、AWS CloudFormation から既存の S3 バケットに通知設定を追加する方法を説明しています。カスタムリソースから Lambda 関数をトリガーすることで、この関数が PutBucketNotification API をトリガーし、S3 バケットに通知設定が追加されます。

解決方法

重要: 次の手順は、通知設定がまったく作成されていない S3 バケットでの S3 通知設定にのみ適用されます。S3 バケットに通知設定が既に存在するか、手動で作成された通知設定がある場合、次の手順を実行すると、それらの設定は上書きされます。

1.    次のコードを含む AWS CloudFormation テンプレートを LambdaS3.template という名前で作成します。

重要 : 次の例では、S3NotificationLambdaFunction リソースに S3 通知設定を追加しています。Lambda 関数 CustomResourceLambdaFunction により、S3NotificationLambdaFunctionに S3 通知設定を追加します。CustomResourceLambdaFunction リソース内のコードは、要件を満たすように変更できます。

AWSTemplateFormatVersion: 2010-09-09
Description: >-
  Sample template to illustrate use of existing S3 bucket as an event source for a Lambda function
Parameters:
  NotificationBucket:
    Type: String
    Description: S3 bucket that's used for the Lambda event notification

Resources:
  S3NotificationLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        ZipFile: !Join
          - |+

          - - import json
            - 'def lambda_handler(event,context):'
            - '    return ''Welcome... This is a test Lambda Function'''
      Handler: index.lambda_handler
      Role: !GetAtt LambdaIAMRole.Arn
      Runtime: python3.6
      Timeout: 5

  LambdaInvokePermission:
    Type: 'AWS::Lambda::Permission'
    Properties:
      FunctionName: !GetAtt S3NotificationLambdaFunction.Arn
      Action: 'lambda:InvokeFunction'
      Principal: s3.amazonaws.com
      SourceAccount: !Ref 'AWS::AccountId'
      SourceArn: !Sub 'arn:aws:s3:::${NotificationBucket}'

  LambdaIAMRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 's3:GetBucketNotification'
                  - 's3:PutBucketNotification'
                Resource: !Sub 'arn:aws:s3:::${NotificationBucket}'
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: 'arn:aws:logs:*:*:*'

  CustomResourceLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.lambda_handler
      Role: !GetAtt LambdaIAMRole.Arn
      Code:
        ZipFile: |

            from __future__ import print_function
            import json
            import boto3
            import cfnresponse
            
            SUCCESS = "SUCCESS"
            FAILED = "FAILED"
            
            print('Loading function')
            s3 = boto3.resource('s3')
            
            def lambda_handler(event, context):
                print("Received event: " + json.dumps(event, indent=2))
                responseData={}
                try:
                    if event['RequestType'] == 'Delete':
                        print("Request Type:",event['RequestType'])
                        Bucket=event['ResourceProperties']['Bucket']
                        delete_notification(Bucket)
                        print("Sending response to custom resource after Delete")
                    elif event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
                        print("Request Type:",event['RequestType'])
                        LambdaArn=event['ResourceProperties']['LambdaArn']
                        Bucket=event['ResourceProperties']['Bucket']
                        add_notification(LambdaArn, Bucket)
                        responseData={'Bucket':Bucket}
                        print("Sending response to custom resource")
                    responseStatus = 'SUCCESS'
                except Exception as e:
                    print('Failed to process:', e)
                    responseStatus = 'FAILURE'
                    responseData = {'Failure': 'Something bad happened.'}
                cfnresponse.send(event, context, responseStatus, responseData)

            def add_notification(LambdaArn, Bucket):
                bucket_notification = s3.BucketNotification(Bucket)
                response = bucket_notification.put(
                  NotificationConfiguration={
                    'LambdaFunctionConfigurations': [
                      {
                          'LambdaFunctionArn': LambdaArn,
                          'Events': [
                              's3:ObjectCreated:*'
                          ]
                      }
                    ]
                  }
                )
                print("Put request completed....")
              
            def delete_notification(Bucket):
                bucket_notification = s3.BucketNotification(Bucket)
                response = bucket_notification.put(
                    NotificationConfiguration={}
                )
                print("Delete request completed....")
      Runtime: python3.6
      Timeout: 50

  LambdaTrigger:
    Type: 'Custom::LambdaTrigger'
    DependsOn: LambdaInvokePermission
    Properties:
      ServiceToken: !GetAtt CustomResourceLambdaFunction.Arn
      LambdaArn: !GetAtt S3NotificationLambdaFunction.Arn
      Bucket: !Ref NotificationBucket

2.    LambdaS3.template ファイルを使用して AWS CloudFormation スタックを起動するには、AWS CloudFormation コンソールか、次の AWS コマンドラインインターフェイス(AWS CLI)コマンドを使用します。

aws cloudformation create-stack --stack-name lambda-s3-notification --template-body file://LambdaS3.template --parameters ParameterKey=NotificationBucket,ParameterValue=existing-bucket-for-lambda-notification --capabilities CAPABILITY_NAMED_IAM --region us-east-1

重要 : AWS CloudFormation スタックを起動するときは、S3 バケット(existing-bucket-for-lambda-notification)を渡す必要があります。

スタックが、Amazon S3 用の Lambda 関数と Lambda のアクセス許可を作成します。これで、S3 バケットに必要な通知設定が追加され、Lambda 通知に S3 バケットを使用できるようになります。


この記事はお役に立ちましたか?


請求に関するサポートまたは技術的なサポートが必要ですか?