Well Architected Frameworkを意識して自分なりにアーキテクチャ設計・構築をしてみた。＜WAF、Cloudfront編＞

#はじめに
この記事は、実務未経験者がロールプレイング形式でアーキテクチャの設計、構築を行うといった記事です。
よろしければ[＜準備編＞](https://qiita.com/mkoki0422/items/9fc0b5d44ff7367994f1
)[＜アーキテクチャ設計編＞](https://qiita.com/mkoki0422/items/33b60250527dbc92b518)[＜VPC、ELB編＞](https://qiita.com/drafts/425cca72ab1efc5e77c2/edit)もご覧くださいませ。




#Cloudfront編



##ディストリビューションの作成

Cloudfrontを使用してエッジロケーションからサービスを配信します。
エッジロケーションにキャッシングを行う事でコンテンツを、ユーザーに最も近いサーバーから配信できますので、**ネットワークレイテンシの低減**や**オリジンサーバーの負荷軽減**を行う事ができます。

ELBなど動的コンテンツオリジンにする場合はどれをキャッシュして、どれをキャッシュさせないのかを検討する必要があります。
今回はとりあえずキャッシングを行わない方針でCloudfrontを導入していきます。

ちなみにキャッシュしない CloudFront は CDN 本来の「エッジサーバにコンテンツをキャッシュし高速に配信する」というメリットはありませんが、それでも導入するメリットは結構あります。

+ HTTP/2 や IPv6、gzip 圧縮といった技術要素を手軽に導入できる
+ DDoS 対策に一定の効果がある
+ パス毎にオリジンを変える事ができる
+ Amazon WAFを手軽に使える
+ 単一リージョンで世界中にサービス展開しているような構成だとレイテンシ改善が期待できる
    + CloudFront のエッジは世界中に 50 以上あり、最も近いエッジサーバに誘導されるから
    + CloudFront のエッジサーバからオリジンサーバへのリクエストは AWS の太いバックボーンを通るから

などなど
実際にCloudfrontでキャッシングさせない方針で導入しているサービスも結構見られます。（Amazon WAFを利用したいからという理由で導入するケースも結構多い気がします）


では実際にCloudfrontの設定を行なっていきましょう！

マネジメントコンールの「Cloudfront」→「Create Distribution」に進んでください。
![スクリーンショット 2020-09-25 23.35.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/1d7cab01-8798-3286-fb70-f2c11a86899e.png)

Webの方の「Get Started」をクリック
Cloudfrontは未だに日本後対応してないんですよねー　
結構設定項目が多いので、早く対応して欲しいです

###Origin Settings

「Origin Domain Name」は前回作成したALBを指定してください。

「Origin Path」はコンテンツをおいているパスを指定してください。
ApacheのDocumentRootを変更しているので一旦デフォルトのままでいきます

「Origin Protocol Policy」は

+ HTTP Only
    + HTTPのみ許可
+ HTTPS Only
    + HTTPSのみ許可
+ Match Viewer
    + どっちも許可

から選べます。　後ほど変更もできますので、とりあえずMatch Viewerを選んでおきます。



+ Origin Connection Attempts
    + オリジンへの接続を試行する回数
+ Origin Connection Timeout
    + オリジンへの接続を確立しようとするときにCloudFrontが待機する時間
+ Origin Response Timeout
    + CloudFrontがカスタムオリジンからの応答を待機する時間
+ Origin Keep-alive Timeout
    + CloudFrontが接続を閉じる前にカスタムオリジンサーバーとのアイドル接続を維持する時間

の設定項目もとりあえずデフォルトでいいかと思います。
処理に時間かかったり、読み込みが遅いコンテンツの場合はここを変更するといいでしょう


+ Origin Custom Headers
Cloudfrontを通過するときに好きなヘッダー、値を追加する事ができます。
アクセス制限をしたりする場合によく使いますね。
後ほど設定しますので一旦スルー



![スクリーンショット 2020-09-25 23.59.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/bc49eb6e-68b5-a206-9743-77372ec49b03.png)

###Default Cache Behavior Settings
こちらの項目は別途変更を行うので、一旦スルーします



###Distribution Settings
「Price Class」
はどこの地域のエッジロケーションを利用するか指定する事が出来ます。
コストを抑えたいときはここを設定してください。

「AWS WAF Web ACL」
後ほどWeb ACLを作成しますので一旦スルー



「Alternate Domain Names」
「SSL Certificate」
ドメインを指定出来ます。後ほど設定しますので一旦スルー

ちなみに設定を行わない場合はデフォルトのドメイン名になります。（デフォルトのドメイン名でもHTTPS化出来ます）
djfaeihfa3eji22.cloudfront.net
みたいな感じですね


残りの項目はCloudfrontのログの設定です。
こちらも後ほど設定していきますので一旦スルーで大丈夫です。

![スクリーンショット 2020-09-25 23.59.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/ed7a5577-8d49-dd24-9bba-ec68666d27a2.png)



Cloudfrontは世界に200以上のエッジロケーションがあるので、一回設定を変更すると結構時間かかります。

##Behaviorsの設定
Statusが「In Progress」の状態でも変更を行えますので、先ほど作成したディストリビューションを指定してオリジンの詳細設定を行いましょう。

「Behaviors」のタブを選択してください。
現時点では全てのパスが先ほど作成したオリジンにアクセスするように設定されてます。

リストを追加する事ができ、複数ある場合は上から順に適用されます。
Default (*)はどのパスでも当てはまらない場合にアクセスするといったものです。
![スクリーンショット 2020-09-26 0.05.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/eb6da8af-0f21-4882-91ef-3f3dff770415.png)


ELBなどで動的コンテンツをオリジンとして指定する場合は
→Default (*)はキャッシュさせて、その他のリストはキャッシュさせる
→Default (*)はキャッシュさせず、その他のリストはキャッシュさせる

の2種類の方法を取る事ができます。

####キャッシュさせない場合

まずはキャッシュさせない場合はこちらの設定で大丈夫です。

Minimum TTL、Maximum TTL、Default TTLは「Cache Based on Selected Request Headers」をALLに設定すると自動的に0になります。

|項目  |設定値  |
|---|---|
|Allowed HTTP Methods  |GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE  |
|Cache Based on Selected Request Headers  |ALL  |
|Minimum TTL  |0  |
|Maximum TTL |0  |
|Default TTL |0  |
|Forward Cookies  |ALL  |
|Query String Forwarding and Caching|Forward all,cache based on all |

その他はデフォルトで大丈夫です。

![スクリーンショット 2020-09-26 0.35.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/6079521d-5b10-a9de-0a0a-251c45dc202e.png)



####キャッシュさせる場合



|項目  |設定値  |
|---|---|
|Allowed HTTP Methods  |GET, HEAD  |
|Cache Based on Selected Request Headers  |WhiteListにて必要なHeaderを追加（ALLにするとTTLが0に設定されます）  |
|Minimum TTL  |0  |
|Maximum TTL |お好みのTTL  |
|Default TTL |お好みのTTL  |
|Forward Cookies  |None or whitelist      (ALLにするとキャッシュされないので注意)  |
|Query String Forwarding and Caching|Forward all,cache based on all |

「Cache Based on Selected Request Headers」
でよく追加するヘッダーについて紹介します。

Authorization
管理画面にベーシック認証を入れる時などに必要です。

CloudFront-Forwarded-Proto
Origin側へプロトコルを通知します。

Host
Origin側へアクセス先ホスト名を通知します。

コンテンツによって使用したいヘッダーを追加して下さい。


![スクリーンショット 2020-09-26 2.32.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/d0709f19-e1f3-db1d-9fdf-3f33682ceb37.png)



キャッシュさせる場合においても
ログイン系、管理ページ系などはキャッシュしないように設定する必要があります。



![スクリーンショット 2020-09-26 2.26.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/82ac0b37-15a3-ecf9-782e-90d02dffe63d.png)





##特定地域からのアクセスをブロックする
今回は日本以外からのアクセスをブロックしてみます

「ディストリビュション」→「Restrictions」→「Edit」を洗濯してください
![スクリーンショット 2020-09-26 2.50.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/7d097016-c281-5d1e-6e32-6ffb375b8744.png)



ホワイトリスト、ブラックリスト形式を選択できます。
今回は日本のみを許可したいので、「ホワイトリスト」、「JP--JAPAN」で設定しました。
![スクリーンショット 2020-09-26 2.51.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/8d329578-13e9-f8fd-0ffa-3d1ee0222e85.png)




##カスタムエラーレスポンスとしてSorry Pageを実装
エラーページを表示させましょう。

準備として、適当なS3バケットを作成、エラーページで使用したいファイルをアップロードしてください。

![スクリーンショット 2020-09-26 3.02.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/27549173-2018-f245-8483-add5c56bacd5.png)


S3をCloudfrontで配信する場合、S3の静的ウェブホスティング、通常バケット、CustomOrigin（Cloudfrontで最初に設定するオリジン）の3種類があります。

+ 通常バケット
    + CloudFront⇔Origin間のHTTPSを自動で設定してくれる
+ S3の静的ウェブホスティング
    + HTTPS化出来ない
+ CustomOrigin
    + HTTPS化する際に自分でSSL証明書を用意する必要がある

などの違いがありますので、今回は通常バケットで用意します。

まずはS3のオリジン登録を行う為に
「Origins and Origin Groups」→「Create Origin」を選択して下さい。

![スクリーンショット 2020-09-26 3.21.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/53dad156-31f5-18ea-e51d-32f6b4e53890.png)

先ほどと同じようにS3のドメイン選択、パスの指定を行なって下さい。
また、S3への直接アクセスを制限する為に、OAIを設定しましょう。

「Restrict Bucket Access」をYesに選択すると、OAIの設定項目が追加されます。
「Origin Access Identity」→Create a New Identity
「Grant Read Permissions on Bucket」→Yes, Update Bucket Policy

と設定すると、自動でOAIの作成、バケットポリシーにOAIのIDを追加してくれます。

![スクリーンショット 2020-09-26 3.21.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/5aa3cc8f-3323-2c7f-6d03-d6c028efd57a.png)



![スクリーンショット 2020-09-26 3.27.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/6efc2a01-7425-1c36-803d-b1d3c74db213.png)



後は「Behaviors」の設定を行なって、先ほど作成したオリジンを追加して下さい。
キャッシュに関してはエラーページで設定出来ますので、こちらではキャッシュしない設定で大丈夫です。
![スクリーンショット 2020-09-26 3.31.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/7f71808e-27e8-b960-cb61-8aea0b673235.png)

エラーページを追加する為に「Error Pages」→「Create Custom Error Response」にて設定を行います。

注意点として、長い時間のTTLを設定すると、エラーページから戻らなくなります。
![スクリーンショット 2020-09-26 3.33.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/a6632fa7-f880-5970-eb52-c95642857490.png)

補足として、「Behaviors」でキャッシュを行う設定を行なった場合、2XX・3XXに対しては設定したTTLが反映されるのですが、
4XX・5XXに対してはデフォルトで1分間のTTLが設定されています。
もし、エラーに対するTTLの変更を行いたい場合は「Error Pages」より、各エラーに対してのTTLを設定して下さい。






##CloudFrontのアクセスログをS3に収集
前回作成したログ専用のバケットを選択して下さい。

プレフィックスを設定できますので今回は「Cloudfront/」を入力します。
![スクリーンショット 2020-09-26 20.05.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/a1f72678-91b1-ed60-12b7-5b9ee2bafaf8.png)

ログを確認してみましょう。
プレフィックスの設定通り、minamialb/Cloudfrontにログが収集されてます。
![スクリーンショット 2020-09-26 20.34.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/d2e6ecd8-a20f-0117-ec85-6e4b6de518e9.png)







#WAF

##CloudFrontからのアクセスのみを許可（オリジンへの直接アクセスを禁止)
現時点では、Cloudfrontからだけではなく、オリジンのALBに対しアクセスが可能となっています。
セキュリティ対策としてWAFをCloudfrontに適用し、アクセス制限を行う場合はALBへの直接アクセスを禁止しましょう。

方法としてはALBを使う方法、WAFを使う方法が一般的ですが、今回はWAFを使ってみます。
現在WAFはWAF v2とWAF Classicがありますが、せっかくなので新しいWAF v2を選択しました。

マネジメントコンソールの「AWS WAF」→「Web ACLs」→「Create web ACL」から作成していきます。
![スクリーンショット 2020-09-26 3.48.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/ffc57062-04af-d598-cb4e-cb7ba1249ef0.png)

「Regional resources」を選択して、ALBが設置されているリージョンを選択します。
その後「Add AWS resources」からWAFを適用したいALBを選択して下さい。
![スクリーンショット 2020-09-26 4.43.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/eec601e9-d1b5-f552-870a-46acd6210f08.png)

WAF v2では様々なマネージドルールを使用できますが、今回は「Add rules」→「Add　my own rules and rule groups」からカスタムルールを作成します。




![スクリーンショット 2020-09-26 4.44.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/2e39a23a-4b44-62b8-e1c1-0acc517f3b85.png)

カスタムルールの設定を

|項目  |設定値  |
|---|---|
|Rule type |Rule builder |
|Type |Regular rule  |
|If a request  |matches the statement  |
|Inspect |Header  |
|Header field name |任意のヘッダー  |
|Match　type  |Exactly　matches　strings  |
|String　to match  |任意の文字列  |
|Text　transformation |None  |
|Action |Allow  |

の様にして下さい
「Header field name」
「String　to match」
に関しては、Cloudfrontの「カスタムオリジンヘッダー」の設定よりヘッダーを追加します。
セキュリティの為、なるべく予測されにくいヘッダーの作成を行って下さい


![スクリーンショット 2020-09-26 4.47.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/ce417188-b581-2ed8-6ef3-bb41a399101e.png)

最後に
「Default web ACL action for requests that don't match any rules」をBlockに
カスタムルールの「Action」をAllowにする事で、ルールに対応する場合のみアクセス許可をする事ができます。


![スクリーンショット 2020-09-26 4.47.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/40d81fb3-4fe9-faa3-f68f-ad74224f8dcc.png)



WAFの方では設定完了ですので、Cloudfrontの設定より、「カスタムオリジンヘッダー」を追加していきましょう。
「Origins」の設定画面から、ALBを選択します。

![スクリーンショット 2020-09-26 17.36.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/69222ac2-713c-dfe8-1995-37d3a7690387.png)


「Origin Custom Headers」より先ほど設定したヘッダーの名前、値を入力して下さい。

**注意** 今回はテストの為「test」という文字列にしていますが、実際に運用する場合はセキュリティの面から予想されにくいヘッダー名、値にして下さい。

![スクリーンショット 2020-09-26 17.36.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/38278924-4569-0e62-0b37-efd245a3686b.png)


実際にALBのDNS名からアクセスすると「403 forbidden」が表示されるかと思います。

![スクリーンショット 2020-09-26 23.56.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/11abc8c5-d1ed-f085-9d93-579a6bd37a61.png)




##Web ACLの設定


![スクリーンショット 2020-09-26 23.39.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/612c0658-b04d-fd97-6b63-ddce90117494.png)


![スクリーンショット 2020-09-26 23.40.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/b4b90fbd-e42b-e676-3461-9f1668692fcf.png)




![スクリーンショット 2020-09-26 23.41.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/50dfeef5-9fcb-9f58-aa60-8e1fe705b1a2.png)

![スクリーンショット 2020-09-26 23.41.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/aff6e0e2-f845-a1a6-d7d2-55c8b2d197ed.png)


![スクリーンショット 2020-09-26 23.42.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/bb927687-629a-a79b-42d7-d304825508fe.png)

#最後に


参考
「キャッシュさせないCloudFrontディストリビューションを設定してみた（CloudFormationテンプレート付）」
https://dev.classmethod.jp/articles/create-no-cached-cloudfront-distribution/

「Amazon Athena で CloudFront のアクセスログを集計する」
https://dev.classmethod.jp/articles/athena-cloudfront-log-activity/

「Athena で CloudFront ログ解析」
https://qiita.com/ytanaka3/items/ad5e7d96bc425ff4c843

「キャッシュしない CloudFront とそのメリット・デメリット」
https://blog.manabusakai.com/2016/11/no-cache-cloudfront/

「AWS Cloudfrontの地域制限機能を使って特定地域からのアクセスを遮断する」
https://beyondjapan.com/blog/2016/09/aws-cloudfront-specificarea-blocking/

「CloudFrontを利用してオリジンサーバー障害時にS3上のコンテンツを表示する」
https://dev.classmethod.jp/articles/cloudfront-sorry-s3/

「CloudFrontのCustom Error Responseを利用して、S3上にあるSorryページを表示する」
https://dev.classmethod.jp/articles/cloudfront_customerrorresponse_s3/

「CloudFront および Lambda@Edge のメトリクスの表示」
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html

「AWS WAFを利用してCloudFrontのELBオリジンへ直接アクセスを制限してみた」
https://dev.classmethod.jp/articles/restrict-elb-origin-awswaf/

「いますぐ使う CloudFront」
https://qiita.com/sasasin/items/0f0ec1a90af6295589f9

「AWS CloudFrontで極力キャッシュさせたくない時の話」
https://qiita.com/shogomuranushi/items/a2367350ea54a8f41257![スクリーンショット 2020-09-26 2.50.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666664/6e7e3508-599c-1e38-0172-7b0de1e99c68.png)