APIGatewayとLambdaのtemplate.ymlを分割したら、Internal server errorになった
AWS SAMを使用して、template.ymlファイルを次のように分割し、APIGatewayの定義にopenAPI(swagger?)を利用することで、APIGatewayとLambdaを紐づけていました。
※ 筆者は大元のtemplate.ymlにAPIGatewayの定義をしています。
フォルダ構成はざっくりこんな感じ。
.
├── template.yml
├── package.json
├── tsconfig.json
└── functions
└──helloWorld
├──index.ts (handler)
└──lambda-template.yml
以下、大元のtemplate.ymlと、Lambda定義のtemplateの中身です。
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Resources:
# functionsディレクトリに保存したlambda-template.yml(後述)で定義したLambdaを読み込む
HelloWorldFunction:
Type: AWS::Serverless::Application
Properties:
Location: functions/helloWorld/lambda-template.yml # 適宜正しいディレクトリパスに置き換えてください
API:
Type: AWS::Serverless::Api
Properties:
Name: hello-world-api
StageName: dev
DefinitionBody:
openapi: 3.0.1
info:
title: hello-world-api
version: "2021-10-01"
paths:
/hello-world:
get:
x-amazon-apigateway-integration:
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:HelloWorldFunction/invocations
httpMethod: POST
type: aws_proxy
Lambdaのtemplate.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: HelloWorldFunction
Handler: index.handler
Runtime: nodejs18.x
AWSコンソールからAPIGatewayのテストを実行すると…
で、最終行を見てみると
Execution failed due to configuration error: Invalid permissions on Lambda function
結論(解決方法)
次のように修正
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Application
Properties:
Location: functions/helloWorld/lambda-template.yml
Parameters: # APIの論理IDをLambdaの定義に渡す
API: !Ref API
API:
Type: AWS::Serverless::Api
Properties:
Name: hello-world-api
StageName: dev
DefinitionBody:
openapi: 3.0.1
info:
title: hello-world-api
version: "2021-10-01"
paths:
/hello-world:
get:
x-amazon-apigateway-integration:
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:HelloWorldFunction/invocations
httpMethod: POST
type: aws_proxy
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters: # 大元のtemplate.ymlのParametersと紐づけ
API:
Type: String
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: HelloWorldFunction
Handler: index.handler
Runtime: nodejs18.x
LambdaPermission: # LambdaにAPIからの呼び出しを許可する「リソースベースのポリシー」を追加
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt HelloWorldFunction.Arn
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${API}/*/GET/hello-world
AWS::Lambda::Permission
についてはこちらを見てください。
こんにちは!しました。
原因
原因はLambdaの設定の「リソースベースのポリシー」が空だったことにあります。
ここに、APIGatewayからの呼び出しを許可するポリシーをくっ付けてやる必要があるのですが、その記述がtemplate.ymlにありませんでした。
そもそも論
APIGatewayと同じtemplate.ymlにLambdaを定義することで、わざわざAWS::Lambda::Permission
の記述をする必要はありません。
例えばこちらのような感じ。
どうやら、SAMの内部的な処理で良しなにやってくれるみたいです。
こちらの記事も同じ事象みたいなので、掲載します。
てか、本記事よりもリンクの記事の方が正しく書いていただいているので、私と同じ事象になった方は是非参照されたし。
最後に
何か補足や間違いがあれば、随時更新しようと思います。
それ以外の感想や、「役に立った」等、何でも良いので、是非コメント頂けると嬉しいです!