Direkt zum Inhalt

Wie behebe ich den Fehler, den ich erhalte, wenn ich eine Push-basierte Ereignisquelle in CloudFormation für eine Lambda-Funktion abonniere?

Lesedauer: 3 Minute
0

Ich kann für meine AWS-Lambda-Funktion keine Amazon Simple Storage Service (Amazon S3)-Ereignisbenachrichtigung und kein Amazon Simple Notification Service (Amazon SNS)-Thema in meinem AWS-CloudFormation-Stack abonnieren.

Kurzbeschreibung

Wenn du die Ressource AWS::Lambda::EventSourceMapping verwendest, um deine Lambda-Funktion zu abonnieren, erhältst du möglicherweise die folgende Fehlermeldung: "Unrecognized event source, must be kinesis or dynamodb stream."

Diese Ressource wurde für Pull-basierte Ereignisquellen wie Amazon-DynamoDB-Ereignis-Streams und Amazon Kinesis entwickelt. Wenn du Push-basierte Ereignisquellen wie Amazon S3-Ereignisbenachrichtigungen oder Amazon SNS-Benachrichtigungen verwendest, ruft die Ereignisquelle die Lambda-Funktion auf. Damit eine Push-Ereignisquelle eine Lambda-Funktion aufrufen kann, muss die Ressourcenrichtlinie der Funktion einen Dienst autorisieren, der Lambda-Funktionen aufrufen kann.

Lösung

Füge in deiner CloudFormation-Vorlage mithilfe der Ressource AWS::Lambda::Permission eine ressourcenbasierte Richtlinie hinzu.

Die folgende ressourcenbasierte Richtlinie ermöglicht es beispielsweise einem Amazon-SNS-Thema, eine Lambda-Funktion aufzurufen:

"LambdaResourcePolicy": {  "Type": "AWS::Lambda::Permission",
  "Properties": {
    "FunctionName" : { "Ref" : "MyFunction" },
    "Principal": "sns.amazonaws.com",
    "Action": "lambda:InvokeFunction",
    "SourceArn" : { "Ref" : "MySNSTopic" }
  }
}

Um ein Amazon-SNS-Thema als Ereignisquelle zu verwenden, musst du eine Thema-Richtlinie mit den erforderlichen Berechtigungen definieren.

Für eine Amazon-S3-Ereignisquelle benötigst du eine Anweisung zur Benachrichtigungkonfiguration, die den Amazon-S3-Bucket für die Lambda-Funktion abonniert. Zum Beispiel:

{  "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>"
                }
              ]
            }
          }
        ]
      }
    }
  }
}

In diesem Beispiel werden der S3-Bucket und die Benachrichtigungskonfiguration gleichzeitig erstellt. Das Beispiel vermeidet eine zirkuläre Abhängigkeit durch die intrinsische Funktion Fn::GetAtt und das DependsOn-Attribut, um die Ressourcen zu erstellen.

Hinweis: Wenn das DependsOn-Attribut nicht angegeben ist, erstellt CloudFormation gleichzeitig den S3-Bucket und die Lambda-Berechtigungsressourcen.

Die Ressourcen werden in der folgenden Reihenfolge erstellt:

  • Rolle für AWS Identity and Access Management (IAM)
  • Lambda-Funktion
  • Lambda-Berechtigung
  • S3-Bucket

Weitere Informationen findest du unter Wie behebe ich den Fehler in CloudFormation?"Unable to validate the following destination configurations"

Ähnliche Informationen

Bewährte Methoden für AWS CloudFormation

Berechtigungen für Lambda-Ressourcenaktionen

Verhalten von Stack-Ressourcen aktualisieren

AWS OFFICIALAktualisiert vor 2 Jahren