🐕

【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::Permissiontemplate.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に対しても、誰からの呼び出しを許可するかを設定する必要があることがわかりました。

参考記事

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-permission.html

Discussion