如何利用 CloudFormation 在現有 S3 儲存貯體上為 Lambda 建立 Amazon S3 通知組態?

3 分的閱讀內容
0

我想利用現有 Amazon Simple Storage Service (Amazon S3) 儲存貯體為 AWS Lambda 函數建立 Amazon S3 通知組態。

簡短描述

若要建立 Amazon S3 通知組態,請使用 CloudFormation 建立新的 S3 儲存貯體。然後,利用 NotificationConfiguration 屬性將通知組態加入儲存貯體。或者,手動將通知組態加入現有 S3 儲存貯體

下列步驟說明如何利用 CloudFormation 將通知組態加入現有 S3 儲存貯體。若要這麼做,請在 Python 3.9 建立由 Lambda 支援的自訂資源自訂資源會啟動 Lambda 函數, Lambda 函數 會啟動 PutBucketNotification API 以將通知組態加入您的 S3 儲存貯體。

注意: 如果您在執行 AWS Command Line Interface (AWS CLI) 命令時收到錯誤,請確認您使用的是最新的 AWS CLI 版本

解決方案

重要事項: 以下步驟僅適用於不具備現有通知組態的 S3 儲存貯體的 Amazon S3 通知組態。如果您的 S3 儲存貯體已存在現有或手動建立的通知組態,則以下步驟會覆寫這些組態。刪除堆疊後,Amazon S3 會移除所有通知。如果您的解決方案顯示為有效,那麼您的利用案例可能存在較不理想的組態。最佳做法是在將其部署到生產環境之前,先在測試 S3 儲存貯體上測試您的解決方案。

1.建立名為 LambdaS3.template 的 CloudFormation 範本,其中包含下列程式碼:

**重要事項:**在下列範例,您將 S3 通知組態加入 S3NotificationLambdaFunction。您利用 Lambda 函數 CustomResourceLambdaFunctionS3NotificationLambdaFunction 新增 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.9
      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 = 'FAILED'
                    responseData = {'Failure': 'Something bad happened.'}
                cfnresponse.send(event, context, responseStatus, responseData, "CustomResourcePhysicalID")

            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.9
      Timeout: 50

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

2.若要利用 LambdaS3.template 檔案啟動 CloudFormation 堆疊,請使用 CloudFormation 主控台或下列 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

重要事項: 當您啟動 CloudFormation 堆疊時,您必須傳入 S3 儲存貯體。例如,執行 existing-bucket-for-lambda-notification

堆疊會為 Amazon S3 建立 Lambda 函數和 Lambda 權限。由於堆疊已將所需的通知組態加入 S3 儲存貯體,因此您現在可利用 S3 儲存貯體來處理 Lambda 通知

AWS 官方
AWS 官方已更新 10 個月前