Comment éviter que le message d'erreur « Unable to validate the following destination configurations » (Impossible de valider les configurations des destination suivantes) avec les notifications d'événements Lambda dans CloudFormation ?

Lecture de 5 minute(s)
0

Ma pile échoue lorsque je déploie un modèle AWS CloudFormation. Je reçois ensuite une erreur similaire à celle-ci : « Unable to validate the following destination configurations » (Impossible de valider les configurations des destination suivantes).

Brève description

Vous recevez cette erreur lorsque vous déployez un modèle AWS CloudFormation avec les ressources suivantes :

Amazon S3 doit valider la configuration des notifications lorsqu'il crée le compartiment. La validation est effectuée en vérifiant si le compartiment est autorisé à envoyer des événements à la fonction Lambda. La ressource d'autorisation (qui doit exister pour que ce contrôle réussisse) nécessite le nom du compartiment. Cela signifie que la ressource d'autorisation dépend du compartiment et que le compartiment dépend de la ressource d'autorisation.

Remarque : vous recevez l'erreur « Circular dependency between resources » (Dépendance circulaire entre les ressources) si vous essayez de résoudre ce problème en implémentant un attribut de ressource DependsOn similaire à l'exemple de code suivant.

L'exemple de code suivant montre une dépendance circulaire entre la ressource de compartiment S3 et la propriété SourceArn de la ressource d'autorisation Lambda.

"Resources": {
  "MyS3BucketPermission": {
    "Type": "AWS::Lambda::Permission",
    "Properties": {
      "Action": "lambda:InvokeFunction",
      ...
      ...
      "SourceArn": {
        "Ref": "MyS3Bucket"
      }
    }
  },
  "MyS3Bucket": {
    "DependsOn" : "MyS3BucketPermission",
    ...
    ...

Important : il est recommandé d'ajouter la propriété SourceAccount à la ressource d'autorisation Lambda pour les sources d'événements Amazon S3. Il convient d'ajouter la propriété, car un Amazon Resource Name (ARN) pour Amazon S3 n'inclut pas d'ID de compte. La propriété SourceArn convient à la plupart des autres sources d'événements, mais envisagez d'ajouter la propriété SourceAccount pour les sources d'événements Amazon S3. Cela empêche les utilisateurs de recréer un compartiment que vous avez supprimé, puis d'accorder à un nouveau propriétaire de compartiment les autorisations complètes pour appeler votre fonction Lambda.

Résolution

Vous pouvez éviter les dépendances circulaires en utilisant la fonction intrinsèque Fn::Sub avec les paramètres de pile. Vous pouvez également utiliser Fn::Join pour combiner des chaînes.

Dans l'exemple de modèle suivant, le nom de compartiment S3 BucketPrefix est fourni comme paramètre aux ressources AWS::S3::Bucket et AWS::Lambda::Permission.

Remarque : l'exemple suivant suppose que le nom du compartiment n'a pas été utilisé précédemment avec vos comptes AWS. Si vous souhaitez réutiliser un modèle avec cet extrait de code, vous devez fournir à chaque fois un préfixe de compartiment différent.

{
  "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": [
              "",
              [
                "var response = require('cfn-response');",
                "exports.handler = function(event, context) {",
                " var responseData = {Value: event.ResourceProperties.List};",
                " responseData.Value.push(event.ResourceProperties.AppendedItem);",
                " response.send(event, context, response.SUCCESS, responseData);",
                "};"
              ]
            ]
          }
        },
        "Runtime": "nodejs12.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:*:*:*"
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Le modèle évite les dépendances circulaires, car il crée les ressources dans l'ordre suivant :

  1. Rôle AWS Identity and Access Management (IAM)
  2. Fonction Lambda
  3. Autorisation Lambda
  4. Compartiment S3

Désormais, Amazon S3 peut vérifier sa configuration de notification et créer le compartiment sans aucun problème.

Vous pouvez également essayer les résolutions suivantes :

  • Créez le compartiment S3 sans configuration de notification, puis ajoutez le compartiment dans la prochaine mise à jour de la pile.
  • Créez une autorisation Lambda moins restrictive. Par exemple, autorisez les appels pour un compte AWS spécifique en omettant SourceArn.
  • Créez une ressource personnalisée à exécuter à la fin du flux de travail de la pile. Cette ressource ajoute la configuration des notifications au compartiment S3 une fois que toutes les autres ressources ont été créées.

Informations connexes

Comment éviter que le message d'erreur « Impossible de valider les configurations des destinations suivantes » dans AWS CloudFormation ?

Utilisation d'AWS Lambda avec les événements Amazon S3

Réf.

Fn::GetAtt

AWS OFFICIEL
AWS OFFICIELA mis à jour il y a 4 ans