No puedo suscribir mi función de AWS Lambda a una notificación de eventos de Amazon Simple Storage Service (Amazon S3) o a un tema de Amazon Simple Notification Service (Amazon SNS) de mi pila de AWS CloudFormation.
Descripción corta
Si utilizas el recurso AWS::Lambda::EventSourceMapping para suscribir la función de Lambda, es posible que recibas el siguiente error: "Unrecognized event source, must be kinesis or dynamodb stream."
Este recurso está diseñado para orígenes de eventos pull, como las transmisiones de eventos de Amazon DynamoDB y Amazon Kinesis. Cuando usas orígenes de eventos push, como las notificaciones de eventos de Amazon S3 o los mensajes de Amazon SNS, el origen de eventos invoca a la función de Lambda. Para que un origen de eventos push invoque una función de Lambda, la política de recursos de la función debe autorizar un servicio que pueda invocar funciones de Lambda.
Resolución
En tu plantilla de AWS CloudFormation, agrega una política basada en recursos mediante el recurso AWS::Lambda::Permission.
Por ejemplo, la siguiente política basada en recursos permite que un tema de Amazon SNS invoque a una función de Lambda:
"LambdaResourcePolicy": { "Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName" : { "Ref" : "MyFunction" },
"Principal": "sns.amazonaws.com",
"Action": "lambda:InvokeFunction",
"SourceArn" : { "Ref" : "MySNSTopic" }
}
}
Para un origen de eventos de tema de Amazon SNS, debes definir una política de temas con los permisos necesarios.
Para un origen de eventos de Amazon S3, debes tener una instrucción de configuración de notificaciones que suscriba la función de Lambda al bucket de Amazon S3. Por ejemplo:
{ "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": "nodejs20.x"
}
},
"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>"
}
]
}
}
]
}
}
}
}
En este ejemplo, el bucket de S3 y la configuración de notificaciones se crean al mismo tiempo. El ejemplo evita una dependencia circular mediante la función intrínseca Fn::GetAtt y el atributo DependsOn para crear los recursos.
Nota: Cuando no se especifica el atributo DependsOn, CloudFormation crea el bucket de S3 y los recursos de permisos de Lambda al mismo tiempo.
Los recursos se crean en el siguiente orden:
- Un rol de AWS Identity and Access Management (IAM)
- Función de Lambda
- Permisos de Lambda
- Bucket de S3
Para obtener más información, consulta ¿Cómo se corrige el error en CloudFormation?"Unable to validate the following destination configurations"
Información relacionada
Prácticas recomendadas de CloudFormation
Permisos de acción de recursos de Lambda
Comportamientos de actualización de los recursos de la pila