フューチャー技術ブログ

VPC内のAmazon API Gatewayをインターネットオーバーで疎通確認する

はじめに

TIG DXユニットの真野です。AWSのAPI Gateway+Lambda という構成でWeb API開発を行う際、ちょっと便利に使える疎通方法をまとめます。

背景

API GatewayですがPublicなエンドポイントがあれば curlコマンドやPostmanを用いての動作検証も容易だと思います。

一方でVPCエンドポイントを利用してプライベート APIとして構築されている場合は少し厄介です。そのセグメントにVPCなどで属することができればよいのですが、そのためだけに接続するのは煩わしい場面があります。踏み台サーバを作ってAWS Systems Manager(ssmコマンド)でログインするのも、開発環境でそこまでするのかという感覚がありました。また、AWS WAFなどで接続が絞られている時にはその条件を思い出す必要があり(覚えておけよって感じですが)、疎通確認すらちょっと面倒な場面があります。

aws apigateway test-invoke-methodコマンドが便利

API Gatewayのマネジメントコンソールには動作確認用のテスト呼び出し機能が存在します。

マネジメントコンソールのテスト呼び出し

こちらと同等の機能がawscliにも提供されています。api gateway test-invoke-methodコマンドです。これを利用することでマネジメントコンソール上と同等のリクエストをコマンドラインから確認できます。

つまりプライベートに構築されたAPI Gatewayに対しても、適切な権限があれば疎通確認ができるということです。

実行例を載せます。レスポンスは少し大きなJSONだったので、jqコマンドでフィールドを、ステータスコード・応答ヘッダ・応答ボディに絞っています。profileやrest-api-id, resoruce-idは適時読み替えてください。

test-invoke-methodの実行例
aws apigateway --profile <my_profile> test-invoke-method --rest-api-id <1234123412> --resource-id <3gapai> \
--http-method PGET --path-with-query-string /v1/health | jq '.status, .headers, .body'
200
{
"Content-Type": "application/json",
"Vary": "Accept-Encoding",
"X-Amzn-Trace-Id": "Root=1-67891233-abcdef012345678912345678;Sampled=0"
}
"{\"message\":\"OK\"}\n"

–rest-api-id と –resource-idの取得方法はStackoverflowの回答がシンプルでした。こちらを参考に取得すると良いかなと思います。

API GatewayにLambdaオーソライザーが設定されている場合

API GatewayでLambdaオーソライザーが設定されている構成の場合があります。オーソライザー側についてはこのブログにもAWS APIGateway Custom Authorizer入門という記事がありますのでぜひ参照ください。

API Gatewayのカスタムオーソライザーの構成図

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html

このときに、オーソライザー側で認可する場合に、後続に追加パラメータを設定する仕様で設計されていると少し考慮が必要です。というのもaws apigateway test-invoke-methodはオーソライザー経由で実行するのではなく、直接API Gatewayにトリガーされたリソースを呼び出すからです。この場合はaws apigateway test-invoke-methodに後続のLambdaなどが必要とする、必要なパラメータを--headersなどで追加して呼び出すするようにしましょう。

ちなみおに、オーソライザー自体のテストもマネジメントコンソールから可能ですし、AWS CLIからも apigateway test-invoke-authorizerコマンドで可能です。

私が利用したことがないため、今回は説明を割愛します。

AWS SDK for Goからテスト要求を呼び出してみる。

AWS SDK for Goを利用すればTest Invokeの呼び出しができます。

実装例を簡単に記載します。

package main

import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/apigateway"
"log"
"net/http"
)

var apigw = apigateway.New(session.Must(session.NewSessionWithOptions(session.Options{
Profile: "my_profile", // TODO 書き換え
SharedConfigState: session.SharedConfigEnable,
},
)))

func main() {

params := &apigateway.TestInvokeMethodInput{
RestApiId: aws.String("1234123412"), // TODO 書き換え
ResourceId: aws.String("3gapai"), // TODO 書き換え
HttpMethod: aws.String(http.MethodGet),
PathWithQueryString: aws.String("/v1/health"),
}

req, resp := apigw.TestInvokeMethodRequest(params)
if err := req.Send(); err != nil {
log.Fatalf("test invoke: %v", err)
}
fmt.Printf("%d\n%v\n%v\n", *resp.Status, aws.StringValueMap(resp.Headers), *resp.Body)
}

これを実行すると、awscliコマンドで実行した結果と同等の応答を得られます。

>go run sample.go
200
map[Content-Type:application/json Vary:Accept-Encoding X-Amzn-Trace-Id:Root=1-67891233-abcdef012345678912345678;Sampled=0]
{"message":"OK"}

awscli側のapigateway test-invoke-methodに慣れておけば、インタフェースで悩むことはほぼ無いと思います。
取得結果のステータスコードや応答ボディなどは int64やstring でポインタなので一瞬戸惑うくらいでしょうか。

まとめ

プライベートなAPI Gatewayだと開発環境の疎通レベルでも検証が面倒だと思ったときには、test-invoke-methodコマンドを利用する選択もあるよという記事でした。

当然、AWS SDKからも呼ぶことができますので、ちょっとした疎通テストを自動化するときにも利用できるかと思います。