概要
API Gateway のプライベート統合で 内部 ELB (ALB/NLB) を API Gateway のターゲットとしてリクエストする際、デフォルトでは HTTP でリクエストを投げます。

デフォルトでは、プライベート統合トラフィックは HTTP プロトコルを使用します。HTTPS を使用するには、https://example.com:443/test などの安全なサーバー名を含む uri を指定します。
ただし、統合リクエストに設定する Endpoint URL の スキームを https とすれば HTTPS でリクエストすることも可能です。
その場合、API Gateway から ターゲットとなる 内部 ELB に対して SSL/TLS ネゴシエーションが行われ、SSL/TLS セッションが確立されます。
つまり、内部 ELB 側にサーバー証明書を紐づければ良いということになります。

本記事では、API Gateway から 内部 ELB の HTTPS トラフィック化を検証していきます。
結論
先に結論ですが、以下の通りです。
- パブリック証明書 (公的に認められた認証局によって払い出された証明書) を 内部 ELB に紐づける場合は 可能
- プライベート証明書 (自己署名証明書 / 公的に認められていない認証局=プライベート認証局から払い出された証明書) を内部 ELB に紐づける場合は 原則不可
実は、API Gateway 自身が証明書検証の利用でサポートしている認証機関が一覧化されています。記載されている通りで、公的に認められた認証局しかありません。
API Gateway 自身はこれら認証局の証明書を内部的に持っているため、ターゲットELBに紐づけるサーバー証明書がこれら認証局から発行されていれば、SSL/TLS ネゴシエーションの際に証明書検証は成功し HTTPS で通信ができるということになります。
上記でプライベート証明書が原則不可と記載したのは、API Gatewayのメソッドを作成する際にパラメータとして証明書検証をスキップさせる設定を追加することで可能となる からです。
ただしこれは REST API のみサポート されているのと、マネジメントコンソールからは設定不可 となります。
設定するには 定義ファイルをインポートするか、Terraform で構築する必要があります。
検証
検証構成
検証構成図は以下の通りです。
ACM 発行のパブリック証明書と、自己署名証明書を 内部 ALB に紐づけています。
- 環境コードは以下 GitHub にあげてますので、よかったら覗いてみてください
ACM 発行パブリック証明書の場合
統合リクエストで指定する Endpoint URL のスキームは https としています。
発行した証明書は 内部 ALB に紐づけています。


この状態でテストを実行すると、問題なくレスポンスが返ってきます。

自己署名証明書の場合
まずうまく行かないパターンを見ていきます。
統合リクエストで指定する Endpoint URL のスキームは https としています。
発行した証明書は ACM にインポートし、内部 ALB に紐づけています。


この状態でテストを実行すると、証明書検証エラーとなっています。

ではこの証明書検証をスキップさせましょう。
API 定義ファイルのインポートでもできますが、今回は Terraform で構築しているのでそちらで対応します。
メソッドの統合リクエスト作成リソースにて以下の属性を追加します。
resource "aws_api_gateway_integration" "no_import_https_selfsigned_get" {
rest_api_id = aws_api_gateway_rest_api.no_import.id
resource_id = aws_api_gateway_resource.no_import_https_selfsigned.id
http_method = aws_api_gateway_method.no_import_https_selfsigned_get.http_method
type = "HTTP_PROXY"
connection_type = "VPC_LINK"
response_transfer_mode = "BUFFERED"
integration_http_method = "GET"
connection_id = aws_apigatewayv2_vpc_link.this.id
integration_target = aws_lb.private_alb.arn
uri = "https://selfsigned.${var.domain_name}"
timeout_milliseconds = 29000
cache_key_parameters = []
request_parameters = {}
content_handling = null
credentials = null
passthrough_behavior = "WHEN_NO_MATCH"
request_templates = {}
+ tls_config {
+ insecure_skip_verification = true
+ }
}
適用後同じくテストを実行すると、問題なくレスポンスが返ってきます。

おわりに
本記事では、Amazon API Gateway のプライベート統合トラフィックを HTTPS 化する方法について整理しました。
AWS グローバルネットワーク内に閉じてはいるものの、要件によっては必要な対応となりますので、その際はぜひ参考にしてみてください。
🌟この記事が誰かの役に立てば幸いです!
また、ご質問やフィードバックもお待ちしています。
番外編
プライベート統合では 統合リクエスト に指定する Endpoint URL はルーティングに使用されない
統合リクエストにてバックエンドの URL を指定するのですが、この値はルーティングに使用されない、つまり 名前解決をして宛先を特定してリクエストする という動きはしません。

公式のドキュメントでは見つけられませんでしたが、Terraform のドキュメントに記載がありました
For private integrations, the URI parameter is not used for routing requests to your endpoint, but is used for setting the Host header and for certificate validation.
ではプライベート統合では何に使われるかと言うと、上記にも記載があるもの含め以下 3 つです。
- リクエストのホストヘッダー
- 証明書検証 (ハッシュ値検証、ホストヘッダーと証明書のCN値比較)
- リクエストのプロトコル ( HTTP or HTTPS )
この状態でテストをすると問題なく Internal ALB からレスポンスが返ってきました。
VPC Link ENI から送られたリクエストのホストヘッダーには変更した値になっていますね。

この状態でテストをすると Internal server error となりました。
これは、ALB側で HTTPS リスナーを作成していないからです。
スキームに応じてリクエストのプロトコルが変わっているのがわかります。

以上のことから、プライベート統合における Endpoint URL はルーティングに使用されていないことがわかります。
統合先の NLB or ALB が HTTP/HTTPS どちらで受け付けているかに応じてスキームを変更しつつ、ALB にてホストヘッダーベースのルーティングを行っている場合はそれに応じたFQDNを指定する という使い分けを行いましょう。
参考資料
リファレンス
- API Gateway REST API で VPC リンク統合を使用する際の 500 エラーのトラブルシューティング方法を教えてください。 - re:Post
- API Gateway での HTTP および HTTP プロキシ統合のための API Gateway 対応の証明機関 - デベロッパーガイド
- x-amazon-apigateway-integration.tlsConfig オブジェクト - デベロッパーガイド
- Amazon Trust Services







