Terraform で API Gateway Lambda オーソライザーを使用する
はじめに
Amazon API Gateway には、「Lambda オーソライザー」と呼ばれる、Lambda 関数を使用して API へのアクセス制御を実施する機能が存在します。
本記事では、Terraform で HTTP API の AWS Lambda オーソライザーを使用する方法についてメモを残します。
HTTP API の Lambda オーソライザーを作成
Lambda オーソライザー関数の例を参考に、下記のような Authorization ヘッダを取得する Node.js の Lambda 関数を作成します。
ここでは、Lambda オーソライザーのレスポンス形式には、2.0 を使用しています。
なお、ドキュメントにも記載があるように、レスポンス形式に 2.0 を使用し、Lambda 関数からブール値を返す場合は、オーソライザーの簡易レスポンスを有効にする必要があります。
こちらについては、Terraform から有効化するようにします。
2.0 形式バージョンを選択した場合は、Lambda 関数から、ブール値を返すか、標準の IAM ポリシー構文を使用する IAM ポリシーを返すことができます。ブール値を返すには、オーソライザーの簡易レスポンスを有効にします
export function handler(event) {
if (event.headers.authorization === "secretToken") {
return {
isAuthorized: true,
context: {},
}
}
return {
isAuthorized: false,
context: {},
}
}
Terraform で HTTP API の Lambda オーソライザーを使用する
以下に Terraform のサンプルコードを記載します。ここでは、hoge という Lambda 関数について、
上記で作成した authorizer という Lambda オーソライザーを使用するようにしています。
data "aws_lambda_function" "authorizer" {
function_name = "authorizer"
}
resource "aws_apigatewayv2_api" "api" {
name = "api"
protocol_type = "HTTP"
}
resource "aws_apigatewayv2_integration" "integration" {
api_id = aws_apigatewayv2_api.api.id
connection_type = "INTERNET"
integration_method = "POST"
integration_uri = aws_lambda_function.hoge.invoke_arn
integration_type = "AWS_PROXY"
}
resource "aws_apigatewayv2_authorizer" "authorizer_resource" {
api_id = aws_apigatewayv2_api.api.id
authorizer_type = "REQUEST"
identity_sources = ["$request.header.Authorization"]
name = "authorizer"
authorizer_payload_format_version = "2.0"
enable_simple_responses = true
authorizer_uri = data.aws_lambda_function.authorizer.invoke_arn
}
resource "aws_apigatewayv2_route" "route" {
api_id = aws_apigatewayv2_api.api.id
route_key = "ANY /${aws_lambda_function.hoge.function_name}"
target = "integrations/${aws_apigatewayv2_integration.integration.id}"
authorization_type = "CUSTOM"
authorizer_id = aws_apigatewayv2_authorizer.authorizer_resource.id
}
resource "aws_apigatewayv2_stage" "stage" {
api_id = aws_apigatewayv2_api.api.id
auto_deploy = true
name = "default"
}
resource "aws_lambda_permission" "hoge" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.hoge.function_name
principal = "apigateway.amazonaws.com"
source_arn = "arn:aws:execute-api:${local.config.current.name}:${local.config.current.account_id}:${aws_apigatewayv2_api.api.id}/*/*/${aws_lambda_function.hoge.function_name}"
}
resource "aws_lambda_permission" "authorizer" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = data.aws_lambda_function.authorizer.function_name
principal = "apigateway.amazonaws.com"
source_arn = "arn:aws:execute-api:${local.config.current.name}:${local.config.current.account_id}:${aws_apigatewayv2_api.api.id}/authorizers/${aws_apigatewayv2_authorizer.authorizer_resource.id}"
}
Lambda オーソライザーについては、特に下記の設定を実施します。
- aws_apigatewayv2_authorizer
- aws_apigatewayv2_route
- aws_lambda_permission
aws_apigatewayv2_authorizer
Resource: aws_apigatewayv2_authorizer を参考に設定します。
-
authorizer_type
- Authorization ヘッダを取得するため、REQUEST を指定します。
-
identity_sources
- Authorization ヘッダを指定します。
-
authorizer_payload_format_version
- Lambda オーソライザーのレスポンス形式を指定します。
-
enable_simple_responses
- レスポンス形式に 2.0 を使用し、Lambda 関数からブール値を返すため、有効化しています。
aws_apigatewayv2_route
Resource: aws_apigatewayv2_route を参考に設定します。
-
authorization_type
- Lambda オーソライザーを使用するため、CUSTOM を指定します。
-
authorizer_id
- Lambda オーソライザーの invoke arn を指定します。
aws_lambda_permission
API Gateway が Lambda オーソライザーを呼び出せるようにするために、authorizer について aws_lambda_permission を設定します。
当初こちらの設定が無く、 {"message":"Internal Server Error"}
が返されハマっていたのですが、下記の記事を参考に、CloudWatch を介してデバッグすることができました。
動作確認
Authorization ヘッダーの値に応じて Lambda オーソライザーが正しく機能することを確認します。
$ ENDPOINT=''
$ curl -Ss -X POST -H "Content-Type: application/json" -H "Authorization: secretToken" --data "{\"fuga\":\"piyo\"}" "$ENDPOINT" | jq .
おわりに
本記事では、Terraform で HTTP API の AWS Lambda オーソライザーを使用する方法についてメモを残しました。Terraform を使用する方の参考になれば幸いです。
Discussion