Private Integrationで作成したAPI GatewayからVPC内のWebサーバーにコンテキスト情報を連携してみる

Private Integrationで作成したAPI GatewayからVPC内のWebサーバーにリクエストIDやグローバルIP等のコンテキスト情報を連携してみました
2018.08.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

サーバーレス開発部@大阪の岩田です。 Private Integrationで作成したAPI GatewayからNLB配下のWebサーバーにAPI GatewayのリクエストIDを引き渡したいという要件があったので、実現方法について調査してみました。

環境

下記のような環境を想定しています。

API GatewayのPrivate Integration機能を使い、API Gatewayで受けたリクエストをNLB経由でVPC内のEC2に渡してやります。 この際、API GatewayのリクエストIDをEC2で稼働するWebサーバーまで引き渡すのがゴールになります。

Private IntegrationのAPI Gateway作成

まずはAPI Gateway → NLB → EC2 の環境を構築します。 こちらのブログで紹介されている手順に従って設定していきます。

【新機能】API Gateway VPC integrationを使ってみた #reinvent

動作確認

設定できたら確認してみます。

なお、今回はWebサーバーにApache2.4を使用しています。

統合リクエストにHTTPヘッダーのマッピングを追加

Private Integrationの設定ができたら、API Gatewayの統合リクエストを設定し、諸々の情報をHTTPヘッダーとしてEC2に渡すように設定します。 マッピング元として指定できる項目の詳細は公式ドキュメントに記載されているのでご参照下さい。

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#context-variable-reference https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/request-response-data-mappings.html

マッピングの設定は統合リクエストのヘッダーの追加から設定します。マッピング先のヘッダ名はお好みで設定して下さい。

今回は試しにコンテキスト変数から下記の情報を引き渡すように設定してみます。

パラメータ 説明
$context.requestTime CLF 形式の要求時間 (dd/MMM/yyyy:HH:mm:ss +-hhmm)。
$context.requestId API 呼び出し用に自動生成された ID です。
$context.extendedRequestId 自動生成された API コールの ID。デバッグとトラブルシューティングにさらに役立つ情報が含まれています。
$context.identity.sourceIp API Gateway へのリクエストを実行する TCP 接続のソース IP アドレス。

※上記公式ドキュメントより抜粋

設定後の画面キャプチャです。

カスタムヘッダの確認

HTTPヘッダーのマッピングが設定できたら、動作確認してみます。 NLB配下のEC2にPHPをインストールし、DocumentRoot配下に下記のファイルを設置します。

index.php

<?php
print_r(getallheaders());

改めてブラウザからAPI Gatewayのエンドポイントにアクセスしてみます。

無事にHTTPヘッダが渡せてそうです。

リクエストIDをApacheのログに残す

せっかくなので、もう少し遊んでみます。 Apacheの設定を修正し、API Gatewayから連携されたリクエストID等の情報をログに残してみます。

Apacheの設定ファイルを修正し、統合リクエストでマッピングを設定したHTTPヘッダをログに残すように設定します。

    #LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{x-amzn-request-time}i %{x-amzn-source-ip}i %{x-amzn-request-id}i %{x-amzn-extended-request-id}i" combined

設定ファイル編集後にサービスをリロード、改めてAPI Gatewayのエンドポイントにアクセスすると・・・

10.0.0.27 - - [09/Aug/2018:02:40:43 +0000] "GET / HTTP/1.1" 200 523 "-" "AmazonAPIGateway_i6uvjdxs8d"
10.0.0.27 - - [09/Aug/2018:03:03:58 +0000] "GET / HTTP/1.1" 200 523 "-" "AmazonAPIGateway_i6uvjdxs8d" 09/Aug/2018:03:03:58 +0000 <アクセス元のGIP> dbea61ae-9b80-11e8-a3e3-078a3b79f244 LVhMuHjJNjMFvhA=

API Gatewayから連携された諸々の情報がログに出力されました!! ALB配下にEC2が並ぶような構成だとX-Forwaded-Forヘッダ等を使ってアクセス元のGIPをログに残すと思いますが、AGI Gateway - NLBの環境でもこのような手順を踏む事でアクセス元のGIPをログに残すことが可能になります。

まとめ

Private Integrationで作成したAPI GatewayからVPC内のWebサーバーにコンテキスト情報を連携する手順をご紹介しました。 API Gatewayのログ出力を有効にしつつ、Private Integrationで複数のWebサーバーにリクエストを分散させているような環境だと、API GatewayのログとWebサーバーのログを付き合わせるためのキーが必要になります。 今回ご紹介したような手順でWebサーバー側のログにもAPI GatewayのリクエストIDを残すように設定しておけば、有事の調査がスムーズに進められるのではないでしょうか。

誰かの役に立てば幸いです。