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

Lesedauer: 3 Minute
0

Ich kann für meine AWS-Lambda-Funktion keine Amazon Simple Storage Service (Amazon S3)-Ereignis-Benachrichtigung und kein Amazon Simple Notification Service (Amazon SNS)-Thema in meinem AWS-CloudFormation-Stack abonnieren. Wenn ich die Ressource AWS::Lambda::EventSourceMapping verwende, erhalte ich die folgende Fehlermeldung: „Unrecognized event source, must be kinesis or dynamodb stream.“

Kurzbeschreibung

Die Ressource AWS::Lambda::EventSourceMapping wurde für Pull-basierte Ereignisquellen wie Amazon-DynamoDB-Ereignis-Streams und Amazon Kinesis entwickelt. Bei Push-basierten Ereignisquellen wie Amazon-S3-Ereignisbenachrichtigungen oder Amazon-SNS-Nachrichten ist die Ereignisquelle für den Aufruf der Lambda-Funktion verantwortlich. Damit eine Push-Ereignisquelle eine Lambda-Funktion aufrufen kann, muss die Ressourcenrichtlinie der Funktion eine unterstützte Ereignisquelle autorisieren.

Lösung

Fügen Sie in Ihrer AWS-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, müssen Sie eine Thema-Richtlinie mit den erforderlichen Berechtigungen definieren.

Für eine Amazon-S3-Ereignisquelle benötigen Sie 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": "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>"
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Im obigen Beispiel werden der S3-Bucket und die Benachrichtigungskonfiguration gleichzeitig erstellt. Eine zirkuläre Abhängigkeit wird vermieden, indem die intrinsische Funktion Fn::Join und das DependsOn-Attribut verwendet werden, um die Ressourcen in dieser Reihenfolge zu erstellen: 1) IAM-Rolle, 2) Lambda-Funktion, 3) Lambda-Berechtigung und dann 4) S3-Bucket. Weitere Informationen finden Sie unter How do I avoid the "Unable to validate the following destination configurations" error with Lambda event notifications in AWS CloudFormation


Ähnliche Informationen

Bewährte Methoden für AWS CloudFormation

Zugriffsberechtigungen für Lambda-Ressourcen

Aktualisieren von Verhalten von Stack-Ressourcen

AWS OFFICIAL
AWS OFFICIALAktualisiert vor 4 Jahren