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."
간략한 설명
AWS::Lambda::EventSourceMapping 리소스는 Amazon DynamoDB 이벤트 스트림 및 Amazon Kinesis 같은 풀 기반 이벤트 소스용으로 설계되었습니다. Amazon S3 이벤트 알림이나 Amazon SNS 메시지 같은 푸시 기반 이벤트 소스를 사용하는 경우 이벤트 소스가 Lambda 함수를 호출합니다. 푸시 이벤트 소스가 Lambda 함수를 호출하려면 함수의 리소스 정책이 지원되는 이벤트 소스에 권한을 부여해야 합니다.
해결 방법
AWS::Lambda::Permission 리소스를 사용하여 AWS CloudFormation 템플릿에 리소스 기반 정책을 추가합니다.
예를 들어 다음 리소스 기반 정책은 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 버킷을 구독하도록 하는 notification configuration 문이 있어야 합니다. 예를 들면 다음과 같습니다.
{
"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 이벤트 알림에 "다음 대상 구성을 검증할 수 없음" 오류가 발생하지 않도록 하려면 어떻게 해야 합니까?를 참조하십시오.
관련 정보
CloudFormation 모범 사례
Lambda 권한
스택 리소스의 업데이트 동작