Lambda の権限は 2 種類: 実行ロール(関数が呼ぶ側)とリソースベースポリシー(関数を呼ぶ側)
S3 イベントで Lambda が起動しないとき、実行ロールをいくら直しても直らないことがある。足りないのは「S3 がその関数を呼んでよい」という許可で、これは関数側のリソースベースポリシーに書くもの。
2 つの違い
| 実行ロール(execution role) | リソースベースポリシー(関数ポリシー) | |
|---|---|---|
| 何の許可か | 関数が 他のサービスを呼ぶ 権限(S3 読み書き、DynamoDB、CloudWatch Logs など) | 誰がこの関数を呼べるか(S3、SNS、EventBridge、API Gateway、別アカウントなど) |
| どこに付く | IAM ロール(関数に 1 つ割り当て) | Lambda 関数(またはエイリアス・バージョン)そのもの |
| 足りないと | 関数は起動するが、中で AccessDenied | そもそも関数が起動しない(呼び出し元側で失敗) |
切り分け
- 関数のログ(CloudWatch Logs)に呼び出しの記録があるか見る
- 記録がない → 呼び出し元の許可(リソースベースポリシー)かトリガー設定の問題
- 記録はあって中で
AccessDenied→ 実行ロールの問題
- 関数ポリシーを確認する
sh
aws lambda get-policy --function-name my-func- S3 から呼べるようにする(コンソールでトリガーを追加すると自動で付くが、IaC や CLI で通知だけ設定したときは漏れやすい)
sh
aws lambda add-permission \
--function-name my-func \
--statement-id s3-invoke \
--action lambda:InvokeFunction \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::my-bucket \
--source-account 123456789012注意点
--source-arnと--source-accountで呼び出し元のバケットとアカウントを絞る。付けないと他人のバケットからも呼べる許可になりうる- エイリアスやバージョンを指定してトリガーを設定した場合、許可もそのエイリアス・バージョン(
--qualifier)に付ける必要がある - 別アカウントから呼ばせる場合も、関数側のリソースベースポリシーで相手のアカウントを許可する
- 権限の上限そのものを決める SCP やキーポリシーとの関係は AWS IAM: 評価は「明示 Deny → 明示 Allow → 暗黙 Deny」 と AWS KMS: キーポリシーが許さない限り、IAM ポリシーで kms:Decrypt を付けても使えない を参照