スキップしてコンテンツを表示

Lambda 関数を AWS CloudFormation 内のプッシュベースのイベントソースにサブスクライブさせる際にエラーが発生するため、解決方法を教えてください。

所要時間2分
0

AWS CloudFormation スタック内の Amazon Simple Storage Service (Amazon S3) イベントまたは Amazon Simple Notification Service (Amazon SNS) トピックに対し、AWS Lambda 関数をサブスクライブできません。

簡単な説明

Lambda 関数をサブスクライブする際に AWS::Lambda::EventSourceMapping を使用した場合、次のエラーが発生する場合があります: "Unrecognized event source, must be kinesis or dynamodb stream."

このリソースは、プルベースのイベントソース (例: Amazon DynamoDB イベントストリーム、Amazon Kinesis) を対象に設計されています。Amazon S3 イベント通知や Amazon SNS メッセージなどのプッシュベースのイベントソースを使用する際、イベントソースは Lambda 関数を呼び出します。プッシュイベントソースで Lambda 関数を呼び出すには、関数のリソースポリシーは、Lambda 関数を呼び出せるサービスを承認する必要があります。

解決策

AWS::Lambda::Permission リソースを含むリソースベースポリシーを CloudFormation テンプレートに追加します。

たとえば、次のリソースベースポリシーでは、Amazon SNS トピックは Lambda 関数を呼び出すことができます。

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

Amazon SNS トピックのイベントソースには、必要な権限を含むトピックポリシーを定義する必要があります。

Amazon S3 イベントソースには、Lambda 関数を Amazon S3 バケットにサブスクライブする通知設定ステートメントが必要です。例:

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

この例では、S3 バケットと通知設定が同時に作成されます。この例では、組み込み関数 Fn::GetAtt および、DependsOn 属性で循環依存を回避することで、リソースを作成しています。

: dependsOn 属性を指定しない場合、CloudFormation は S3 バケットと Lambda 権限リソースを同時に作成します。

リソースは次の順序で作成されます。

  • AWS Identity and Access Management (IAM) ロール
  • Lambda 関数
  • Lambda 権限
  • S3 バケット

詳細については、「CloudFormation で エラーを修正する方法を教えてください"Unable to validate the following destination configurations"」を参照してください。

関連情報

CloudFormation のベストプラクティス

Lambda リソースのアクションの権限

スタックリソース更新の動作

AWS公式更新しました 2年前
コメントはありません

関連するコンテンツ