【AWS】クロスアカウントでDNS委任設定を行う

ミロゴス株式会社では複数のAWSアカウントを運用していますが、クロスアカウントで大元のドメインからサブドメインへDNSの管理を委任したい場合があります。
よくやる手順の割にまとまった情報がなかったので記事にしました。ついでにCloudFrontとAPI Gatewayへのサブドメイン内でのドメインの設定も合わせて記載しておきます。

## 前提
構成図は以下です。
![arch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/451d055d-6155-1aab-57e3-ef812752f977.png)
要件が単純なアプリなので、Next.jsはCSR/SSGのみ(next export)でCloudFront + S3でホストし、BFFを挟んでバックエンドへアクセスするように作っています。
Next.jsのサーバーは建てないで普通に素のNode.jsでLambdaを動作させていて、これらをCI/CD含めてほぼAWS CDKで完結させています。

ただ、ドメインの設定はACM周りの関係上CDK内では作成せず、手動で設定しています。(初回だけですし...)

## 手動設定の流れ
アプリケーションとは別アカウントに大元のホストゾーンがあるので、そちらからアプリケーションが載っているAWSアカウント上へ管理を委任します。(下図のドメイン名は例です。)
![dns.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/418954a0-458d-73aa-8e09-1621d6ac7c44.png)

管理している親アカウントで委任したい子アカウントのNSレコードを作成するだけで良いです。これだけで図の例だと`app.milogos.co.jp`へのアクセスがあった場合、子アカウントの方に問い合わせに行くようになります。([JPRS用語辞典｜委任](https://jprs.jp/glossary/index.php?ID=0152))
このDNS委任設定を行っておくと、それ移行は`app.milogos.co.jp`のドメインに子アカウント内で自由にレコードを追加できるようになります。

## DNS委任設定の手順
- AWS マネジメントコンソールからRoute 53の画面を開き、ダッシュボードから「ホストゾーンの作成」をクリックします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/2fe42421-aea3-801b-7920-25f93311ba7e.png)


- ドメイン名に新しく作成するドメイン名を入力して、ホストゾーンを作成します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/ba8b55f2-a168-b847-a630-c46b61ccd0f6.png)


- ホストゾーンが作成できたら、レコード一覧でNSレコードを見つけて、そちらの4行の値を控えておきます。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/5c4747a2-33ba-268a-add0-6711c81f5449.png)


- 委任元のホストゾーンでレコード作成を行います。レコード名は先程作成したものと合わせるようにし、レコードタイプを「NS - ホストゾーンのネームサーバー」を選択し、値/トラフィックのルーティング先を「レコードタイプに応じたIPアドレスまたは別の値」を選択した後に、先程控えておいた4行のレコードを記載します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/62d4c99e-cd4a-da29-5001-feabea71ede9.png)


以上でDNS委任の設定は完了です。
つづいて委任先ホストゾーンで、実際にCloudFrontとAPI Gatewayにカスタムドメインを設定する方法を紹介します。

## CloudFrontのDNS設定
- 下図のようにAレコードを作成画面を開きます。エイリアスにチェックを入れ、トラフィックのルーティング先を「CloudFront ディストリビューションへのエイリアス」にして、ドメイン名を入力します。(補完が効かない場合は、対象ディストリビューションのディストリビューションドメイン名をコピーしてきて貼り付けます。)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/4d5c197d-cae0-5473-842d-f0b044e1034c.png)


- レコードが作成できたら、CloudFrontの対象ディストリビューションの画面を開き、一般->設定の「編集」をクリックします。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/d0dc79d9-c5d3-478d-4c0a-f32bd5129ff4.png)


- 編集画面の中程にある「代替ドメイン名(CNAME)-オプション」の「項目を追加」をクリックして、設定したいドメイン名を入力します。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/4abe3174-9d81-416a-e0fe-2587037a72e0.png)


- すぐ下にある「カスタムSSL証明書 - オプション」の「証明書をリクエスト」のリンクをクリックします。別タブでAWS Certificate Managerが開くので、そのまま「次へ」をクリックします。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/9c1ee6f6-4bbd-8919-18aa-2531bd2b3988.png)


- パブリック証明書をリクエストの画面で、「完全修飾ドメイン名」で設定したいドメイン名を入力し、他はデフォルトのまま「リクエスト」をクリックします。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/faa9190b-29ea-44d1-784a-9789ee0d8c7d.png)


- 証明書の一覧画面に遷移して、証明書が表示されるので、リンクをクリックして開きます。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/385f016a-33b6-de3b-c5af-3e09013df309.png)


- 「ドメイン」の「Route 53でレコードを作成」をクリックします。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/3612f519-1cd9-c106-7ab9-8469d6ade19b.png)


- レコードの作成画面が表示されるので、そのまま「レコードを作成」をクリックします。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/c9e82261-0017-1400-4f06-54081bad46ef.png)


- CloudFrontの画面に戻り、「カスタムSSL証明書 - オプション」の右にある更新ボタンを押して更新すると、今発行した証明書が選択できるようになっているので選択し、画面下部の「変更を保存」をクリックして変更を完了します。
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/e53af3b0-9576-f260-a247-a555a9694e6f.png)


- ディストリビューションの画面に戻ると、「代替ドメイン名」に設定したドメインが表示されます。
![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/5405fc3d-75e5-c3a7-a752-41641878b6fb.png)


## API Gatewayでのカスタムドメインの設定
- API Gatewayのコンソールで、カスタムドメイン名を選択して「作成」をクリックする。ドメイン名を作成画面でドメイン名に設定したいドメインを入力します。
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/87d6c885-7639-c777-8ebb-fbe1b2b51e01.png)


- ホストゾーンでレコードを作成する。エイリアスに切り替えて、トラフィックのルーティング先は「API Gateway APIへのエイリアス」、対象のリージョンを選択し、ホスト名に対象API Gatewayのデフォルトで発行されるドメイン名を入力しておきます。
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/9f819e85-b5d2-82b1-e03b-e7d8f74b07a6.png)


- レコードを作成したら**CloudFrontのDNS設定**と同様の手順で証明書を作成し、「ドメイン名を作成」をクリックします。
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/a79122e2-c7d7-cef6-21a0-c58940d77ef4.png)


- 以下のようにカスタムドメインが作成されます。(デフォルトエンドポイントを無効化する場合は、API Gatewayドメイン名を控えておく。)
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/35f10e14-c8ad-6be5-857d-fee697b4be59.png)


- APIマッピングタブで「APIマッピングを設定」をクリックします。
![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/08ec244f-0b5c-5fcd-24a1-f19f9ebf24b0.png)


- APIとステージ、パスを選択して保存。ここまでの設定で`ドメイン名/パス`でマッピングしたステージのエンドポイントを叩けるようになります。
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/d311c919-0928-af0b-d3e7-e56a467d9846.png)


- API Gatewayのデフォルトエンドポイントの無効化をする場合は、作成してあるAレコードを編集し、トラフィックのルーティング先を控えておいたAPI Gatewayドメイン名に変更します。(おそらく補完が効く。)
![23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/863cd70e-b549-1a39-0a5a-a7bc8b3b4ccb.png)


- デフォルトエンドポイントを無効化する場合は以下を参照
[REST API のデフォルトエンドポイントの無効化 - Amazon API Gateway](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/rest-api-disable-default-endpoint.html)

## まとめ
複数のゾーンを管理して、リソースとの紐付け、証明書の発行までサクサクできてしまうのはやはりAWSの強みですね。