【AWS】 Route 53 + ACM + CloudFront + S3 の構成を構築する際にいろいろつまずいた件

# この記事の対象者

-  Route 53 + ACM + CloudFront + S3 構成を構築しようと試みている人
-  Route 53 + ACM + CloudFront + S3 構成を構築してみたがいまいち全体像がわからない人
-  AWS で独自ドメインで HTTPS 通信で Web サイトを配信したい人
-  AWS 初心者

# はじめに

AWS で Web サイトを独自ドメインで配信するにはどうしたらいいのか調べてたところ、どうも Route 53 + ACM + CloudFront + S3 の構成がスタンダードのようでした。

【参考】
・[AWSにおける静的コンテンツ配信パターンカタログ（アンチパターン含む）](https://dev.classmethod.jp/articles/static-contents-delivery-patterns/)

そして、この構成についての参考になるサイトがたくさん存在します。

以下リンクになります。

・[AWSで独自ドメインのhttpsな静的Webサイトを構築する（ACM+S3＋CloudFront+Route53）](https://t-dilemma.info/static-website-hosting-by-aws-2020)
・[AWSをフル活用してブログをdevドメインに移行した](https://blog.pirox.dev/2019/03/16/337/) 
・[Amazon S3 + AWS Certificate Manager (ACM) + Amazon CloudFront + オリジンアクセスアイデンティティ(OAI) でhttpsサイト公開](https://www.seeds-std.co.jp/blog/creators/2019-12-24-124054/)

**特に1番上の記事は全ての手順に画像があるので非常にわかりやすかったです。**

初めはこれらに相当する記事を書こうと思ったのですが、上記のようにそのような記事は既にあったため、**この記事は自分が実際に環境を構築した際につまずいたところについて書いていきたいと思います。**

# つまずいたところ解説

基本的にここのサイトの手順になぞって構築してうまくいきました。
・[AWSで独自ドメインのhttpsな静的Webサイトを構築する（ACM+S3＋CloudFront+Route53）](https://t-dilemma.info/static-website-hosting-by-aws-2020)

個人的につまずいたところを書いていきたいと思います。

## 全体感がつかめない（この記事のメイン）

解説の記事通りやっても、かなり操作が多いため、途中で自分が何を、何のためにやっているか分からなくなります。

全体感が分かりやすくなるように、私なりに解説していきます。

まず、サンプルとして以下の値を設定するとして、**各サービス別での**操作を書いていきたいと思います。

### 設定値（サンプル）

- 独自ドメイン名：`hogehoge.com`
- S3 バケット名：`mogemoge-bucket`
- 発行される CloudFront ドメイン名：`nantoka.cloudfront.net.` ← 実際は設定不可能な値
- 一般ユーザーがサイトにアクセスする際のURL：`https://pokapoka.hogehoge.com`

### 各サービスごとに実施する操作

#### **独自ドメイン発行サービス（お名前.com や freenom など、もちろん Route 53 でドメインを買ってもよい）**

-  `hogehoge.com` というドメインを発行する（末尾が `.com` である必要はない）

#### **Route 53**

- `hogehoge.com` の HostedZone （ ＝ DNS レコードを格納できるところ） を作成する（Route 53 でドメインを購入した場合は自動で作成される）
-  （この操作は CloudFront 設定後の作業）CloudFront で代替ドメイン名（CNAMEs）として登録したドメイン `pokapoka.hogehoge.com` と、CloudFront 
の Distribution のドメイン `nantoka.cloudfront.net.` を結びつけるために ALIAS レコード（A レコード）を挿入する

#### **ACM（AWS Certificate Manager）**

- `hogehoge.com` と `*.hogehoge.com` というドメインに対する証明書を発行する（ワイルドカードを使ってドメインある程度まとめてドメインを発行したほうがあとあと便利）（参考：[パブリック証明書のリクエスト](https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/gs-acm-request-public.html)）

#### **S3**

- `mogemoge-bucket` というバケットを作成する（今回の構成ではドメイン名と合わせる必要はありません）
- `mogemoge-bucket` を静的ウェブサイトとして公開する
- `mogemoge-bucket` に静的コンテンツをアップロードする（最低限 index.html があればよい）

#### **CloudFront**

- CloudFront の Distribution 作成する
  - Distribution を S3 の `mogemoge-bucket` に指定
  - Distribution の代替ドメイン名 (CNAMEs) を `pokapoka.hogehoge.com` と登録する（複数登録することも可能）
  - さきほど ACM で作成した証明書を指定する
- Distribution 作成すると Distribution のドメインが自動的に発行される（`nantoka.cloudfront.net.` など）（※このドメイン名は自動発行）
- Distribution を作成後に CloudFront の Distribution の origin access identity（OAI）の編集から S3 の `mogemoge-bucket` へのアクセスを CloudFront を介してのみに制限する（これを行うとワンクリックで `mogemoge-bucket` のバケットポリシーが更新される）（これを設定しないと S3 の `mogemoge-bucket` は静的ウェブサイトとして公開しているため、CloudFront を経由せずに直接アクセス可能になってしまう）

### 操作の結果

そして、これらの手順の結果、各 AWS のサービスの状態と、その状態が表す意味は以下のようになります。

#### Route 53

- CNAME レコード
  - ACM の DNS 検証 で挿入したレコード
        - **（解説）**証明書の発行のときに挿入したよ、普段はとくに使わないよ、このレコードがある間は ACM が証明書の自動更新をやってくれるよ
- A レコード
  - `pokapoka.hogehoge.com` = `nantoka.cloudfront.net.`
        - **（解説）**`pokapoka.hogehoge.com` は `nantoka.cloudfront.net.` のフリをするよ、名前解決のときに使うよ


#### ACM（AWS Certificate Manager）

- 証明書
  - `hogehoge.com` と `*.hogehoge.com` というドメインに対する証明書
        - **（解説）**この証明書は ACM で管理しているよ、一度、証明書を発行したらここの設定を変えることはないよ
      
#### CloudFront

- Distribution
  - S3 `mogemoge-bucket`
      - **（解説）**`nantoka.cloudfront.net.` のアクセス先は S3 の `mogemoge-bucket` だよ
- Distribution CNAMEs
  - `nantoka.cloudfront.net.` = `pokapoka.hogehoge.com`
      - **（解説）**`nantoka.cloudfront.net.` は `pokapoka.hogehoge.com` のフリをするよ、基本的に `pokapoka.hogehoge.com` でアクセスされたのを `nantoka.cloudfront.net.` に読み替えるよ
- SSL Certificate
  - `*.hogehoge.com` の証明書を設定
      - **（解説）**この Distribution では `*.hogehoge.com` の証明書を使うよ

#### S3

- 静的ウェブサイトホスティング設定
  - 有効
      - **（解説）**HTTP/HTTPS のリクエストがきたら `mogemoge-bucket` の中身をWebページとして返却するよ
- パケットポリシー
  - CloudFront のみ OK
      - **（解説）**`mogemoge-bucket` にアクセスにするには必ず CloudFront を経由してくださいね、それ以外の経路でアクセスしたら断ますよ

### 全体像

ここで、全体像を確認したいと思います。

まず、名前解決を含めた Web サイトにアクセスした際の通信のフローは以下の図のようになります。
![how-route-53-routes-traffic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/cc7589f5-b5c8-da4c-951a-3a9f5287f6b3.png)

大きく分けて以下のフローに分けれれます。

- 1 〜 7 ：ドメインの名前解決
- 8 〜 9 ：コンテンツ配信

そのフローを、 Route 53 + ACM + CloudFront + S3 構成の全体像で当てはめると以下のようになります。
![img_5f01d1bdc21cb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/b4bf6ff7-fa70-0396-0622-07574e98e252.png)

**Route 53 は 「ドメインの名前解決する役割」 と 「ACM の証明書リクエストを検証する役割」があるということが分かります。**

**また、CloudFront は 「証明書が置いてある Web サーバーとしての役割」 と 「キャッシュサーバーとしての役割」 があることがわかります。**

ちなみに、8 〜 9のコンテンツ配信は SSL 通信をしており、その詳細のフローは以下の図のようになります。
![fig02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/4d0fae3c-4d8f-18ce-10d3-27864870af43.png)

【参考】
・[AWSで独自ドメインのhttpsな静的Webサイトを構築する（ACM+S3＋CloudFront+Route53）](https://t-dilemma.info/static-website-hosting-by-aws-2020)
・[ウェブサイトやウェブアプリケーションへのインターネットトラフィックのルーティング](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/welcome-dns-service.html)
・[SSL/TLSとは何か](https://www.lac.co.jp/library/ssl/3.html)

## SSL やら DNSサーバー やら 証明書 が何だかわからない

今回の構成は SSL やら DNSサーバー やら 証明書 やらその辺の知識が必要になってきます。

ITパスポートレベルの基礎的なことだと思うのですが、自分はこの辺の理解が乏しく、よくわからないまま環境を構築することになりました。

（自分が無知なだけでありますが、）AWS の公式ドキュメントは割とそのあたりの知識があることを前提としているので、**基本的な用語などについては別で調べて、よく理解しながら進むしかないと思います。**

以下、よく見たサイトのリンクになります。

**暗号化通信**
・[HTTPS と SSL と TLS：その違いを５分でわかりやすく解説！](https://blog.qbist.co.jp/?p=1441)
・[SSL/TLSとは何か](https://www.lac.co.jp/library/ssl/3.html)

**DNS レコード**
・[DNSレコード](https://qiita.com/leomaro7/items/7d717077dd9165357f16)
・[AレコードとCNAMEレコードの違い](https://qiita.com/PharaohKJ/items/b6a933b7f79afe8a32e1)

## freenom で無料ドメインが発行できない

この構成での解説記事は [freenom](https://www.freenom.com/ja/index.html?lang=ja) というサイトで無料ドメインを作成して、それを用いて検証しているものが多くありました。

それに習って、無料ドメインを作成したかったのですが、なぜか作成できませんでした。

なので、仕方なく AWS の Route 53 は有料でしたが、年間 12-14 ドルほどで購入できるとのことでしたので、Route 53 でドメインを購入しました。

ドメインの購入は一瞬で作成できたので、初めから Route 53 で購入しておけば楽だったと後悔しました。

【参考】
[Route53でドメインを購入方法](https://qiita.com/takashi8816/items/d6d7edc711494dd24e0d)


## ACM での証明書のリクエスト時の DNS 検証がよくわかわからない

ACM での証明書のリクエストはなにやっているかわからなくて、何度も調べたので、私なりにまとめました。
（結局、[公式ドキュメント]((https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/gs-acm-validate-dns.html))を読んだらよく理解できました。）

以下、解説になります。

ACM では証明書のリクエストをすると Amazon 認証局 (CA) が証明書を発行する前にドメイン名の所有者または管理者であることを検証します。

その検証の方法は以下の 2 種類があります。

1. DNS 検証
2. E メール検証

公式ドキュメントにもあるように DNS 検証の方が証明書の自動更新などの恩恵を受けられるので E メール検証よりも **DNS 検証**が推奨されています。

DNS 検証の手順は以下の通りです。

1. DNS 検証を選択する
2. DNS データベースに挿入する CNAME レコードを ACM が発行される
3. 発行された CNAME レコードを DNS データベースに挿入する（Route 53 を DNS プロバイダにしている場合はACM のコンソールからワンクリックで挿入可能）
4. CNAME レコード挿入後、しばらくすると自動的に ACM が DNS 検証を完了します（完了までに数分かかります）

ここで発行される CNAME レコードの値は ACM が所有するドメインを指すエイリアスであり、ACM が証明書を自動更新するときに使用されるらしいです（ここでのレコードの値については特に気にする必要はない理解）。

ACM での証明書のリクエストで行っていることはこのような感じになります。