こんばんは、しーまんです。
今回はAWSでSPAのWebサイトを構築する際にハマった点を解説していきたいと思います。
サーバを立てずにサッと簡単なWebサイトを構築する際はよく用いる方法ですので、参考にしていただければと思います。
AWSで簡単なSPAサイトの構築
まずSPAはご存知でしょうか。
SPAとは Single Page Application の略で文字通り単一のページで構成されるWebアプリケーションです。
通常だとページの遷移のたびに新しいページを構成する要素をサーバからダウンロードして表示しますが、SPAの場合1つのページをあたかも遷移したページのように見せかけページを構成する要素だけを入れ替えて表示します。
こうすることによってページの切り替えが早く、ユーザビリティが向上します。
こちらのSPAをAWSで構築する場合、よくS3+CloudFontの構成で実現したりします。
この構成にする理由は簡単で、S3を使用することで自身で専用のサーバを用意する必要がなくなります。またCloudFrontを使用することでグローバルにCacheを持つことができ、軽快にアクセスを捌くことが可能だからです。
間にWAFがありますが、これはCloudFrontへのアクセスに対して何かしらの制限をかけたい場合に使用します。よくあるのが開発中の環境に対して、特定のIPアドレスからのみにアクセスを制限するなどの要件です。
CloudFrontでErrorPages設定
SPAリロードのエラー
通常のWebサーバだと上記のような設計で問題ないのですが、SPAの場合は先程も少し触れましたが、ページ遷移する際は仮想的なページ遷移であって実際にそのURLのhtmlが存在するわけではありません。
つまりWebブラウザでリロードを走らせた場合、デフォルトのルーティング設定だと403エラーが返ってきてしまいます。
こんな感じのエラーをみたことありませんか。よくあるエラーですよね。
これはSPAサイトでは例えば example.com/login
というページに遷移した際に /login
という部分は実際には存在していないページで、仮想的にuriを作成しているために起こる現象です。
SPAリロードエラー対応
これを解決する方法はCloudFrontでErrorPagesを設定する方法がよく取り上げられています。
まずCloudFrontのページから対象のディストリビューションを選択しエラーページタブを選択します。
そのページから「カスタムエラーレスポンスを作成」を選択します。
そしてレスポンスコード403, 404に対して200に変更しつつ「/index.html」を返すように設定します。
最終的に下記の画像のような設定ができていればOKです。
これでリロードした際はシングルページのindex.htmlにアクセスすることができ、エラーが表示されてしまう問題は解決できます。
WAFのIP制限時の403をどう扱うか
403でハマったポイント
多くのサイトだと上記の設定で説明が終わっているものがほとんどです。
しかし今回は上記環境でWAFによるIP制限をかけた際に問題が発生しました。
上記設定は403, 404のレスポンスを200にしてレスポンスページを変更する対応でした。
しかしこれによってWAFによるIP制限のデフォルトレスポンスである403も200に変更され、/index.htmlにアクセスできてしまう事象が起きました。
つまりIP制限したはずなのでindex.htmlだけは表示されてしまうという問題が発生したのです。
これではIP制限の意味が無いのでどうにかできないか思考錯誤しました。
最初は「Lamda@Edge」や「CloudFront Functions」を使用してリクエストuriを書き換えるなどを試みてみたのですが、結局うまくいかず。
半日ほどいろいろ書き換えを考えていたのですが、そもそも「IP制限の403」と「ファイルが無かった際に返される403」の見分けがつかないとこが原因だよなと思い、じゃあWAFによるIP制限のレスポンスを変えちゃえばいいじゃんという結論にたどり着きました。
WAFによるIP制限のレスポンスをカスタマイズ
ということでWAFによるIP制限時のレスポンスを403ではなく401に変更します。
そうすれば200が返ることなくちゃんとIP制限をエラーとして返すことが可能になります。
まずはエラー時にクライアントに返却するカスタムレスポンスボディを作成します。
WAFのページから対象のWebACLを選択し、「Custom respons bodies」タブを開き「Create custom response body」を選択します。
レスポンスボディを設定し、名前をつけて保存します。
次に「Rules」タブを開き「Default web ACL action for requests that don’t match any rules」を設定していきます。これは指定したIPをAllowにしてそれ以外のアクセスをBlockする時の設定です。いわゆるホワイトリスト方式の場合ですね。
ページ右下にある「Edit」を選択しましょう。
そしてResponse codeを401に設定し、先程上記で設定したレスポンスボディを設定します。
ここでResponse codeを401に設定することが今回の一番の目的です。この設定をすることで、CloudFront側のエラーページ対応からIP制限の処理を除くことができます。
保存が正常に完了すると下記のように表示されます。
実際に許可していないIPでブラウザからアクセスした場合は下記のような表示がされることが確認できます。
まとめ
今回はS3+CloudFrontでSPAのWebサイトを構築する方法と、リロードエラーの対応を解説しました。そのあとWAFによるIP制限の問題についても対応方法を解説しています。
最初はなかなか良い方法が思いつかなく、見当違いな方法を検証していましたが、WAFのカスタムレスポンスを設定するというシンプルな方法で問題解決することができ、スッキリしました。
AWSの記事は気づくと初めてだったですね。普段から触っている分当たり前の領域になってきてしまっていてあまり記事出せていなかったですが、今後はCloudに関しての記事もどんどん出していこうと思います。
以上、どなたかの参考になれば幸いです。
コメント