Come posso risolvere l'errore che ricevo quando sottoscrivo una funzione AWS Lambda a un'origine di eventi basata su notifiche push in AWS CloudFormation?

3 minuti di lettura
0

Non riesco a sottoscrivere la mia funzione AWS Lambda a una notifica di eventi Amazon Simple Storage Service (Amazon S3) o a un argomento di Amazon Simple Notification Service (Amazon SNS) nel mio stack AWS CloudFormation. Se utilizzo la risorsa AWS::Lambda::EventSourceMapping, ricevo il seguente errore: "Unrecognized event source, must be kinesis or dynamodb stream."

Breve descrizione

La risorsa AWS::Lambda::EventSourceMapping è progettata per origini di eventi basate su pull, come i flussi di eventi di Amazon DynamoDB e Amazon Kinesis. Con le origini di eventi basate su push, come le notifiche di eventi di Amazon S3 o i messaggi Amazon SNS, l'origine dell'evento è responsabile della chiamata della funzione Lambda. Affinché un'origine di eventi push richiami una funzione Lambda, la policy delle risorse della funzione deve autorizzare un'origine di eventi supportata.

Soluzione

Nel tuo modello AWS CloudFormation, aggiungi una policy basata sulle risorse utilizzando la risorsa AWS::Lambda::Permission.

Ad esempio, la seguente policy basata sulle risorse consente a un argomento Amazon SNS di richiamare una funzione Lambda:

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

Per un'origine di eventi tematici di Amazon SNS, devi definire una policy sull'argomento con le autorizzazioni richieste.

Per un'origine di eventi Amazon S3, devi disporre di un'istruzione sulla configurazione delle notifiche che sottoscriva la funzione Lambda al bucket Amazon S3. Ad esempio:

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

nell'esempio precedente, il bucket S3 e la configurazione delle notifiche vengono creati contemporaneamente. L'esempio evita una dipendenza circolare utilizzando la funzione intrinseca Fn::Join e l'attributo DependsOn per creare le risorse nel seguente ordine: 1) Ruolo IAM, 2) Funzione Lambda, 3) Autorizzazione Lambda e quindi 4) Bucket S3. Per ulteriori informazioni, consulta Come posso evitare l'errore "Unable to validate the following destination configurations" con le notifiche degli eventi Lambda in AWS CloudFormation?


Informazioni correlate

CloudFormation best practices

Autorizzazioni Lambda

Aggiornamento dei comportamenti delle risorse dello stack

AWS UFFICIALE
AWS UFFICIALEAggiornata 4 anni fa