AWS CloudFrontとS3を使用して、webサイトをhttpsで公開する方法

業務でよく、APISpecのSwaggerViewをS3+CloudFrontの構成で公開する事が多く、毎回やるたびに工程が多くて忘れてしまうので、備忘録として残しておきます。
私のAWS歴は約半年程ですが、たぶん初心者の方でもできるぐらい詳しく書いたつもりなので、分からない所とかあればコメントいただけると、わかる範囲でお答えします。

# 1. s3バケットを作成する
### 必須の設定項目
1. このバケットのブロックパブリックアクセス設定⇒パブリックアクセスをすべてブロック
これ以外は自由に設定して問題ないと思われるが、一通りデフォルトの状態で問題ないので、バケット名だけ入力してバケットを作成でOK

###  ページにベーシック認証を付ける場合
1. cloudShellを開き、以下のようなコマンドを叩く({}内は任意の文字列)
```echo -n "{ID}:{password}" | base64```
するとこのような形のランダムな文字列が生成される
```aAAfCAiut5bvsD6gTA==```
これをコピーしておく
2. ``cloudFront``で関数ページを開き、関数を作成する(名前と説明のみ適当につければOK)

3. 作成した関数を開き、下までスクロールし、開発コードページを編集していく

4. 以下のコードのうち、6行目```  var authString = "Basic aG9nZTpob2dlaG9nZQ==";```の``Basic``以下の文字列を先ほどコピーしたものに編集する

```javascript:関数コード
function handler(event) {
  var request = event.request;
  var headers = request.headers;

  // echo -n user:pass | base64
  var authString = "Basic aAAfCAiut5bvsD6gTA==";

  if (
    typeof headers.authorization === "undefined" ||
    headers.authorization.value !== authString
  ) {
    return {
      statusCode: 401,
      statusDescription: "Unauthorized",
      headers: { "www-authenticate": { value: "Basic" } }
    };
  }

  return request;
}
```

5\. 変更を保存を押し、上部タブから発行を選択し、関数を発行ボタンをクリックする
6. 以上でベーシック認証用の``CloudFront関数``が使用できるようになる

# 2. CloudFrontでディストリビューションを作成する
### 必須の設定項目
#### オリジン
1. オリジンドメイン⇒1で作成したS3バケットを指定
2. オリジンアクセス⇒Origin access control settingsにチェック
3. Origin access control⇒コントロール設定を作成を押して、設定を変えずに、作成ボタンを押す
#### デフォルトのキャッシュビヘイビア
変更なし
#### 関数の関連付け
1. ページにベーシック認証を付ける場合、ビューワーリクエストに先ほど作成した関数を設定する(ベーシック認証を付けない場合はスキップ)
1. 関数タイプにCloudFront Functionsを設定して、関数 ARN/名前で先ほど作成した関数を設定する

#### ウェブアプリケーションファイアウォール (WAF) 
1. 任意だが、今回は保護しない方にチェックを入れる

#### 設定
1. 料金クラス ⇒ 北米、欧州、アジア、中東、アフリカを使用にチェック
2. 代替ドメイン名（CNAME）⇒ 実際に使用したいURLを入力する
2. カスタムSSL証明書⇒証明書をリクエストをクリックし、別タブでACMを開く
2. パブリック証明書をリクエストにチェックを入れたまま、次へ
2. 完全修飾ドメイン名⇒2で入力したドメイン名をベースに、ワイルドカードを用いて入力する
```:例
代替ドメイン名: my-page.my-world.net
完全修飾ドメイン名: *.my-world.net
```
このようにすることで、今後別のCloudFrontでキャッシュしたページを作成する際に、○○.my-world.netというドメインを利用することが容易になる
6. それ以外の設定はデフォルトのままでリクエストする
7. 今作成した証明書のステータスが発行済みになるまで待つ
8. 発行済みになったら、再度CloudFrontのタブに戻って、カスタムSSL証明書の項目右側にあるリロードボタンを押すと、発行した証明書が表示されるはずなので、選択する
9. デフォルトルートオブジェクトはこのドメインにアクセスしたときに一番最初に表示してほしいファイル(ほとんどの場合index.htmlになるのかな？)
10. 画面一番下までスクロールして、必要であれば説明を記入して、ディストリビューションを作成ボタンを押す 

# 3. S3のバケットポリシーを設定する
1. 先ほど作成したCloudFrontディストリビューションを開き、オリジンのタブから、作成したオリジンを選択して、編集ボタンを押す
1. ページ中ほどに、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/2ca5c79e-895a-6812-8aad-4a8e36d784ef.png)
このような表示があると思うので、ポリシーをコピーを押す
3. 1で作成したS3バケットのコンソールを開き、アクセス許可タブを選択する
3. バケットポリシーの編集ボタンを押し、先ほどコピーしたポリシーをペーストする
3. 変更の保存を押す

# Route53でDNSを取得する
### ホストゾーンの作成
1. Route53を開き、ホストゾーンを作成する
1. ドメイン名には、完全修飾ドメイン名の*.以下を入力する(例. my-world.net)
1. 説明が必要であれば入力して、パブリックホストゾーンを選択し、ホストゾーンの作成を押す
### レコードの作成
1. 作成したホストゾーンを選択し、レコードを作成を押す
1. レコード名には、ドメイン名以上の部分を入力する(例. my-page)
1. レコードタイプはAを選択
1. エイリアスのドグルをONにする
1. トラフィックのルーティング先でエンドポイントを選択プルダウンで「CloudFrontディストリビューションへのエイリアス」を選択
1. ディストリビューションを選択で、先ほど作成したCloudFrontディストリビューションを選択する(それしか出てこないはず)
1. そのままレコードを作成

# S3にソースをアップロードしてチェック
1. S3に表示させたいページのソースコードをアップロードする
この時注意したいのが、CloudFrontの設定でデフォルトルートオブジェクトに設定したオブジェクトは必ず必要な点と、そのオブジェクトはバケットのルートに配置する必要があること
2. CloudFrontでディストリビューションを選択して、キャッシュ削除タブを開く
2. キャッシュ削除をクリックして、オブジェクトパスに```/*```と入力してキャッシュ削除を作成する(こうしないと、アップロードした内容が反映されない)
2. CloudFrontで指定した代替ドメインを叩く
2. この時、ベーシック認証をかけていた場合はIDとパスワードの入力が求められる
2. 無事、アップロードしたページが表示されていればOK！

もし、S3のオブジェクトを更新した場合は、再度キャッシュ削除をすれば最新のアップロードしたファイルが表示されるようになる
また、ブラウザーのキャッシュによって最新の表示がされない場合もあるので、その場合はゲストモードで開くか、ページのキャッシュを削除する

参考にしたページ
ClassMethod  [CloudFront FunctionsでBasic認証のパスワードをかける](https://dev.classmethod.jp/articles/apply-basic-authentication-password-with-cloudfront-functions/)