CloudFrontマルチオリジン [APIGateway / S3]

# 概要

:::note

* サーバレスアーキテクチャのフロントエンドを構築
* CloudFrontを前段に置いてマルチオリジンを構成する
* オリジンはAPIGateWayとS3で構成し、URIによってどちらかのオリジンにアクセス
* APIGatewayの後ろはLambdaだがここでは書かない
* 最後にWAFでIPアドレスによるアクセス制限

:::

# 前提

* ドメインと証明書は取得済み
* ここではdev-＜projectname＞.comを取得ドメイン名とする

# 詳細

* こんな感じの完成イメージ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/7f2e5695-3cc3-5ae6-a760-bb3879af030b.png" width=70%>

## Distribution作成

* オリジンドメインは作成したS3のアドレスを入力
* オリジンパスはここでは無し
* OAIを任意の名前で作成
* バケットポリシーはここではひとまず自動

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/8c31c542-8dbf-0374-81fb-20b0125670a6.png" width=50%>

* ビュワーはHTTPSオンリーでも良いかも。APIGatewayはHTTPSのみしか対応してないはず

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/bee70406-24d4-6960-e182-f1f2a1a4674e.png" width=50%>

* キャッシュポリシーとオリジンリクエストポリシーは後で変更予定。ここではとりあえずデフォルト

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/966301b8-2b97-669b-8232-8a948b995510.png" width=50%>

* デフォルト

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/44f7d0f7-750c-5bde-093e-0ef442c51ca4.png" width=50%>

* デフォルトルートオブジェクトに"index.html"

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/b5759c11-ee71-cd91-a7be-9f4265d479fe.png" width=50%>

* 以上でとりあえずDistribution作成

## S3バケット作成

* パブリック・アクセスのバケットを作成
* 詳細手順は割愛

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/52ce4666-cfbd-5907-6116-cc6e5aa76975.png" width=50%>

* Identityがない方のバケットポリシーを削除

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/e7c2e921-31fc-f36e-d404-e5cc184ae7e8.png" width=50%>

## ACM証明書作成

* 詳細手順は省略
* 申請した手続きをRoute５３にレコード作成して認証にする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/5f8842c5-b90d-eea0-c6e9-d3e8e1907017.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/f5dd2d32-932a-3721-bc52-3b671cebb387.png" width=50%>

## Distributionに証明書をセット

* CNAMEにドメインをセット
* 証明書をセット

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/2fe1e843-0831-811a-88a9-e74fcb230c23.png" width=50%>

## Route53レコード登録

* Route53にAレコードを作成。Distributionのドメインを入力

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/3d07bb2b-e45a-fc32-e5ee-063dfd95436e.png" width=50%>


## APIGateaway

* RestAPIを任意の名前で作成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/5c22dda9-3ecc-bf21-910a-7bc74349fc58.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/20ae2067-37c4-3dd3-521a-2b091745a286.png" width=50%>

### リソースの作成

* リソース”/api”と”/admin”を作成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/40975ac4-3919-f35d-1562-30f45b4f9a5c.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/e4a905e0-5377-d537-5b14-e67dfc7bdd33.png" width=50%>

* apiの下にadminを作成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/e98ce9c1-b74f-003f-845a-09335e2c1e1b.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/859e388d-411e-c5a8-1c24-51ac1449e283.png" width=50%>

* リソースの作成後、レスポンスさせたいリソースを選択、[アクション]から[メソッドの作成]を選択。
* [メソッドの作成]後、HTTPメソッドが選択可能、今回は"GET"を選択し、確定。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/e6115db4-42ab-5711-8a24-6905553c128c.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/7c8b6721-2781-a75b-096c-7054c23de9e8.png" width=50%>

* シンプルに使いたい場合は、統合レスポンスのマッピングテーブルを作成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/2ec04605-ab0f-efdc-dbca-7c876aacd843.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/324c638f-7b46-b283-8cf2-01c22d622cc1.png" width=50%>

* デフォルトの統合レスポンスを順番に展開し、マッピングテンプレートのContent-Type：application/jsonにレスポンスしたい内容を入力。入力完了後、[保存]。

### API動作確認（テスト）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/5fb492c7-b782-c136-d6b4-282e5edb9afd.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/7c936f29-d64d-4f13-99b5-1b6b226f7566.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/f99f1e42-6c83-609a-b69a-3a5e8a653bac.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/4d8701b7-cb12-94bb-4e74-c3c309b63b08.png" width=50%>


### APIデプロイ

* テストで動作に問題がないことを確認したあとは、実際にデプロイ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/aa0f0965-f826-4057-990c-6bdc4ad4fa13.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/9f93ee46-f74e-a929-0174-d2965f599dcb.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/5dc9de55-23d7-d4ba-7597-15db52b5e5a8.png" width=50%>

* 生成されたURLでアクセス。APIGatewayで任意のステージ名を作成した場合、最初のパスになる
* APIGateway単体でのアクセス成功を確認

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/449be42e-a506-25a6-aea0-b77547f877ce.png" width=50%>

※末尾のパスが設定できていない場合、下図のようにMissing Authentication Tokenエラーが返ってくる
※APIGatewayでStage名が”dev”だった場合、CloudFrontのオリジンパスは"/dev"に設定する
※ステージ名（ステージ変数）が$defaultだった場合オリジンパスの入力は不要

### CloudFront経由でAPIアクセス

* Distirbutionではオリジンパスを設定
* APIGatewayのステージ変数が＄defaultの場合は不要

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/278d0cf9-255d-3981-5544-e070a061b0ee.png" width=50%>

* Behavor

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/6f061539-c634-f872-0aea-4e7d784f4627.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/2c884cad-1f04-0a69-9a33-34c5e2ca0798.png" width=50%>

* ここでは詳細は書かないがキャッシュポリシーは”CachingDisabled”、オリジンリクエストポリシーは任意で作成したポリシーを設定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/ef7315d5-7c01-2976-b82e-f0b1e4433f0d.png" width=50%>

* S3のBehavorは以下の通り

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/935619cb-555c-2525-ac1f-df5dcabdbbf9.png" width=50%>

* APIGatewayのパスにアクセス

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/51649ad4-c00d-28a2-db74-2a132927a9ed.png" width=50%>

* S3のパスにアクセス

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/7ccde23c-9419-bb5b-dae9-4f03b8ccbc02.png" width=50%>

## WAFによるIPアクセス制限

* 接続可能なIPをまとめたIPSetを作成する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/be5054b1-a681-1484-206b-36dcddf34ad4.png" width=50%>

* 対象のCloudFrontディストリビューションを使用してACLを作成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/ccdc9dbc-1169-4921-df9a-5862055ae8cb.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/17adeccc-15da-d157-1ffb-6849d5d1e549.png" width=50%>

* 作成したルールを選択し、対象IP以外はBlock

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/85e02617-99ff-b896-669f-550c4c1ca05f.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/b687fa70-00ae-f15d-1ec2-96e5f92b775b.png" width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/0c320e0c-281c-4fa1-9f13-f0720a7b663d.png" width=50%>