🔑

Terraform で API Gateway Lambda オーソライザーを使用する

2024/05/19に公開

はじめに

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 を使用する方の参考になれば幸いです。

shinaps テックブログ

Discussion