【AWS】Basic認証付き静的ページをS3でホスティングするまで(CodeBuildによるデプロイも含む)

# 概要
タイトルの通りです。
ソースコードはCodeCommitで管理をしている前提です。

# 大まかな流れ
* リポジトリ作成
* S3バケット作成
* CodeBuildでビルドプロジェクトを作成
* CodePipelineの作成
* Lambda関数の作成
* CloudFront Distributionの作成

あまり躓く箇所がない場合、注意点のみ記述し、詳細な手順は割愛させて頂きます。

# リポジトリ、S3バケットの作成
リポジトリの構成は以下の形として解説していきます。  

```
.
├── buildspec.yml
└── public  # このディレクトリ内をS3へ展開します。
    └── index.html
```

* 複数のAWSアカウントでCodeCommitを使用しており、コードをプッシュする際に「Please make sure you have the correct access rights and the repository exists.」と表示されてしまう場合。  
  * sshコンフィグファイルにそれぞれの接続情報を記載します。

```~/.ssh/config
Host git-codecommit.*.amazonaws.com  # AWSアカウント1
  User SSH キーID  # AWSアカウント1に登録されているもの
  IdentityFile ~/.ssh/認証鍵

Host git-codecommit.*.amazonaws.com  # AWSアカウント2
  User SSH キーID  # AWSアカウント2に登録されているもの
  IdentityFile ~/.ssh/認証鍵
```

* 
  * リモートリポジトリを登録する際に、SSHキーIDを含めたURLを登録します。

```
$ git remote add origin ssh://SSH キーID@git-codecommit.us-west-1.amazonaws.com/v1/repos/repo-name
```


* CloudFront経由で配信するため、S3バケットに対するパブリックアクセスは全てブロック、静的ウェブサイトホスティングは無効で問題ありません。  

# CodeBuildでビルドプロジェクトを作成
リポジトリのMasterブランチに変更が加わった際に、publicディレクトリ内のファイルをS3へ展開させるためのプロジェクトを作成します。
今回は複雑なことは特にしませんので、マネジメントコンソールからぽちぽち作成していきましょう。

```buildspec.yml
version: 0.2

phases:
  build:
    commands:
      - aws s3 sync public s3://bucket-name --delete
```

ビルドプロジェクトの作成が完了すると、新しいサービスロールが作成されるかと思います。
ビルド時にs3 syncを実行するため、サービスロールへS3へのアクセス権を付与してあげましょう。

# CodePipelineの作成
こちらもコンソールからぽちぽち作成していきます。
ソースステージではCodeCommitのリポジトリを、ビルドステージでは先ほど作成したビルドプロジェクトを指定します。デプロイステージはスキップします。

# Lambda関数の作成
CloudFrontアクセス時にBasic認証を行う関数を作成します。
__CloudFrontと関連付けるため、us-east-1(バージニア北部)リージョンで関数を作成して下さい。__

CloudFrontをトリガーとするため、関数作成時にポリシーテンプレートからロールを作成して下さい。
アタッチするポリシーは「基本的なLambda@Edgeのアクセス権限(CloudFrontトリガーの場合)」を選択します。
![create_lambda_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57448/aefd083c-0ace-a514-cac8-053a089d4c1c.jpeg)

### 関数コード

```index.js
'use strict';
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const authUser = 'username';  # 適宜書き換えて下さい。
    const authPass = 'password';  # 適宜書き換えて下さい。
    const authString = 'Basic ' + new Buffer(authUser + ':' + authPass).toString('base64');

    if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString) {
        const body = 'Unauthorized';
        const response = {
            status: '401',
            statusDescription: 'Unauthorized',
            body: body,
            headers: {
                'www-authenticate': [{key: 'WWW-Authenticate', value:'Basic'}]
            },
        };
        callback(null, response);
    }
    callback(null, request);
};

```

最後にアクションから新しいバージョンを発行します。

# CloudFront Distributionの作成
Web用のDistributionを作成していきます。
項目が多いため、変更を加える必要がある部分のみ解説していきます。

![create_distribution_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57448/469c1b62-d48d-3740-9165-8cd74a308b56.jpeg)

* Origin Domain Name
    * コードが展開されるS3バケットを指定して下さい。

* Restrict Bucket Access
    * CloudFrontを経由したアクセスにのみ、バケット内のオブジェクトへのアクセスを許可します。
    * 許可する識別子を作成し、対象となるバケットポリシーを更新します。

* Viewer Protocol Policy
    * HTTPでアクセスした場合、HTTPSへリダイレクトします。

* Lambda Function Associations
    * 先ほど作成したLambda関数のARNを指定します。

* Default Root Object
    * index.htmlを指定します。

以上となります。
この記事を作成するにあたり、参考とさせて頂きましたQiita内の記事を下記へ記載致します。

https://qiita.com/Junpei_Takagi/items/0ff85de3bf2de3aaf4eb
https://qiita.com/m4fg/items/80db7ce0050e5f3ab801
https://qiita.com/NaokiIshimura/items/46994e67b712831c3016

最後までお読み頂きありがとうございました。