はじめに
AWS SAMでEventBridge + Lambdaを作成する際に、Lambdaのリソースポリシー(リソースベースのポリシー)が必要となります。その定義の仕方についてまとめます。
構成
Lambdaを定期実行させるための、EventBridge + Lambdaの環境。
この際、EventBridgeからLambdaの実行を許可するリソースポリシーを設定する必要があります。
2パターンで定義できる
上記の構成をSAMテンプレートで定義する場合、EventBridgeルールをどう定義するかで以下の2パターンがあり、ケースによって使い分ければ良いと思います。
パターン | EventBridgeルール | リソースポリシー | ケース |
---|---|---|---|
組み合わせテンプレート | AWS::Serverless::Function 内にEventsプロパティで定義する |
自動生成される | EventBridge:Lambdaが1:1のようなシンプルな構成の場合 |
分離テンプレート | AWS::Events::Rule で定義 |
AWS::lambda::Permission で定義 |
上記以外の複雑なルーティングロジックがある場合や、SAMテンプレートの外部のリソースに接続している場合 |
Amazon EventBridge と AWS Serverless Application Model テンプレートの使用
やってみる
組み合わせテンプレートの場合
AWS::Serverless::Function
にEventsプロパティを定義しておきます。
Lambdaのリソースベースポリシーは自動で作成されます。
[template.yaml]
CombinedTemplateFunction: Type: AWS::Serverless::Function Properties: FunctionName: combined-template-function CodeUri: function/ Handler: combined-template-function.main Runtime: python3.9 Events: Trigger: Type: Schedule Properties: Name: combined-template-function-rule Schedule: cron(0 19 * * ? *) Enabled: true
Lambdaの リソースベースのポリシーステートメント
に設定されます。
ステートメントの名前は、 SAMにて展開されるCFnテンプレート名
と SAMテンプレートで定義したLambdaのリソース名
が使われているようです。
ポリシーの中身はこんなJSONになってます。
EventBridgeからLambdaを実行できるようなポリシーです。
{ "Version": "2012-10-17", "Id": "default", "Statement": [ { "Sid": "matsuki-sam-test-stack-CombinedTemplateFunctionTriggerPermission-1W1YZ5AHM55JM", "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:combined-template-function", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:events:ap-northeast-1:xxxxxxxxxxxx:rule/combined-template-function-rule" } } } ] }
注意
組み合わせテンプレートで定義した上に、AWS::Events::Rule
, AWS::lambda::Permission
を定義すると、自動作成されるリソースベースポリシーと合わせて2つのポリシーができてしまうので注意。(もちろんEventBridgeルールも2つ作成することになります)
{ "Version": "2012-10-17", "Id": "default", "Statement": [ { "Sid": "matsuki-sam-test-stack-CombinedTemplateFunctionTriggerPermission-1V9ZUVBPFTLY2", "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:combined-template-function", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:events:ap-northeast-1:xxxxxxxxxxxx:rule/combined-template-function-rule" } } }, { "Sid": "matsuki-sam-test-stack-PermissionForEventsToInvokeLambda-DPGG7INS0F8H", "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:combined-template-function", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:events:ap-northeast-1:xxxxxxxxxxxx:rule/separated-template-function-rule" } } } ] }
分離テンプレートの場合
AWS::Serverless::Function
にEventsプロパティを定義しません。AWS::lambda::Permission
で、LambdaとEventBridgeを紐づけるような定義をします。
- Lambda Function
[template.yaml]
SeparatedTemplateFunction: Type: AWS::Serverless::Function Properties: CodeUri: function/ Handler: handler.case1Handler Runtime: python3.9
- EventBridge Rule
[template.yaml]
SeparatedTemplateFunctionRule: Type: AWS::Events::Rule Properties: Name: separated-template-function-rule ScheduleExpression: cron(0 19 * * ? *) State: ENABLED Targets: - Arn: !GetAtt SeparatedTemplateFunction.Arn Id: "TargetFunctionV1"
- Lambda リソースポリシー
[template.yaml]
PermissionForEventsToInvokeLambda: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: SeparatedTemplateFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: !GetAtt SeparatedTemplateFunctionRule.Arn
デプロイするとこんな形となります。
{ "Version": "2012-10-17", "Id": "default", "Statement": [ { "Sid": "matsuki-sam-test-stack-PermissionForEventsToInvokeLambda-12RZWZ0IU5Z5Y", "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:separated-template-function", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:events:ap-northeast-1:xxxxxxxxxxxx:rule/separated-template-function-rule" } } } ] }
ちなみに、CFnテンプレートの場合
CFnテンプレートも同じかなと思ったら、AWS::lambda::Function
のプロパティにはEventsはありませんでした。
よって、組み合わせテンプレートの書き方を使えば良いと思います。
AWS::Lambda::Function
おわりに
SAMテンプレートでLambda + EventBridgeを作成する際の定義の仕方についてまとめました。
ケースによって組み合わせテンプレートと分離テンプレートを使い分けましょう。