API GatewayのVPCエンドポイント導入で障害が発生してしまったw

はじめに

社内でAPI Gatewayを使いたいという要望があったため調査しましたが、問題なさげ。
導入するならAPI GatewayVPCエンドポイントを導入しようとなりました。
VPCエンドポイントを使えば公共のインターネットから隔離された(AWS環境内の)通信でプライベートAPIへのアクセスが可能になります。
参考リンク

VPCエンドポイントを導入

[VPC] - [エンドポイント] - [エンドポイントの作成]から
[サービスカテゴリ]は「AWS サービス」のままで
[サービス名]はAPI Gateway(com.amazonaws.<リージョン名>.execute-api)を選択。
f:id:rioner2525:20190314085505j:plain
VPCサブネットおよびセキュリティグループ(443通信のインバウンドが必要)を選択。

あとは今回の障害ポイントになるのですが、プライベートDNSについては公式で有効が推奨となっていたので有効にしてました。

障害発生

あるシステム担当から他社さんのAPIが全部403応答になっててやばwと連絡を受けました。
先日にAPI GatewayVPCエンドポイントを導入したうちのせいやん...と思って調査したところ、そのAPIはパブリックなAPIで素の名前(xxxxxxxx.execute-api.<リージョン名>.amazonaws.com)だったようです。
公式サイトにも書いてあった以下の記述を見逃したことで障害となりました。

プライベート DNS を有効にすることを選択した場合、API にプライベートまたはパブリック DNS を経由してアクセスできます。(この設定は、API にアクセスできるユーザーには影響を与えません。使用できる DNS アドレスにのみ関係します。) ただし、プライベート DNS を有効にした API Gateway VPC エンドポイントを使用して、VPC からパブリック API にアクセスすることはできません。

つまりパブリックなAPIを素の名前のまま呼んでいた場合はVPCエンドポイントを通って通信しようとしてアクセスできずに403応答となっていたようです。

原因図解

VPCエンドポイント作成時、プライベートDNSを有効にしていた場合の通信経路は以下。
f:id:rioner2525:20190314113606p:plain
パブリックなAPIへの通信はカスタムドメイン名などを利用して代替のURLが用意されている必要があるようです。
素の名前(xxxxxxxx.execute-api.<リージョン名>.amazonaws.com)ではVPCエンドポイントから先に通信できず障害となりました。

(改善案)プライベートDNSを無効にしていた場合の通信経路は以下。
f:id:rioner2525:20190314114110p:plain
この場合はパブリックなAPIへの通信が素の名前でもVPCエンドポイントではなくIGWを経由して通信されます。
ただしプライベートAPIへの通信をVPCエンドポイントに向けるため、以下のように宛先としてエンドポイントの指定と実体となるプライベートAPI Gatewayをヘッダ情報としてホスト指定する必要があります。

curl -v https://vpce-0c1308d7312217cd7-01234567.execute-api.us-east-1.vpce.amazonaws.com/test -H'Host:0qzs2sy7bh.execute-api.us-west-2.amazonaws.com'

参考リンク

まとめ

素の名前のパブリックなAPIを呼ばないならプライベートDNSは有効で導入してOK。
よく分からないなら無効で導入した方が丸いと思いますが、この場合は既にプライベートなAPIを呼んでいないか注意が必要。
どちらにしろAPI GatewayVPCエンドポイント導入時にはシステム側でどこかのAPI Gatewayで作成されたAPI(~.execute-api.<リージョン名>.amazonaws.com)を呼んでいないか調査が必要ですね。

(2019/07/18追記)
すいません。 まとめ の箇所に記述ミスがありました。
よく分からないなら無効で導入した方が丸いと思いますが、この場合は既にプライベートなAPIを呼んでいないか注意が必要。 とありますが、VPC エンドポイントが存在していないとプライベートAPIを呼べないため注意するとかなかったです。

結果、無効の方がよくね?となりますが以下の2つのうちどちらを許容するかという話になります。
①有効の場合、パブリックAPIを素の名前で呼べなくなる
②無効の場合、プライベートAPIを呼ぶときに毎回ヘッダ情報を付ける

①有効の場合はパブリックAPIをカスタムドメインで呼べばいい話です。
他社のAPIAWSの素の名前のまま呼ばなくてはならない状況でもなければ問題ないハズ。
自社開発用パブリックAPIの場合はカスタムドメインを設定するか公開するまではプライベートAPIとすればよいです。
②無効の場合はパブリックAPIAWSの素の名前のまま呼べます。
プライベートAPIについては毎回ヘッダ情報を付けて呼ぶ必要があります。

どちらにしても一度設定して運用を始めると変えることは難しいと思われます。
丸いから無効とするよりベストプラクティスである有効の方で導入を検討することをおすすめします。
有効の方がスッキリしてて変な運用がいらないので。

(2019/11/27追記)
プライベートDNSが無効でも簡単にプライベートAPIを呼べるようになるアップデートが来ました!
rioner2525.hatenablog.com