EventBridge Scheduler からの Lambda 関数起動に Lambda Permission は不要
AWS Lambda 関数の他サービスからの呼び出し
AWS Lambda 関数にはリソースベースポリシーを割り当てることができます。
関数を他のサービスから呼び出すとき,通常はリソースベースポリシーにそのサービスからの実行を許可するポリシーを追加する必要があります。
例えば,Amazon SNS からイベント駆動で呼び出す場合は,以下のように add-permission コマンドを実行することでポリシーを追加することができます。
aws lambda add-permission --function-name example-function \
--action lambda:InvokeFunction \
--statement-id AllowExecutionFromSNS \
--principal sns.amazonaws.com
Terraform では aws_lambda_permission リソースを使います。
resource "aws_lambda_permission" "with_sns" {
statement_id = "AllowExecutionFromSNS"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.example.function_name
principal = "sns.amazonaws.com"
source_arn = aws_sns_topic.example.arn
}
マネジメントコンソール上でトリガーを追加すると,自動的にリソースベースポリシーも追加されます。
一方で,AWS CLI や Terraform など API 経由で関数を作成する場合は,リソースベースポリシーも手動で追加する必要があります。
Lambda 関数と連携するのに必要なリソースを作成したのになぜか実行されない場合は,リソースベースポリシー(permission)を作り忘れていたということがよくあります。エラーも出ないので,知らないと原因特定が難しくて厄介です。
EventBridge からの呼び出しでは必要
Amazon EventBridge というサービスから Lambda 関数を呼び出す場合も同様にリソースベースポリシーへの追加が必要になります。principal は events.amazonaws.com
です。
EventBridge Scheduler からの呼び出しでは不要
Amazon EventBridge Scheduler は2022年11月にリリースされた新しいサービスで,EventBridge ルールとは別のスケジューリング機能を提供します。
EventBridge という名前がついていますが,ドキュメントもサービスプリンシパルも分かれているので,内部的には独立したサービスとみなせます。
EventBridge と EventBridge Scheduler の違いは以下の記事に書かれています。
呼び出しにはなぜか Lambda 関数のリソースベースポリシーが不要で,InvokeFunction を許可した IAM ロールを付与するだけで実現できます。
Terraform で表現すると以下のようになります。
EventBridge Scheduler の権限設定
locals {
function_name = "example-function"
}
resource "aws_scheduler_schedule" "scheduler" {
name = local.function_name
flexible_time_window {
mode = "OFF"
}
schedule_expression = "cron(0 3 * * ? *)"
schedule_expression_timezone = "Asia/Tokyo"
target {
arn = aws_lambda_function.example.arn
role_arn = aws_iam_role.scheduler.arn
}
}
resource "aws_iam_role" "scheduler" {
name = local.function_name
assume_role_policy = data.aws_iam_policy_document.trust_scheduler.json
}
data "aws_iam_policy_document" "trust_scheduler" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["scheduler.amazonaws.com"]
}
}
}
resource "aws_iam_policy" "scheduler" {
name = local.function_name
policy = data.aws_iam_policy_document.scheduler.json
}
data "aws_iam_policy_document" "scheduler" {
statement {
actions = ["lambda:InvokeFunction"]
resources = [aws_lambda_function.example.arn]
}
}
resource "aws_iam_role_policy_attachment" "scheduler" {
role = aws_iam_role.scheduler.name
policy_arn = aws_iam_policy.scheduler.arn
}
なぜこのサービスだけリソースベースポリシーが不要なのかはよくわかりませんでした。ご存じの方がいらっしゃいましたらご教示頂けると助かります。
参考:リソースベースポリシーの追加画面
Lambda 関数のマネジメントコンソールで,リソースベースポリシーを追加する画面で許可する AWS のサービスを選択できるのですが,選択肢は以下に挙げるものになっていました。EventBridge Scheduler の名前がないことが関連しているのかもしれません。
- API Gateway
- AWS IoT
- Alexa Skills Kit
- Alexa Smart Home
- Application Load Balancer
- CloudWatch Logs
- CodeCommit
- Cognito Sync Trigger
- EventBridge (CloudWatch Events)
- Kinesis
- S3
- Secrets Manager
- SNS
- SQS
- Other
Discussion