Amazon API Gateway Private APIの呼び出し方法と名前解決について整理する

# はじめに

API Gateway Private APIの呼び出し方法と利用するFQDNや名前解決がどこからできるかについて、毎回記憶喪失に陥って確認している気がするので整理してみました。


※前提として以下については記載しないのでご注意ください。

- セキュリティグループや、リソースポリシー、経路上のFirewall等のアクセス制御や、ルーティングの詳細に関する記載
- API Gateway Private APIの詳細な構築手順

# 構成環境に関する前提

## 呼び出し元環境

呼び出し元環境としては大きく
- VPC内
- Directconnectで接続されたオンプレミス環境

の2種類を考えます。

## 環境構成

- API Gateway Private APIを利用する場合、前提としてVPC内にAPI GatewayのインタフェースVPCエンドポイントを作成します
- 上述の呼び出し元として記載されているオンプレミス環境は、インタフェースVPCエンドポイントを作成したVPCとプライベートIPアドレスでの到達性があるものとします

## 参考情報
基本的には以下に従います。
（が内容を読み解くのにいつも時間がかかってしまうので本投稿にまとめてます:rolling_eyes:）

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-private-api-test-invoke-url.html

# 呼び出し方

大きくポイントとなるのは以下2つかなと思います。
- VPCエンドポイントのプライベートDNS名を有効にしているか否か
- 提供される各FQDN、ドメインはどこで名前解決できるか

上記のポイントを頭の片隅に置きながら、以下整理していきます。

## VPC内から呼び出す場合
### ～VPCエンドポイントのプライベートDNS名を有効にしている場合～
API Gateway のインターフェイス VPC エンドポイントの作成時に、[プライベート DNS 名を有効にする] オプションを有効化します。作成後に変更することも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/101a8a8b-81f0-f1e0-2a23-944ed655ea98.png)

上記設定を有効にすると、
VPCエンドポイントが配置されているVPCにおいては（※）、
API Gatewayから提供されるFQDN
`{restapi-id}.execute-api.{region}.amazonaws.com`
の名前解決結果がプライベートIPアドレス（VPCエンドポイントのIPアドレス）になり、
上記を利用することで作成したAPIの呼び出しが可能です。

`{restapi-id}.execute-api.{region}.amazonaws.com`
の名前解決は基本的には上述の通りVPC内からしか行えません。
（Amazon Route 53 Resolver Inbound Endpointを利用した方法については後程。）

※ 厳密にいうとDNSサーバとしてAmazon Route 53 Resolverが使われるようになっている場合、です。VPCの設定として「DNS解決を有効化」、「DNSホスト名を有効化」する必要があります。
上記が行われた状態であれば、Amazon Route 53 ResolverがVPC内のみで名前解決できるAWS側定義のFQDNの問い合わせをAmazon-provided
private DNS hostnamesのDNSにフォワードし、名前解決が行われます。  
Amazon Route 53 Resolverについては以下のBlackBeltが大変参考になります。

https://youtu.be/6nf6vIQha1g?si=acmBSKpc_5WITiHH

### ～VPCエンドポイントのプライベートDNS名を有効にしていない場合（有効にしていても使える）～

呼び出し方法としては以下の2種類あります。

- エンドポイント固有のパブリック DNS ホスト名を使用したプライベート API の呼び出し
- Route 53 エイリアスを使用したプライベート API へのアクセス

#### エンドポイント固有のパブリック DNS ホスト名を使用したプライベート API の呼び出し

Private APIが利用できるようになった当初から利用できていたのが、"エンドポイント固有のパブリック DNS ホスト名を使用したプライベート API の呼び出し"です。

VPCエンドポイントを作成すると、以下の2種類（※）のDNS名が作成されます。
※今回は1AZにしかエンドポイントを作成しなかったため2つですが、2つ目はAZ毎のもののため、AZ数が増えれば提供されるFQDN数も増えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/6aac0065-f628-e2ff-d98c-77e93dcaead1.png)

上記のFQDNの名前解決はパブリック（公開）DNSで行うことが可能ですが、返却されるIPアドレスはプライベートIPアドレス（VPCエンドポイントのIPアドレス）です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/669b1017-87fc-2561-691d-ce74dbf0737c.png)

ただ、上記を宛先にそのままリクエストを投げてもどのAPIに一致するのかが分からないため、以下のどちらかの方法でホスト名 or IDを伝えてあげる必要があります。

【ホストヘッダとして指定する方法（curlの場合）】
`curl -v https://{public-dns-hostname}.execute-api.{region}.vpce.amazonaws.com/test/pets -H 'Host: 01234567ab.execute-api.us-west-2.amazonaws.com'`

【 "x-apigw-api-id"でIDを伝える方法（curlの場合）】
 `curl -v https://{public-dns-hostname}.execute-api.{region}.vpce.amazonaws.com/test -H'x-apigw-api-id:{api-id}'`

なお、上述のDNS名はVPCエンドポイントのプライベートDNS名を有効にしている場合にも利用可能です。  
プライベートDNS名を有効にしている場合VPC内からは利用することはあまりないかもしれませんが、後述のDirectConnectから利用が併用される場合に利用することが考えられます。

#### Route 53 エイリアスを使用したプライベート API へのアクセス

こちらは2019年のアップデートで後から利用できるようになった機能です。

https://aws.amazon.com/jp/about-aws/whats-new/2019/09/amazon-api-gateway-simplifies-invoking-private-apis/

利用するには、対象のVPCエンドポイントとAPI GatewayのPrivate APIを紐付ける必要があります。具体的にはAPI Gateway側のAPIの詳細設定で、以下のようにVPCエンドポイントIDを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/df591d9c-3fa0-7691-a259-f854008d10c4.png)

上記を行うことにより、以下の形式のFQDNに対する名前解決がパブリック（公開）DNSサーバにて行われ、応答結果として紐付けたVPCエンドポイントのプライベートIPアドレスが返ります。

`https://{rest-api-id}-{vpce-id}.execute-api.{region}.amazonaws.com/{stage}`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/ba4e3be3-6255-6fa6-f95f-d81b0407a160.png)

この場合はFQDN内にAPI IDが含まれるため、ホストヘッダや "x-apigw-api-id"の付与は不要です。

### 補足：クロスアカウントの場合にどうなるか

基本的には前述の考え方と大きくは変わりませんが、以下が参考になります。

https://repost.aws/ja/knowledge-center/api-gateway-private-cross-account-vpce

## Directconnectで接続されたオンプレミス環境から呼び出す場合

Directconnectで接続されたオンプレミス環境から呼び出す場合についても、
VPCエンドポイントのプライベートDNS名を利用するかしないか（利用できるかできないか）の2パターンが考えられます。

参考：

https://repost.aws/ja/knowledge-center/api-gateway-on-premises

### VPCエンドポイントのプライベートDNS名を利用しないケース

まずシンプルな方を。
この場合は、上述の”～VPCエンドポイントのプライベートDNS名を有効にしていない場合（有効にしていても使える）～”に準じます。
パブリック（公開）DNSで名前解決が行えるため、返ってきたプライベートIPアドレスに対する経路的な接続性があれば到達可能です。

### VPCエンドポイントのプライベートDNS名を利用するケース

VPCエンドポイントのプライベートDNS名の名前解決は基本的にはVPC内からしか行えません。VPC外から名前解決を行うにはRoute 53 Resolver Inbound Endpointの利用が必要です。

Route 53 Resolver Inbound EndpointをVPC上に作成し、名前解決を行いたい環境のDNSにおいて、対象のドメインについてはRoute 53 Resolver Inbound Endpointに名前解決をフォワードする設定を追加します。

上記設定が行われている環境であれば、VPCエンドポイントのプライベートDNS名を利用可能です。
※VPCエンドポイントについてプライベートDNS名が有効化されていることが前提。

# API Gateway Private APIの注意点
## カスタムドメイン名は使えない → [2024/11/21]使えるようになりました！

2024/11/21のアップデートでPrivate REST APIでもカスタムドメイン名に対応しました:tada:
https://aws.amazon.com/jp/about-aws/whats-new/2024/11/amazon-api-gateway-custom-domain-name-private-rest-apis/

具体的な使い方はこちらが参考になります。（そのうち試したい。）
https://aws.amazon.com/jp/blogs/compute/implementing-custom-domain-names-for-private-endpoints-with-amazon-api-gateway/

~~API Gateway Private APIでは、カスタムドメイン名は使えません。~~
~~Developer Guideにも明記されています。~~

~~https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-private-apis.html#associate-private-api-with-vpc-endpoint~~


~~### カスタムドメイン名をどうしても使いたい場合の対処法~~


~~どうしてもカスタムドメイン名を利用したい場合は、VPC Endpointの手前にALB/NLBを挟むことにより実現可能です。~~

~~https://repost.aws/ja/knowledge-center/invoke-private-api-gateway~~

~~必要なリソースの作成の後、カスタムドメインのFQDNをALB/NLBと紐付けるDNS登録を行えば、（curlの場合）以下の形で呼び出すことができます。~~

~~`curl -v https://{custom-domain-name}/<stage-name>/<resource-path> -H 'Host: <api-id>.execute-api.<region>.amazonaws.com'`~~
~~または~~
~~`curl -v https://{custom-domain-name}/<stage-name>/<resource-path> -H 'x-apigw-api-id:{api-id}'`~~

~~FQDNにどのAPIを呼び出すかの情報がないため、明確にホストヘッダや"x-apigw-api-id"の情報を渡してあげることが必要です。~~

~~（ALB/NLBと同じような処理をクライアント側にさせればALB/NLBを挟まなくてもできるような気はしますが、公式ドキュメントで他の対処法は挙げられていないので、方法としてはこちらを取り上げます。）~~

## Public APIとPrivate APIの双方に接続が必要な場合は要注意

VPCエンドポイントのプライベートDNSが有効化されている場合、`*.execute-api.us-east-1.amazonaws.com `ドメインはプライベートDNSドメインとして扱われるため（パブリックDNSよりもプライベートDNSが優先されるため）、DNSの応答結果としてVPCエンドポイントのIPアドレスが返される形になります。
そのため、Public APIについても同じ形で名前解決が行われてしまい、接続できなくなってしまいます。（Public APIはVPCエンドポイント経由では接続できないため。）
上記状況を解消するためには、以下いずれかの対応をとる必要があります。

参考：

https://repost.aws/ja/knowledge-center/api-gateway-vpc-connections

### プライベートDNS名を有効化したまま利用する場合

Public APIをエッジ最適化カスタムドメイン名（※1）またはリージョンのカスタムドメイン名を設定してパブリック API に接続します。また、リージョンのカスタムドメイン名を利用する場合、CNAMEではなくAliasレコードを利用する必要があります（※2）。

※1：エッジ最適化の場合、カスタムドメインの紐付先FQDNがCloudFrontのFQDNになるため。（という理由の認識。）
※2：CNAMEの場合Valueに登録されているFQDNにもクライアントからリクエストが投げられる形になるが、Aliasレコードの場合はAWSで内部的に処理されて一度の処理で応答が返るため、`*.execute-api.us-east-1.amazonaws.com `に対してリクエストは投げられない = プライベートIPアドレスが返ってしまう問題を回避できる。（という理由の認識。）

### プライベートDNS名を無効化して利用する場合

こちらの場合、Private API利用時は上述の通りVPCエンドポイントに紐付くFQDNを明示的に指定する必要があり、`*.execute-api.us-east-1.amazonaws.com `の名前解決結果としてもパブリックIPアドレスが返ります。
そのため、特に意識せずに併用が可能です。

# まとめ

API Gateway Private APIの呼び出し方法と利用するFQDNや名前解決について整理しました。

個人的な感触としては、VPC内でPrivate APIだけを利用しているケース（やオンプレ側もRoute 53 Resolver Inbound Endpointを利用している場合）はプライベートDNS名を有効化しての利用が有用ですが、それ以外の場合は、プライベートDNS名を有効化せず、パブリックDNS名を利用した方がシンプルなケースもあるなと思いました。

今回何度か登場したRoute 53 Resolver始めとするVPC内の名前解決についてはどこかでまとめたいです。