Je n'arrive pas à abonner ma fonction AWS Lambda à une rubrique de notification d'événement Amazon Simple Storage Service (Amazon S3) ou une rubrique Amazon Simple Notification Service (Amazon SNS) dans ma pile AWS CloudFormation.
Brève description
Si vous utilisez la ressource AWS::Lambda::EventSourceMapping pour abonner votre fonction Lambda, l'erreur suivante peut s'afficher : "Unrecognized event source, must be kinesis or dynamodb stream."
Cette ressource est conçue pour les sources d'événements basées sur des extractions, telles que les flux d'événements Amazon DynamoDB et Amazon Kinesis. Lorsque vous utilisez des sources d'événements basées sur la technologie push, telles que les notifications d'événements Amazon S3 ou les messages Amazon SNS, la source d'événements appelle la fonction Lambda. Pour qu'une source d'événement push invoque une fonction Lambda, la politique de ressources de la fonction doit autoriser un service capable d'invoquer des fonctions Lambda.
Résolution
Dans votre modèle CloudFormation, ajoutez une politique basée sur les ressources avec la ressource AWS::Lambda::Permission.
Par exemple, la politique basée sur les ressources suivante permet à une rubrique Amazon SNS d'invoquer une fonction Lambda :
"LambdaResourcePolicy": { "Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName" : { "Ref" : "MyFunction" },
"Principal": "sns.amazonaws.com",
"Action": "lambda:InvokeFunction",
"SourceArn" : { "Ref" : "MySNSTopic" }
}
}
Pour une source d'événements de rubrique Amazon SNS, vous devez définir une stratégie de rubrique dotée des autorisations requises.
Pour une source d'événements Amazon S3, vous devez disposer d'une instruction de configuration des notifications qui abonne la fonction Lambda au compartiment Amazon S3. Exemple :
{ "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>"
}
]
}
}
]
}
}
}
}
Dans cet exemple, le compartiment S3 et la configuration des notifications sont créés en même temps. L'exemple évite une dépendance circulaire grâce à la fonction intrinsèque Fn::GetAtt et à l'attribut DependsOn pour créer les ressources.
Remarque : Lorsque l'attribut DependsOn n'est pas spécifié, CloudFormation crée le compartiment S3 et les ressources d'autorisation Lambda en même temps.
Les ressources sont créées dans l'ordre suivant :
- Rôle Gestion des identités et des accès AWS (AWS IAM)
- Fonction Lambda
- Autorisation Lambda
- Compartiment S3
Pour plus d'informations, consultez la section Comment corriger l’erreur dans CloudFormation ?"Unable to validate the following destination configurations"
Informations connexes
Bonnes pratiques de CloudFormation
Autorisations d'action de ressource Lambda
Mettre à jour les comportements des ressources de pile