🐕
【AWS SAM】Lambda同士の呼び出しで「AccessDeniedException」になる理由と対処法
はじめに
AWS SAMでLambda A(リクエスト受付)から Lambda B(処理実行)を呼び出す構成を組みました。
RequestFunction(Lambda A) → ProcessorFunction(Lambda B)
呼び出す側のLambda Aに lambda:InvokeFunction 権限を付与していたのでLambda B(処理実行)を呼び出せると思っていたが、アクセス拒否されました。
今回はこのエラー原因と解決をします。
構成
template.yamlの内容を一部抜粋
Resources:
# Lambda A
RequestFunction:
Type: AWS::Serverless::Function
Properties:
Handler: request.app.lambda_handler
Runtime: python3.9
Events:
ApiEvent:
Type: Api
Properties:
Path: /process
Method: post
Policies:
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource: !GetAtt ProcessorFunction.Arn
# Lambda B
ProcessorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: processor.app.lambda_handler
Runtime: python3.9
RequestFunctionのPoliciesにlambda:InvokeFunctionを書いたため、ProcessorFunctionを呼び出せると思っていました。
しかし、デプロイ後にRequestFunctionを実行すると、以下のようなエラーが発生しました。
[ERROR] ClientError: An error occurred (AccessDeniedException) when calling the Invoke operation: User: arn:aws:sts::*** is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:*** because no identity-based policy allows the lambda:InvokeFunction action
原因
呼び出しされる側の権限が許可されていなかった。
| 権限の種類 | 対象 | 役割 |
|---|---|---|
| IAM Policy | 呼び出す側のLambda A |
lambda:InvokeFunctionを使うための許可 |
| Lambda Permission | 呼び出される側のLambda B | 「誰からの呼び出しを受け入れるか」を明示する |
つまり、Policiesにlambda:InvokeFunctionを書くだけでは不十分で、呼び出されるProcessorFunctionにLambda::Permissionを追加する必要がありました。
解決方法
Lambda::Permissionをtemplate.yamlに追加したところ、無事にProcessorFunctionを呼び出せるようになりました🎉
Resources:
# 以下を追加
ProcessorFunctionPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt ProcessorFunction.Arn
Principal: lambda.amazonaws.com
SourceArn: !GetAtt RequestFunction.Arn
項目の補足:
-
Action: Lambdaを呼び出す操作を許可 -
FunctionName: 呼び出されるLambda(ProcessorFunction) -
SourceArn: 呼び出し元のLambda(RequestFunction)
おわりに
DynamoDBやS3にアクセスする場合は、IAMロールに必要な権限を付与すればアクセスできます。
しかし、Lambdaを呼び出す場合はそれだけでは不十分で、呼び出される側のLambdaに対しても、誰からの呼び出しを許可するかを設定する必要があることがわかりました。
参考記事
Discussion