如何解决将 AWS Lambda 函数订阅到 AWS CloudFormation 中基于推送的事件源时收到的错误?
我无法将 AWS Lambda 函数订阅到我的 AWS CloudFormation 堆栈中的 Amazon Simple Storage Service (Amazon S3) 事件通知或 Amazon Simple Notification Service (Amazon SNS) 主题。如果使用 AWS::Lambda::EventSourceMapping 资源,我将收到以下错误:“Unrecognized event source, must be kinesis or dynamodb stream(无法识别的事件源,必须是 kinesis 或 dynamodb 流)。”
简短描述
AWS::Lambda::EventSourceMapping 资源为基于提取的事件源设计,例如 Amazon DynamoDB 事件流和 Amazon Kinesis。借助基于推送的事件源,例如 Amazon S3 事件通知或 Amazon SNS 消息,事件源负责调用 Lambda 函数。为了使推送事件源调用 Lambda 函数时,该函数的资源策略必须授权受支持的事件源。
解决方法
在您的 AWS CloudFormation 模板,使用 AWS::Lambda::Permission 资源添加一个基于资源的策略。
例如,下面的基于资源的策略允许 Amazon SNS 主题调用 Lambda 函数:
"LambdaResourcePolicy": { "Type": "AWS::Lambda::Permission", "Properties": { "FunctionName" : { "Ref" : "MyFunction" }, "Principal": "sns.amazonaws.com", "Action": "lambda:InvokeFunction", "SourceArn" : { "Ref" : "MySNSTopic" } } }
对于 Amazon SNS 主题事件源,您必须使用所需的权限定义主题策略。
对于 Amazon S3 事件源,您必须使用通知配置语句将 Lambda 函数订阅到 Amazon S3 存储桶。例如:
{ "AWSTemplateFormatVersion": "2010-09-09", "Parameters": { "BucketPrefix": { "Type": "String", "Default": "test-bucket-name" } }, "Resources": { "EncryptionServiceBucket": { "DependsOn": "LambdaInvokePermission", "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { "Fn::Sub": "${BucketPrefix}-encryption-service" }, "NotificationConfiguration": { "LambdaConfigurations": [ { "Function": { "Fn::GetAtt": [ "AppendItemToListFunction", "Arn" ] }, "Event": "s3:ObjectCreated:*", "Filter": { "S3Key": { "Rules": [ { "Name": "suffix", "Value": "zip" } ] } } } ] } } }, "LambdaInvokePermission": { "Type": "AWS::Lambda::Permission", "Properties": { "FunctionName": { "Fn::GetAtt": [ "AppendItemToListFunction", "Arn" ] }, "Action": "lambda:InvokeFunction", "Principal": "s3.amazonaws.com", "SourceAccount": { "Ref": "AWS::AccountId" }, "SourceArn": { "Fn::Sub": "arn:aws:s3:::${BucketPrefix}-encryption-service" } } }, "AppendItemToListFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "LambdaExecutionRole", "Arn" ] }, "Code": { "ZipFile": { "Fn::Join": [ "", [ "exports.handler = function(event, context) {", "console.log('Received event: ', JSON.stringify(event, null, 2));", "};" ] ] } }, "Runtime": "nodejs8.10" } }, "LambdaExecutionRole": { "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": [ "logs:*" ], "Resource": "arn:aws:logs:*:*:log-group:/path/<log-group-name>:log-stream:<log-stream-name>" } ] } } ] } } } }
在前面的示例中,S3 存储桶和通知配置同时创建。该示例通过使用 Fn::Join 内部函数和 DependsOn 属性按照以下顺序创建资源,从而避免循环依赖:1) IAM 角色,2) Lambda 函数,3) Lambda 权限,然后是 4) S3 存储桶。有关更多信息,请参阅如何避免在 AWS CloudFormation 中使用 Lambda 事件通知时出现的“Unable to validate the following destination configurations”错误?
相关信息
相关内容
- AWS 官方已更新 8 个月前
- AWS 官方已更新 4 年前
- AWS 官方已更新 3 年前