VPC内からPublicなAPI gatewayにアクセスできなくて困った話

VPC内のEC2インスタンス(以下EC2)から、PublicなAPI gateway(以下API)にリクエストを送ると403が返ってきて困りました。
なんとか解決できて個人的に腑に落ちるところまで来たので整理がてら記事にしようと思います。

今回は例として以下の構成で進めていきます。
**構成例**
![Untitled Diagram-Page-11 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382072/c198b99f-4d4e-50ff-328b-0f652a17b8fb.png)

構成図を見るだけだとアクセスできるじゃん？って思うかもしれませんが、残念ながらできませんでした。

## TL;DR
- InterNetGateway(以下IGW)からリクエスト行ってると思ったらVPCEndPoint(以下EndPoint)からリクエストが行っていた
- エッジ最適化のカスタムドメインをAPIにアタッチしてやると、パブリックなAPIにアクセスが可能になる
- 同VPCからPrivateなAPIにアクセスする構成がある場合にこの事象が発生する。

## 解決までの流れ
### VPC周りの設定を見直してみる。
まず『VPC内のEC2からAPIを叩いたときに403エラーが返されている』という報告をうけました。

例)

```
$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev
```

今回の事象が発生したAWSアカウントは弊社のアカウントのうちの一つなので詳しい情報は流せませんが、専門のインフラチームが整備しており、基本的な導線や弊社が提供しているサービスのバックエンドで必要な構成が作成されていました。
設定を見返すと、同VPCのEC2が配置されたサブネットにはIGWが設置されており、ルーティングも整っていました。

この時一番初めに上げた構成図を頭でイメージしており、『理論上は叩くことが可能だよな……』と思っていました。

### 実は以前も同様の事象が起きていた。
実は以前も似たような事象が起きており、その際は **APIにエンドポイントタイプがエッジ最適化のカスタムドメインをアタッチし、カスタムドメインを利用して呼び出す。** そうすることで解決したらしいです。

VPC周りの設定はある程度確認したので、あまり理解しきらないままひとまず同じ方法で当たってみようと思い、叩くことが出来ないAPIにエッジ最適化のカスタムドメインをアタッチし、カスタムドメインを利用してEC2からAPIにリクエストを送ってみます。

```
$ curl https://custom-domain.com
```

**通りました**

### どうして通ったのか、どうしてデフォルトのURLではダメだったのか。
実は、以前も同じ事象があったよということを教えてくれたメンバーは同時に1つの記事を教えてくれました。
[API GatewayのVPCエンドポイント導入で障害が発生してしまったw](https://rioner2525.hatenablog.com/entry/2019/03/14/124149)
この記事を読み解いていくと、どうやらある条件に当てはまる場合、VPC内からはデフォルトのURLではpublicなAPIへのリクエストがブロックされるようです。

その条件が以下
- execute-apiのEndPointがVPCにアタッチされている
- Private DNS names enabled が true になっている

実際VPC内からPrivateなAPIを叩く要件が既に存在していたので、この構成がとられていました。またその構成を守るためには上記の設定は外すことが出来ません。
そのためEC2からのリクエストはEndPointに届くようになり上記の設定によりブロックされていたというのが真相です。

そうなってくると、初めに上げた構成図は以下のようになります。
![Untitled Diagram-Page-11 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382072/19f32761-0256-e7bd-1986-c300739074d1.png)

そこで、カスタムドメインをアタッチしすることで導線がEndPoint経由ではなく、IGWを経由してくれるようになります。この構成を取ることでアクセスできるようになるということですね。
![Untitled Diagram-Page-11 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382072/f5597def-65d6-6fbf-9f42-038673a1155b.png)

また[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-private-apis.html#apigateway-private-api-create-interface-vpc-endpoint)にもあるように、カスタムドメインのエンドポイントタイプはあくまで **エッジ最適化** であるべきだそうです。
>エッジ最適化されたカスタムドメイン名を使用してパブリック API にアクセスする (プライベート DNS を使用してプライベート API にアクセスする) 方法は、プライベート DNS を有効にしてエンドポイントを作成した VPC からパブリック API とプライベート API の両方にアクセスする方法の 1 つです

## 最後に
ということで簡単にではありますがVPC内からPublicなAPIにアクセスする方法をまとめてみました。
要件的にはあるあるな話だと思うので覚えておいて損ない話なのではないかと思います。

以上です。それでは良きAWSライフを。

### 参考
[API GatewayのVPCエンドポイント導入で障害が発生してしまったw](https://rioner2525.hatenablog.com/entry/2019/03/14/124149)
[【公式Doc】VPC での DNS の使用](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-dns.html#vpc-dns-updating)
[【公式Doc】インターフェイス VPC エンドポイント (AWS PrivateLink)
](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpce-interface.html#vpce-private-dns)[【公式Doc】API Gateway execute-api のインターフェイス VPC エンドポイントの作成](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-private-apis.html#apigateway-private-api-create-interface-vpc-endpoint)