【AWS】CloudFront + S3 + ALB のhttps構成を構築してみました

#はじめに
最近 CloudFront と S3 を組み合わせて、静的コンテンツを S3 で配置するアーキテクチャが増えてきているような気がします。
元々 ALB 後ろの EC2 に保存していた画像とかを、S3 に転換配置することによって、EC2 へのアクセス負担軽減効果が得られるではないでしょうか。
今回は CloudFront の後ろに、S3 と ALB を両方組み合わせて、構築してみました。

#構成図
構成図は下記となります。簡単に説明させていただきます。
１．前提条件として、Route 53でドメインを取得済みであること。
２．ユーザー→CloudFront→ALB はhttpsでのアクセスとなります。
３．CloudFrontに ```cloudfront.XXXXX.com```というサブドメインを設定します。
４．ALBに```alb.XXXXX.com```というサブドメインを設定します。
５．S3とALBはそれぞれ CloudFront の OAI として設定されております。
６．外部から直接 S3 内のオブジェクトへのアクセスは不可です。
７．外部から直接 ALB 用のサブドメインへのアクセスは不可です。
８．外部からは CloudFront を通してのみ、ALB と S3 内の資材にアクセスすることが出来ます。
９．ACM で証明書を発行しており、それぞれ CloudFront と ALB に関連付けしています。

![cloudfront.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/0494b2c9-73be-503e-270f-865c3c3bb656.png)

#１．EC2作成と配置
今回私が使用しているEC2は Amazon Linux 2 です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/cc95fded-b9a3-c30b-4113-5efe6c8e3c2e.png)

「ユーザーデータ」に、下記のコマンドを入力し、EC2 が起動後に nginx をインストールしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/9495ee9d-0f8f-baeb-97a1-0865bd0571a2.png)


```
#!/bin/bash
amazon-linux-extras install epel -y
yum install nginx -y
systemctl start nginx
systemctl enable nginx
```

EC2が起動後に、nginx 配下で dadada ディレクトリを作成し、htmlファイルを配置しておきます。

```
sh-4.2$ cd /usr/share/nginx/html
sh-4.2$ pwd
/usr/share/nginx/html
sh-4.2$ sudo mkdir dadada
sh-4.2$ cd dadada
sh-4.2$ pwd
/usr/share/nginx/html/dadada
sh-4.2$ sudo vi index.html
sh-4.2$ sudo systemctl restart nginx
sh-4.2$ cat index.html
<!DOCTYPE html>
<html>
<head>***************************************************************************************************
  <link rel=""shortcut icon"" href=""#"" />
  <meta charset=""utf-8"" />
  <title>Page Title</title>
</head>
<body>
  <h1>CloudFront-ALB-EC2 Test Page <br>Hello World!</h1>
  <p>***************************************************************************************************</p>
</body>
</html>"
```

#２．ACMで証明書を作成
今回作成するACM証明書は、二つリージョン内にあります。
・CloudFront用証明書：```バージニア北部```リージョン側で```*.xxxxx.com```証明書を作成
・ALB用証明書：```東京```リージョン側で```*.xxxxx.com```証明書を作成

まず最初は```バージニア北部```リージョン側で作成しておきます。
ACMの証明書作成画面で```証明書のリクエスト```を押下し、```証明書のリクエスト```を押下します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/db696058-1245-a666-ee0a-ad778a4a5086.png)

ここに```*.xxxxx.com```を入力します。（xxxxx.comはドメイン名）
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/c0fed359-5c57-4b50-2345-4c749be992a5.png)

検証方法は```DNSの検証```を選択しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/ced268f7-d982-59f2-649a-b9f66a7e84df.png)

タグは追加せずに、```確認```を押下します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/43588476-3210-9729-99d9-d0fff86c8a7b.png)

確認後に、```確定とリクエスト```を押下します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/957e3a74-b88a-ffcc-2016-64b781d877e2.png)

```Route 53 でのレコードの作成```を押下し、追加しておいてください。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/dee70b8b-8742-a340-7e07-161b9262e635.png)

しばらくすると、```バージニア北部```リージョン側で、状況が```発行済み```に変更されていれば完了です。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/c1a5fb8c-4031-d3f4-0166-ab953bf87906.png)

同じように、```東京```リージョン側で```*.xxxxx.com```証明書を作成しておいてください。
作成完了後はこんな感じです。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/bc2a8c5d-a2d8-bdf3-2a2b-244663c74b2b.png)

#３．ALBを作成
```Application Load Balancer```を作成します。
EC2→ロードバランサー画面で作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/5433d907-39b0-5a77-039c-838b1681bb3b.png)

名前欄に、適宜に入力をしてください。
```リスナー```欄には、```HTTPS```の```443```を選択してください。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/b2a24844-df4a-68d1-8d14-5ab18284d32e.png)

AZは、パブリックサブネットを選択します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/3ad04316-5bd7-f313-0d75-375f48d17eb0.png)

証明書タイプに```ACMから証明書を選択する（推奨）```をクリックし、先ほど東京リージョンのACMで作成された証明書を選択してください。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/b27e8a10-10f0-08d5-1374-1c5f2399a4f2.png)

セキュリティーグループは、HTTPS 443ポートを全部開放とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/a209557f-a67d-e8f1-36b9-3c5ab46efae1.png)

ターゲットグループに```新しいターゲットグループ```を選択の上、名前は適宜ご入力ください。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/42e6383e-bf6f-e4d9-6965-017cb2d1be59.png)

EC2を選択し、```登録済みの追加```をクリックし、ALBを作成してください。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/4f135753-4255-5490-e7b4-f7b20cfee993.png)

Route 53画面を開き、新規のレコードを追加します。
・```レコード名```に、ALB用のサブドメイン名を記入します。
・```レコードタイプ```は、Aレコードを選択します。
・```エイリアス```をオンの上、先ほど作成されたALBを選択してください。
上記項目が選択しおわったら、```レコードを作成```をクリックします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/da9051bd-781f-72e0-e607-fe4d25cf4df0.png)

ALBのリスナールールは、下記のように変更設定をしておいてください。
・IF ホストがalb.xxxxx.com THEN 転送先 ec2-test: 1 (100%)
グループレベルの維持設定: オフ
・IF それ以外の場合はルーティングされないリクエスト THEN 固定レスポンスを返す 503
Content-Type:text/plain
レスポンス本文:Error Page
(未満...)

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/4ce4c5ae-4bda-84ef-b649-05fba9919fea.png)

ここで、ALBのサブドメインで直接アクセスをしてみたところ、無事に反映されていますね！
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/9131a690-ff91-0081-0eed-0292130576d3.png)

#４．S3 を作成
以前私が直接CloudFormationでS3を作成したことがあるので、下記のURLにご参考していただいて、作成していただければと思います。

|項目            | 設定 |
|:------------------|:------------------|
|デフォルトの暗号化(SSE-S3)|有効|
|バージョニング機能|有効|
|ブロックパブリックアクセス(バケット設定)|有効|

https://qiita.com/lalala233/items/2ece21a23bd738dde4a2

S3作成完了後に、S3で```lalala```というフォルダを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/e53ee616-8e66-9cc6-6b9b-cc4d9e21df1c.png)

作成完了後に、下記のhtmlファイルをS3へアップロードしておきます。

```html
<!DOCTYPE html>
<html>
<head>***************************************************************************************************
  <link rel="shortcut icon" href="#" />
  <meta charset="utf-8" />
  <title>Page Title</title>
</head>
<body>
  <h1>CloudFront-ALB-S3 Test Page <br>Hello S3!</h1>
  <p>***************************************************************************************************</p>
</body>
</html>
```

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/ccd4bd19-502c-770d-ac77-b188b0cb9ccb.png)

#５．CloudFront作成と設定
CloudFront の Distributions 画面で、```Create distributions```を押下します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/0029dd5d-7812-c21c-d7f2-017ee1d663d1.png)

・```Origin domain```に先ほど作成していたS3を選択してください。
・```S3 bucket access```に```Yes use OAI```を選択します。
・```Create new OAI```をクリックします。
・```Bucket policy```に```Yes, update the bucket policy```を選択します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/83948f8e-622f-8628-e442-5d22eeeb8382.png)

```Redirect HTTP to HTTPS```を選択します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/2e168572-179d-ca2e-1eaa-02b4e1fe7e6b.png)

ここの設定はデフォルで大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/4129adf9-89f4-a25b-83cb-961eede349b3.png)

ここの設定はデフォルで大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/58216a69-a969-91fa-3e73-22ea41063eaa.png)

ここの設定はデフォルで大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/39a24262-9b23-10d9-020b-0206a673266b.png)

```Create distribution```を押下します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/ecff1ec9-38b1-30d6-4fa6-806748e78ffd.png)

Route 53画面を開き、新規のレコードを追加します。
・```レコード名```に、CloudFront用のサブドメイン名を記入します。
・```レコードタイプ```は、Aレコードを選択します。
・```エイリアス```をオンの上、CloudFrontの```Distribution domain name```を記入します。
上記項目が選択しおわったら、```レコードを作成```をクリックします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/1b285d9e-96e3-6a2a-119a-18f4f1a42635.png)

CloudFront画面で、```Settings```を編集します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/e4c1df1e-ae64-ff3b-1bca-4e1480af5dd0.png)

・```Alternate domain name (CNAME) - optional```に、先ほど作成したCloudFrontのサブドメイン名を記入します。
・```Custom SSL certificate - optional```に、バージニア北部リージョンで作成したACM証明書を選択します。
以上選択し終わったら、保存を押下します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/074e5648-d026-f57f-1311-9497fc3ca89b.png)

CloudFront画面で、```Create origin```を押下します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/e37705cf-f758-a056-272f-cd0127e9bf91.png)

（★★★★★ここ超重要★★★★★）
・```Origin domain```はALBのサブドメイン名を記入します！！！！！！！！！
ALBのDNS名ではないので、くれぐれもご注意ください！！！！！！！！
・```Protocol```は```HTTPS only```を選択します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/d59048b4-75b9-a5a4-cd7d-19af97403d15.png)

（★★★★★ここ超重要★★★★★）
```Add header```を押下し、お好みのヘッダーを追加してください。
今回私は適当に入れてあります。
記入後に、メモをしておいてください。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/685d3e43-049d-76b0-eb85-8051b98caf0c.png)

```Behaviors ```で、```Create behaviors```を押下します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/60cc7a71-c0bd-c3e0-cb89-9bbfe41e4f71.png)

・```Pate pattern```に、ALB用のパスである```/dadada/*```を入力します。
・```Origin and origin groups```に、先ほど作成したALBのoriginを選択します。
・```Viewer protocol policy```に、```HTTPS only```を選択します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/42d19cce-f997-710a-7252-32ec54ccf121.png)

ここの設定はデフォルで大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/359a0c11-f825-f423-3c64-a07f594a5b06.png)

ここの設定はデフォルで大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/cedca490-cfe8-85b9-11ad-a7d37376be80.png)

ALBのリスナールールを開き、下記のように編集をします。
先ほど好みで入力していたヘッダーネームを、ALBのルール内に埋め込みます。
・IF HTTP ヘッダー laslkdfsidfjoisanfiowen が2348732u85oisdnfsnfd 
ホストがalb.xxxxx.com
THEN 転送先
ec2-test: 1 (100%)
グループレベルの維持設定: オフ
・IF それ以外の場合はルーティングされないリクエスト THEN 固定レスポンスを返す 503
Content-Type:text/plain
レスポンス本文:Error Page
(未満...)
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/85e83a1f-7994-b57d-707c-ab36489a6d66.png)

#６．疎通確認
ALBのサブドメインでアクセスすると、アクセス不可となります。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/b3d13f4f-7050-a174-e36f-7eb05285bee6.png)

CloudFrontのサブドメインから、```/lalala/index.html```をアクセスすると、S3配下のファイルにアクセスできていることを確認できております。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/0b7a5d06-8300-6382-e25f-b9d33f985a9c.png)

CloudFrontのサブドメインから、```/dadada/index.html```をアクセスすると、EC2のnginx配下のファイルにアクセスできていることを確認できております。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/555edf4d-c991-c019-f6e8-6489a6645b46.png)

S3バケットのポリシーが更新されていることを確認できました。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/f924d22b-e08e-0c91-8ece-2b942fdb4711.png)

S3内のオブジェクトのURLへ直接アクセスすると、アクセス不可が確認できました。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/442cf6fd-2a65-0833-d42a-acf7254643c1.png)
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/5a59b0a1-94da-cabf-76be-da27872d026f.png)

上記をまとめると、

|項目            | 設定 |
|:------------------|:------------------|
|CloudFrontのサブドメインからS3へアクセス|可能|
|CloudFrontのサブドメインからALBへアクセス|可能|
|ALBのサブドメインへのアクセス|不可|
|S3のオブジェクトURLへのアクセス|不可|

これで確認ができました！

#７．注意事項
CloudFrontは作成後から反映するまでは、時間がかかる場合はありますので、もし設定直後にうまく反映されていない場合は、焦らずに待ちましょう～

本記事は誰かにお役に立てれば幸いです！
宜しくお願い致します。