はじめに
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を作成する際の定義の仕方についてまとめました。
ケースによって組み合わせテンプレートと分離テンプレートを使い分けましょう。