AmplifyでWAFも使いたい


# 概要

Githubと連携させたAmplifyを使用したいが、**WAFによるアクセス制限**もしたい。
しかし、WAFがAmplifyをサポートしておらず苦戦したので、メモしておきます。

※2025/04追記
注記：現在は公式サポートされているので本記事の対応は不要です。
https://aws.amazon.com/jp/blogs/news/firewall-support-for-aws-amplify-hosted-sites/
ただし本記事を通して、Amplifyでホストされているアーキテクチャの仕組みを一定知ることは可能です。

# TL;DR

Amplify Consoleで構築したものに対してWAF適用しました。

構築内容
- CloudFrontを前段に配置してWAFを適用する

- OriginにAmplifyのEndpointを設定する

- Amplify側への直アクセスも制御

- ループ防止の設定をする


# Amplifyに関して

### Amplifyのメリット

SPA、静的コンテンツなどを新規サービスとして配信時、スピード感を持って構築できます。

- 例えば、S3に配置したい静的ファイルをGithubのコミットから直接更新出来る

- 複数の開発環境をブランチベースで用意することが出来て管理しやすい

- 認証機能がコンソールで実装できる

- Amplify側のエラー処理やルーティング設定などをコンソールから開発者ができる

などのメリットがあります。


### Amplify自体の構築パターン

Amplifyには構築方法が何パターンかあります。


- Amplify Console

**マネジメントコンソールからの構築**です。今回はこちらを使用しました。
理由は、開発者が最も容易に設定をいじれるという点に尽きます。
また、GitHubリポジトリとの連携やリダイレクト機能なども利用できます。
Basic 認証を付与することも**コンソールからできるので非常に便利**だと思います。
作成すると、デプロイされたAmplify環境のURLが発行されます。

尚、この構築方法ではAmplifyのインフラ部分が自動構築になるため
**CloudFrontやS3がAWSコンソール上から見えない**のですが、内部はCloudFront+S3などで出来ます。

WAFが使えないのであれば自分で前段においてしまおうというパターンをこの記事では記載します。


- Amplify CLI

```
npm install -g @aws-amplify/cli
```

でamplify cliから対話形式で構築内容を入力すると、CloudFormaitonが自動的に立ち上がり
CloudFrontやS3が構築されていきます。(amplify-***という名前のスタック)

この方法でCloudFront + S3を使用すると、GitHubリポジトリ連携が出来ません。
ただし、他のCICDツールを利用することでリポジトリのコードを更新した際に自動的にamplify publishコマンドが実行されるような仕組みを構築すれば、自動デプロイを実現することは可能みたいです。

構築例
amplify init 
※環境により[このあたり参考](https://docs.amplify.aws/guides/hosting/git-based-deployments/q/platform/js/#4-deploy-your-app-to-aws-amplify)
-> amplify add hosting (CloudFront + S3でHTTPSパターンを選択) 
-> amplify publish


### Amplifyを使用するかはケースバイケース

大前提の話ですが、CodePipelineなどのCDツールを使用してデプロイする方法もあります。
Amplifyには制約があるので、この辺は手法によりそれぞれのメリットがあるため開発者で決める必要があります。

今回はあくまで「Amplifyを選んだがアクセス制限を基本機能に加えて実現したい場合」の手法です。


# 要件例

こんな要件のときに、今回の記事に記載する構築手法を用いられます。

・Githubリポジトリと連携がされており、自動デプロイ出来る
・WAFでアクセス制御が出来る
・CloudFrontは運用時のカスタマイズ性を考慮し、CloudFrontはマネジメントコンソールで管理出来る
・Amplifyの基本機能を使用したい＝コンソールからリダイレクトや環境変数などの設定が出来る


# アーキテクチャー例

Amplify Consoleで構築して前段にCloudFrontとWAFをおいた場合の部分構成図です。

![Amplify_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406764/a2b9cd6d-af6b-c48b-39d5-219e5808e727.png)


# Amplify側のアクセス制限

厳密にいうと、このアーキテクチャは穴があります。
Amplifyのエンドポイントは**Public状態**であるため、もしEndpoint情報がさらされた場合は直接アクセスをされる可能性が大いにあります。せっかくの前段環境を通過される危険性があります。

CloudFront+S3をOAC/OAIなどで制限するような方法が、
CloudFront+Amplifyパターンにも無いのかという点ですが
代替案の一つとして、認証+ヘッダー制御の方法があります。

具体的には、**Basic認証**をAmplifyでかんたんに設定することができるため
あとは認証情報をCloudFrontのBehaviorで渡してあげます。

これでアクセスしたユーザはBasic認証情報を入力することなくサイト閲覧ができます。



# 設定方法

要点を重視した簡易手順です。

### Amplifyアプリ作成

AWSマネジメントコンソールの、Amplify Consoleから作成。
Githubリポジトリ連携もします。

まずは単体での動作確認をします。
「ウェブアプリケーションをホスト」
->「リポジトリブランチの追加」ブランチ選択
-> 環境変数があれば設定後、次へ
-> 保存してデプロイ

待機し、デプロイまで完了したら
全般 -> 本番稼働ブランチURL にアクセスして、まずは**単体で動作確認**


### 前段のCloudFrontとWAFを作成

前段に置くCloudFrontを構築します。
**管理化にできる**リソースなのでTerraformで構築してもOKです。

構築に際しては特記事項はありません。


### Amplifyを接続

CloudFrontディストリビューション構築後、**AmplifyをOriginに登録**します。

オリジン -> オリジンを作成 にて
「オリジンドメイン」項目にAmplifyの本番稼働ブランチURLを登録
Behavior設定でも*などでパス登録し、デプロイ後問題なくアクセスできることを確認します。

これでAmplifyアプリケーションの前段に、管理可能なCloudFrontとWAFを配置できました。
CloudFrontに対しては通常通りドメイン設定や別環境の連携も出来ます。


### Amplifyに直接アクセスさせないように制御する場合

先に、Amplifyで[Basic認証](https://docs.aws.amazon.com/ja_jp/amplify/latest/userguide/access-control.html)を設定します。

その後、**Amplify単体で認証要求されること、アクセスできることを確認**したら

先程のCloudFrontオリジン設定のカスタムヘッダー設定にて
先程の認証情報を[Base64形式エンコード](https://www.en-pc.jp/tech/base64.php#result)をした状態で付与します。
※ Authorization: Basic ${BASE64エンコード済のユーザ名:パスワード}

ディストリビューション側のデプロイタイムが終わったら再度アクセスして完了です。
これで**IP制限やWAFRuleの適用**ができるようになりました。

### ループ防止

内部的に**多段CloudFront**なので、以下の環境変数をAmplify側に入れて完了です。
[_DISABLE_L2_CACHE: true](https://github.com/aws-amplify/amplify-console/issues/8)