3ステップでお手軽！WAFでIP制限をかけCloudFront経由でS3から画像を取得する

# 概要
おはこんばんにちは@kaoryuuuです。

この記事[LIFULLその2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/lifull2)の12日目の記事です。
今回は３ステップで簡単に特定のIPのみからCloudFrontを経由してS3にある画像へアクセスする方法を試してみたいと思います。

## やること

目的：特定のIPのみからCloudFrontを経由してS3にある画像へアクセス

大きく分けて３つの作業になります
1. S3バケットの作成
2. CloudFrontの設定
3. WAFの設定

## S3バケット作成
ここに配信を行うコンテンツを格納します。

### 1.作成
バケット名はユニーク名なので適当にとは言えませんがわかりやすいものを。
<img width="1106" alt="スクリーンショット 2018-12-12 16.33.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/6c74e635-423c-a2ee-7171-b0724019f4a9.png">

### 2.オプションの設定
必要であればログの設定も行ってください。
ここでは特に入力せずに進みます。
<img width="1107" alt="スクリーンショット 2018-12-12 16.35.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/d7809302-d2f9-c9be-4090-ff4fdb617c36.png">

### 3.アクセス許可の設定
こちらも特にデフォルトのまま進みます。
<img width="1107" alt="スクリーンショット 2018-12-12 16.35.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/d8617faf-08c9-8135-bcc4-92b802e7e0af.png">

### 4.確認&完成
確認ができたらバケットの作成は完了です。
後ほど確認用で適当な画像を使用しますのでアップロードしておいても問題ないです。
続いてCloudFrontの設定を行います。
<img width="1104" alt="スクリーンショット 2018-12-12 16.36.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/6a06d71c-a420-aac0-65ff-9c2b53e00967.png">

## CloudFront
概要

> Amazon CloudFront は、データ、動画、アプリケーション、および API をすべて開発者にとって使いやすい環境で、低レイテンシーの高速転送により視聴者に安全に配信する高速コンテンツ配信ネットワーク (CDN) サービスです。

要は自前のサーバーやS3から直接取得しにいかずに、その手前にCloudFrontを置くことでキャッシュサーバーやプロキシサーバーの役割を担ってくれているものです。便利ですね😃

### GetStart
Create Distributionを選択し、Webの「Get Staeted」を選択
<img width="1399" alt="スクリーンショット 2018-12-12 16.37.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/83fddfd6-fd8f-346f-2bbe-afa54c264a2f.png">

### OriginSettings
先ほど作成したバケッド名が出てくるので選択
<img width="1418" alt="foo.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/f0682dae-1eea-0ae2-8162-538d09f2be8d.png">

Restric Bucket Accessを「YES」に変更
こちらを設定することによりバケットにあるコンテンツへのアクセスをCloudFrontからのみに制限することができます。
<img width="1404" alt="hoge.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/54b7f2e7-5267-3559-4421-b2d87ca6ecf5.png">

あとは今回は特に設定を変更せずにCreateDistributionを行います。
※ドメインを指定する場合はRoute53の設定を行う必要があります。

Distibutionsが作成できると、起動を開始しますが数分かかるのでEnableになるまで待ちましょう。

## WAFの導入
現在の状況ではS3から直接アクセスすることはできないですが、CloudFront経由でのリンクを知っていると外部から参照することができてしまいます。それを防ぐためにWAFを利用して制限をかけていきます。

IP制限だけでなく他にも用途は多様ですが今回は割愛します。
https://aws.amazon.com/jp/waf/

### Create conditions
WAFのページから「Create web ACL」を選択

「IP match conditions」を今回は利用します。
<img width="1365" alt="fuga.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/f4e99c47-2a29-cb29-4772-e920a2dabc30.png">

作成するルール名と許可したいIPをこちらに設定します。
完了したら「Create」👈
<img width="866" alt="foo.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/055ebbcf-644b-49fc-9d59-59f213f06a74.png">

作成ができたらこの画面は完了です。次のページへ進みます。

### Create Rule
「Create Rule」を選択し、先ほど作成した条件を設定します。
完了したら「Create」👈
<img width="868" alt="hoge.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/fc64be60-3a2d-33df-31be-2ec2011be609.png">

設定した条件にマッチングした場合にどうするかを設定します。
今回は「Allow」を選択します。

Default actionは「Block all requests…」を選択します。
※条件にマッチしなかった場合の挙動ですね。

<img width="1212" alt="aaa.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/f9f7ce6e-763f-cdc2-62f8-dcd8740455e8.png">

### Review and create
設定が確認、完了できたらWAFの設定は終わりです。


## CloudFrontにWAFの設定を反映させる

CloudFrontに移動し、アクセス制限をかけたいCloudFront Distributionを選択、
General の「Edit」を押す👈

「AWS WAF Web ACL」の項目を選択し、先ほど作成したWAFのACLを選択します。
<img width="1134" alt="fuga.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/41ae8112-62b9-7671-d128-670719351df6.png">

これにて諸々の設定は完了になります。


## 確認作業
CloudFrontのドメイン名をメモし、S3へアップロードした画像名を組み合わせて正しく表示できるか確認し、
また特定のIPのみ表示できるかチェックします。
<img width="965" alt="sasasa.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/ac2f28df-4ff2-e469-f129-1ea868c04a94.png">

エラーの場合は403 ERRORが表示されるはずです。
<ドメイン名>/<S3の画像名>
<img width="468" alt="スクリーンショット 2018-12-12 17.54.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/d09adf4b-f132-086e-d185-2869deb17073.png">

# 参考
https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/how-aws-waf-works.html
https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/what-is-aws-waf.html
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/distribution-web-awswaf.html

# 余談
WAF入れてるからリクエストの監視などもできますね👏
<img width="736" alt="スクリーンショット 2018-12-12 18.37.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/186277/9c3acae5-3d43-1b44-07d8-85a5dc4174c7.png">


# 最後に
間違い等ありましたらコメントよろしくお願いします。