Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

API Gateway経由でVPC内からプライベート/パブリックAPIへアクセスする方法

By Tomer RadianSep 16, 202517 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

本記事では、Regional APIエンドポイントタイプで定義されたパブリックAPIを扱うAPI Gatewayについて解説します。

TL;DR実装手順はこちら

クラウド中心の現代のアーキテクチャにおいて、APIはサービス間通信を支える基盤です。Amazon Web Services(AWS)が提供する強力なAPI Gatewayを使えば、開発者はあらゆる規模でAPIの作成・公開・運用・保護を行えます。

よくあるシナリオとして、VPC内のサービスからパブリックAPIとプライベートAPIの両方にアクセスする必要があるケースが挙げられます。パブリックAPIのURLには次の2つの形式があります。

1. API Gatewayが自動生成するデフォルトURL: api-id.execute-api.REGION.amazonaws.com

2. カスタムドメイン名(例: api.mydomain.com)。任意のドメイン名と証明書を利用できます。

まずカスタムドメイン名における課題と解決方法を説明し、その後、API Gatewayが生成したURLを利用する方法について解説します。

問題となるのは、カスタムドメイン名をRoute 53以外でホスティングし、CNAMEレコードを使用しているケースです。

本記事の目的は、VPC内からプライベートAPIとパブリックAPIへシームレスにアクセスできる環境を構築し、効率的かつセキュアなサービス間通信を実現することにあります。

パブリックなカスタムドメイン名をRoute 53でホストし、API Gatewayドメイン名へAliasレコードで向けている場合、同一VPC内からパブリックAPIとプライベートAPIを併用しても問題は起こりません。

しかし以下で見ていくように、外部DNSプロバイダー(CNAMEレコードしか使えない)を利用する場合は、正しいDNS解決とSSL証明書の検証を成立させるために追加の手順が必要になります。

用語

API Gatewayドメイン名

API Gatewayドメイン名とは、APIのカスタムドメイン名を構成した際にAWSが作成する、AWSマネージドのエンドポイントです。APIのデフォルトエンドポイントapiID.execute-api.REGION.amazonaws.comに対するエイリアスとして機能し、TLS終端と扱いやすいURLを実現します。

仕組みは次のとおりです。

1. パブリックAPIエンドポイントの2タイプにおけるAPI Gatewayドメイン名の構造

  • Edge-Optimized:

グローバルで低レイテンシーのアクセスを実現するため、CloudFrontディストリビューション(例: d123.cloudfront.net)を使用します。

  • Regional:

リージョン固有のエンドポイント(例: d-abc123.execute-api.us-east-1.amazonaws.com)を使用します。

2. DNS構成

  • DNSプロバイダー(例: GoDaddy):

カスタムドメイン名(api.mydomain.com)をAPI Gatewayドメイン名(例: d-abc123.execute-api.us-east-1.amazonaws.com)へ向けるCNAMEレコードを作成します。

  • GoDaddyでのDNSレコード例:

Name: api.mydomain.com

Type: CNAME

Value: d-abc123.execute-api.us-east-1.amazonaws.com

  • このレコードにより、api.mydomain.com宛てのトラフィックがAPI Gatewayのエンドポイントへルーティングされます。

3. 証明書の関連付け

  • AWS Certificate Manager(ACM)証明書:

API Gatewayでカスタムドメイン名を定義する際、ACM証明書(例: *.mydomain.com)を紐付けます。

  • 証明書のSubject Alternative Name(SAN)には、カスタムドメイン名(例: api.mydomain.com、またはトップレベルのワイルドカード*.mydomain.com)が含まれている必要があります。
  • API Gatewayはこの証明書をエッジレイヤーでのTLS終端に使用します。

4. 全体の連携 — リクエストの流れ

  • クライアントがhttps://api.mydomain.comへリクエストを送信します。
  • DNSがAPI Gatewayドメイン名(例: d-abc123.execute-api.us-east-1.amazonaws.com)に解決します。
  • AWSのDNSがAPI GatewayドメイN名をAWS GatewayサービスのパブリックIPに解決し、ACM証明書によるTLS終端とトラフィックの負荷分散が行われます。
  • API Gatewayが、カスタムドメイン名にマッピングされたAPIとステージを呼び出します。

問題点

問題の核心は、プライベートAPIへのアクセスに必要なAPI Gateway用VPCエンドポイントにあります。VPCエンドポイントでPrivate DNSを有効化していると、パブリックAPIへアクセスする際に厄介な問題が発生し得ます。具体的には、SSL証明書の問題でパブリックAPI呼び出しが失敗してしまうのです。これを理解するには、このアーキテクチャ構成下でのDNS解決の挙動を押さえる必要があります(Appendix A参照)。

カスタムドメイン名を持たないパブリックAPIには、インターネット上の誰もがアクセスできるパブリックエンドポイントURLしか存在しません。

パブリックAPIはインターネット経由でのみ呼び出せるため、Private DNSが有効化されたAPI Gateway用VPCエンドポイントを持つVPC内からこのURLを呼び出そうとすると、インターネットではなくVPC経由でAPIを呼び出そうとし、HTTP 403(Forbidden)エラーが返されます。

パブリックAPIをカスタムドメイン名にマッピングする場合は、証明書が必要です。

Route 53でAlias型Aレコードを作成し、カスタムドメイン名でパブリックAPIを呼び出すように構成すれば、Private DNSが有効なAPI Gateway用VPCエンドポイントが存在する場合でも、VPCからプライベートAPIとパブリックAPIの両方を呼び出せます。

ドメインを外部プロバイダーでホストしている場合は、外部DNSにCNAMEレコードを作成することになります。

このCNAMEレコードこそが問題の根本原因です。

カスタムドメイン名でパブリックAPIを呼び出すと、それをAPI Gatewayドメイン名にマッピングするレコードを取得するためのDNSルックアップが発生します。続いて、最初のルックアップで返されたAPI Gatewayドメイン名のIPアドレスを取得するため、2回目のDNSルックアップが必要になります。

Private DNSが有効でなければ、ルックアップはパブリックAPIのパブリックIPを返します。これが本来期待される動作です。

このパブリックIPはAWS Gatewayサービスのものであり、同サービスはカスタムドメイン名に関連付けられた証明書のSubject Alternative Name(SAN)からカスタムドメイン名を探します。カスタムドメイン名の証明書(例: mydomain.com)はAPI Gatewayドメイン名と関連付けられているため、SSLハンドシェイクは成功し、パブリックAPIが呼び出されます。

一方、VPCにPrivate DNSが有効化されたAPI Gateway用VPCエンドポイントがある場合、このPrivate DNSがAPI Gatewayドメイン名のルックアップをキャッチし(execute-api.REGION.amazonaws.comのすべてのサブドメインを捕捉するため)、VPCエンドポイントのElastic Network Interface(ENI)に割り当てられたプライベートIPを返します。

このプライベートIPはAPI Gatewayサービスのアドレスであり、apiID.execute-api.REGION.amazonaws.com形式のプライベートAPIエンドポイントURLに該当する内部URLエンドポイントしか受け付けません

結果として次のような状態になります。

Private DNSが有効なAPI Gateway用VPCエンドポイントが存在する状態でパブリックAPIを呼び出した結果

このように、VPC内からパブリックAPIを呼び出そうとすると必ずSSLハンドシェイクが失敗し、接続がブロックされてしまいます。

ソリューションの概要

すでに説明したとおり、API Gateway用VPCエンドポイントでPrivate DNSが有効になっていると、execute-api.REGION.amazonaws.comに対するDNSルックアップがすべてプライベートIPに解決されてしまい、カスタムドメイン名を使ったパブリックAPI呼び出しがSSL検証で失敗します。解決策は、Route 53のプライベートホストゾーンを利用してDNSの優先順位付けを行うこと、いわゆるSplit-Horizon / Split-View DNSです。

プライベートホストゾーン(PHZ)を用意すると、VPC内からのDNSルックアップは、他のパブリックDNSサーバーを参照する前にPHZを先に確認するようになります。

たとえば、トップレベルドメインmydomain.comをホストしているGoDaddy DNSサーバーがあるとします。

api.mydomain.comをパブリックAPIにマッピングする場合は、このサブドメインをPHZ DNSにホストしてsplit-view DNSを構築します。

これにより、VPC内から発行されたapi.mydomain.comのルックアップはPHZから応答され、API Gatewayを使わない他のサブドメイン(VPCエンドポイントが捕捉しない別サービスを指すものなど)へのアクセスはパブリックDNSで解決されるようになります。

このソリューションは、次の3つの要素で構成されます。

  1. VPCエンドポイント: プライベートAPIへのアクセス用(Private DNS有効)
  2. プライベートホストゾーン: split-view DNSの構築用
  3. PHZ内のAlias型Aレコード: パブリックAPI Gatewayドメイン名へトラフィックを誘導するためのレコード

実装手順

前提条件

  • Route 53以外でホストされ、インターネットから呼び出し可能なカスタムドメイン名を持つパブリックAPI Gateway。または、Route 53でホストされているもののAlias型AレコードではなくCNAMEレコードでカスタムドメイン名を向けているパブリックAPI。
  • パブリックAPIを呼び出したいVPC内に定義された、Private DNSが有効なAPI Gateway用VPCエンドポイント。

このVPCエンドポイントが既にある場合は、下記のステップ2から始めてください。

無い場合は、プライベートAPIを呼び出すことができません。

1. プライベートAPIにアクセスするためのAPI Gateway用VPCエンドポイントを構成する

このエンドポイントが既にある場合は、ステップ「2」へお進みください。

  • AWSコンソールでVPCコンソール > エンドポイントへ移動します。
  • com.amazonaws.REGION.execute-apiのインターフェースエンドポイントを作成します。
  • Private DNSを有効化します(デフォルト設定)。
  • VPCからのインバウンドHTTPS(ポート443)を許可するセキュリティグループを割り当てます(またはプライベートAPI Gateway APIの呼び出しを許可したいVPC内の特定リソースのIPからのみ許可するセキュリティグループでも構いません)。

2. プライベートホストゾーンを作成する

  • Route 53コンソールで、パブリックなカスタムドメイン名のAPIパス(例: api.mydomain.com)に一致するPHZを作成します。

パブリックドメインに、呼び出したいがAPI GatewayにマッピングされていないURLが存在する場合(例: dev.mydomain.comがAPI Gatewayではなくロードバランサーを指している場合)、プライベートホストゾーンのドメイン名にはAPIの完全なカスタムドメイン名(例: api.mydomain.com)を指定してください。

ドメイン内のすべてのサブドメインがAPI Gateway APIにマッピングされている場合は、トップレベルのmydomain.comをドメイン名に使用します。

  • ゾーンをVPCに関連付けます。

カスタムドメイン名用のPHZを作成し、このドメインへのアクセスが必要なVPCに関連付けます

3. DNSレコードを設定する

  • APIで使用される各ドメインに対して、Alias型Aレコードを作成する必要があります。

たとえばapi.mydomain.comspecial-api.mydomain.comがある場合、それぞれにレコードを作成します(api用とspecial-api用)。レコードタイプには「A」を選択してください。

  • レコード名について:

- カスタムドメイン名がAPIの完全なドメイン名と同じ場合は、「レコード名」にサブドメイン(「api」)を入力せず、空欄のままにしてください。たとえばAPI Gatewayで使う唯一のサブドメインとしてapi.mydomain.com用のPHZを作成した場合、レコード名フィールドは空欄のままにします。

- 複数のサブドメインをAPI Gatewayにマッピングしているためトップレベルのmydomain.comを使用している場合は、各レコードの「レコード名」にAPIの名前を入力します。たとえば一方には「api」、もう一方には「special-api」と入力します。

  • 「alias」ボックスにチェックを入れてAliasレコードに設定します
  • 「Alias to API Gateway API」を選択します
  • APIのリージョンを選択します
  • パブリックAPIのリージョナルエンドポイント(カスタムドメイン名用に作成されたAPI Gatewayドメイン名)を選択します。

名前は次のような形式です。

d-abc123.execute-api.REGION.amazonaws.com

  • 一覧に表示されない場合は、API Gatewayコンソールの「カスタムドメイン名」→ API Gatewayドメイン名からコピーしてください。
  • レコードを保存します

新しく作成したプライベートホストゾーンがVPCで利用可能になるまで、Route 53で多少時間がかかる場合があります。

本ソリューションのアーキテクチャはAppendix Bを参照してください。

動作確認

パブリックAPIを呼び出すために、インターネット接続のあるEC2をVPC内で稼働させる必要があります。

EC2インスタンスに接続し、以下のURLをご自身のものに置き換えて実行します。

curl -v https://your-public-api.yourdomain.com/your-path

次のような出力が得られるはずです。

PHZの作成・構成前は、Private DNS(API Gateway用VPCエンドポイントに関連付けられたもの)がカスタムドメイン名に対してプライベートIP(10.0.3.79)を返しており、このプライベートIPはVPCエンドポイントのENIのものでした。カスタムドメイン名用のPHZを作成すると、API GatewayドメイN名のパブリックIPが取得できるようになり、本例では次のとおりです。

IPv4: 44.221.197.141, 34.192.177.183, 34.232.190.93

デフォルトのパブリックAPI Gateway URLを使う場合

プライベートAPIとパブリックAPIを併用するには、まずAPI Gateway用VPCエンドポイントに関連付けられたPrivate DNSを無効化します。次にexecute-api.REGION.amazonaws.comという名前のPHZを作成し、プライベートAPIをホストするVPCへのアクセスを許可したいすべてのVPCに関連付けます(別リージョンのVPCに関連付けるケースは、本記事「ボーナス」セクションに関連します)。

続いて、すべてのAPI Gateway API-IDを捕捉するためのワイルドカードレコードを以下のように作成します。

このリージョンのプライベートAPI用ホストゾーンを作成

次に、VPCエンドポイントのDNSを指す「キャッチオール」レコードを以下のように作成します。

このリージョンのすべてのプライベートAPI用キャッチオールレコードを作成

これにより、us-east-1で定義されたプライベートAPI GatewayのすべてのURLがこのPHZに捕捉され、API Gateway用VPCエンドポイントのプライベートIPアドレスが返されるようになります。

カスタムドメイン名を持つパブリックAPIについては、そのカスタムドメイン名用のPHZを作成すれば問題が解決することは前述のとおりです。

カスタムドメイン名を持たないパブリックAPIについては、APIのAPI IDを使ったAliasレコードを追加し、それをパブリックURLへ向ける必要があります。

たとえば、us-east-1にURLがbmf11pk5je.execute-api.us-east-1.amazonaws.comのパブリックAPIがあるとします。

これをVPC内から呼び出すと、前述のカスタムドメイン名のシナリオと同じく「Forbidden(403)」が返されます。これを解決するには、「bmf11pk5je」というレコードを追加し、次のように呼び出しURLへ向けます。

これで、このレコードに定義したパブリックAPIをVPC内から呼び出せるようになります。同じリージョンで別のパブリックAPIを呼び出したい場合も、同様にAliasレコードを追加していきます。

ボーナス

あるリージョンに配置したプライベートAPIを、別のAWSリージョンのVPCから呼び出す方法を解説します。

問題点

プライベートAPIは、同一リージョン内の複数VPC間であれば容易に共有できます。各VPCにAPI Gateway用VPCエンドポイントを配置し、これらのVPCからのアクセスを許可するリソースポリシーをプライベートAPIに設定したうえで、API設定からVPCエンドポイントをプライベートAPIに追加するだけです。

ところが、VPCがプライベートAPIをホストするリージョンと異なるリージョンにある場合は、これでは機能しません。

その場合は、以下の手順が必要です。

  1. 2つのVPC、すなわちプライベートAPIをホストするVPCとアクセスを付与したいVPCをピアリングします。

VPCピアリングを行うには、両VPCのCIDRブロックが重複していないことを確認する必要があります。 2. プライベートAPIをホストするAPI Gatewayリージョン用のプライベートホストゾーンが無ければ、新規に作成します。 3. プライベートホストゾーン(PHZ)の名前は次のとおりにします。

execute-api.REGION.amazonaws.com 4. このPHZを、当該リージョンのAPI Gateway用VPCエンドポイントと、アクセスを付与したいVPCの両方に関連付けます。 5. PHZにAlias型Aレコードを追加します(「alias」ボックスにチェックを入れてaliasに設定)。続いてドロップダウンから「Alias to VPC Endpoint」を選択します。 6. アクセスを付与したいVPCのリージョンを選択します。 7. このVPC内のAPI Gateway用VPCエンドポイントを選択します。 8. ピアVPCのCIDRブロックを、VPCエンドポイントのセキュリティグループに追加します。これがないとピアVPCからの通信がブロックされます。 9. レコードを保存します。

以上が完了すれば、別リージョンのVPCからプライベートAPIを呼び出せるようになります。

VPCピアリングを利用しているため、プライベートAPI Gatewayのリソースポリシーでピア接続元VPCからのトラフィックを承認する必要はなく、デプロイ先のメインVPCからの承認だけで十分です。これは、ピアVPCから発信されたトラフィックであっても、API Gatewayへの通信は同一VPC内のVPCエンドポイント経由で届くためです。

ただし、このクロスリージョンピアリング構成でも、プライベートAPIと同じVPCに定義されたパブリックAPIへアクセスしようとすると、SSL証明書エラーという同じ問題が発生します。別リージョンであっても、execute-api.REGION(APIがデプロイされているREGION)用のPHZと関連付けられているため、パブリックAPI用のPHZを定義しない限り、VPCエンドポイントのプライベートIPを呼び出そうとしてしまうのです。

クロスリージョンか否かに関わらず、プライベートAPIとパブリックAPIの両方を呼び出したい場合は、本記事前半の手順に従ってください。

Appendix A

下図は、Private DNSが有効なAPI Gateway用VPCエンドポイントを持つVPC内のEC2インスタンスから、パブリックAPI Gatewayを呼び出した際の挙動を示しています。

PHZが無いVPCからパブリックAPIを呼び出した場合

  1. EC2がhttps://api.mydomain.com,を呼び出そうとし、DNSルックアップが行われる
  2. DNSからの応答はAPI Gatewayドメイン名
  3. 2回目のDNSルックアップが行われ、API Gateway用VPCエンドポイントに関連付けられたPrivate DNSが捕捉する
  4. VPCエンドポイントのプライベートIPアドレスが返される
  5. EC2はこのプライベートIPアドレス経由でAPIを呼び出そうとする
  6. プライベートIP経由で到達するAPI Gatewayサービスは*.execute-api.REGION.amazonaws.comに対する証明書を提示するが、api.mydomain.comには対応していないため、証明書エラーが返される

Appendix B

下図も同様に、Private DNSが有効なAPI Gateway用VPCエンドポイントを持つVPC内のEC2インスタンスからパブリックAPI Gatewayを呼び出した際の挙動を示しています。ただし今回は、カスタムドメイン名用のプライベートホストゾーンも定義されているケースです。

PHZがあるVPCからパブリックAPIを呼び出した場合

インターネットからパブリックAPIを呼び出す

  1. APIのカスタムドメイン名(例: api.mydomain.com)について、外部のドメインホスティングサービス(例: GoDaddy)にDNSルックアップが行われる
  2. クエリは、このカスタムドメイン名に対するAPI Gatewayドメイン名を返す
  3. API Gatewayドメイン名がAWSのRoute 53に問い合わせられる
  4. パブリックAPI GatewayサービスのパブリックIPアドレスが返される
  5. このパブリックIPでAPI Gatewayサービスが呼び出され、api.mydomain.comの証明書と関連付けられているためSSLが終端され、API Gatewayの該当ステージのターゲットが呼び出される

VPC内からプライベートAPIを呼び出す

6. プライベートAPIはapiID.execute-api.REGION.amazonaws.com形式のURLを持ちます。このURLが、Private DNSが有効なAPI Gateway用VPCエンドポイントを持つVPCから呼び出されると、リクエストはこのPrivate DNSによって処理されます。

7. Private DNSは、API Gateway用VPCエンドポイントのENIのプライベートIPを返します。

8. このプライベートIP経由で到達するAPI Gatewayサービスは*.execute-api.REGION.amazonaws.com用の証明書を持っているため、このURLを使ったプライベートAPI呼び出しは認証を通過し、プライベートAPIのターゲットへ転送されます。

VPC内からパブリックAPI Gateway APIを呼び出す

9. カスタムドメイン名用に作成されたプライベートホストゾーンDNSが、自身のドメイン名配下のクエリを捕捉して処理します。

10. PHZにはAlias型Aレコードがあり、カスタムドメイン名に関連付けられたAPI Gatewayドメイン名のパブリックIPを返します。

11. このパブリックIPがインターネットゲートウェイ経由で呼び出され、API Gatewayサービスのアドレスに到達します。パブリックIPで到達するサービスはカスタムドメイン名とAPIドメイン名の証明書関連付けを保持しているため、SSLハンドシェイクは成功してTLSが終端されます。リクエストはAPI GatewayパブリックAPIの該当ステージのターゲットへ転送されます。

お問い合わせ

本記事が皆さまの参考になりましたら幸いです。さらに詳しく知りたい方や、当社サービスにご関心のある方は、ぜひお気軽にご連絡ください。お問い合わせはこちらから。

参考文献

もっともシンプルな解決策は、パブリックなカスタムドメイン名をRoute 53でホストし、Alias型Aレコードを使うことです。これなら、Private DNSが有効なAPI Gateway用VPCエンドポイントが存在する状況でも、パブリックAPIとプライベートAPIを呼び出せます。

それが難しい場合は、本記事で紹介した方法を活用してください。

留意点

  1. Private DNSが有効なAPI Gateway用VPCエンドポイントが存在する場合、当該リージョン内のすべてのAPI GatewayパブリックAPIへの呼び出しが証明書不一致エラーで失敗します。本記事でapi.mydomain.comのみを取り上げたのはあくまで例示にすぎません。たとえばapi.mydomain.comapi.example.commyapi.myspecialdomain.comがある場合、各ドメインに関連性がないため、それぞれにPHZを用意する必要があります。
  2. 本記事ではREST APIを前提に説明していますが、これはプロトコルの問題ではなくネットワークとDNSに関する問題のため、HTTP API(検証済み)やWebSocket API(未検証)でも同様に機能します。