如何使用 CloudFormation 在现有 S3 存储桶上为 Lambda 创建 Amazon S3 通知配置?
我想使用现有的 Amazon Simple Storage Service (Amazon S3) 存储桶为 AWS Lambda 函数创建 Amazon S3 通知配置。
简短描述
要创建 Amazon S3 通知配置,请使用 CloudFormation 创建新的 S3 存储桶。然后,使用通知配置属性,向该存储桶添加通知配置。或手动向现有 S3 存储桶添加通知配置。
以下步骤向您展示如何使用 CloudFormation 向现有 S3 存储桶添加通知配置。为此,请在 Python 3.9 中创建一个由 Lambda 支持的自定义资源。自定义资源会启动 Lambda 函数,该函数启动 PutBucketNotification API,向您的 S3 存储桶添加通知配置。
**注意:**如果在运行 AWS 命令行界面(AWS CLI)命令时收到错误,请确保您使用的是最新的 AWS CLI 版本。
解决方法
**重要信息:**以下步骤仅适用于没有通知配置的 S3 存储桶的 Amazon S3 通知配置。如果您的 S3 存储桶已经有现有或手动创建的通知配置,则以下步骤会覆盖这些配置。删除堆栈后,Amazon S3 会删除所有通知。如果您的解决方案似乎可行,则表明您的用例中可能存在次优配置。最佳做法是先在测试 S3 存储桶上测试解决方案,然后再将其部署到生产环境。
1.创建一个名为 LambdaS3.template 的 CloudFormation 模板,其中包含以下代码:
**重要信息:**在以下示例中,将 S3 通知配置添加到 S3NotificationLambdaFunction 资源。您可以使用 Lambda 函数 CustomResourceLambdaFunction 将 S3 通知配置添加到 S3NotificationLambdaFunction。为了满足您的要求,您可以修改 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 官方已更新 1 年前
- AWS 官方已更新 3 个月前
- AWS 官方已更新 1 年前