LoginSignup
18
16

S3+CloudFrontで静的Webページをホスティングする際にハマったこと

Last updated at Posted at 2024-03-27

前提

現状

SPAのフロントページをホスティングしたS3「通称バケットA」にCloudFront経由でのみアクセスできるようにしている。

やりたいこと

特定パス /signage/{userName} にアクセスされた時のみ、別のS3「通称バケットB」にホスティングした静的Webページを表示したい。

その他

  • {userName}はユーザーによって可変
  • バケットA、バケットB共にパブリックブロックは全てOFF
  • S3の静的ウェブサイトホスティング機能はCloudFrontを通してアクセスするので無効状態

手順

◆ バケットB直下にindex.html等の成果物を格納
Image from Gyazo
◆ CloudFrontのオリジンにバケットBを追加
◆ CloudFrontのポリシーをバケットBのバケットポリシーに設定
Image from Gyazo
◆ CloudFrontのビヘイビアにて/signage/*へのアクセスはバケットBを向くように設定
Image from Gyazo

発生した問題1

ここまで行った手順で、/signage/mori-devへアクセスした時はバケットBの静的ページを表示してくれると思ったが、バケットAのページを表示してしまう。

原因

CloudFrontのビヘイビア設定/signage/*が効いていないのか大分疑ったが、原因は別にあった。
/signage/mori-devへアクセスするとバケットB自体にはアクセスしていたが、バケットB/signage/mori-dev/を探しに行ってしまう。
index.htmlはバケットB直下に置いており、バケットB/signage/mori-dev/は存在しないオブジェクトなので403エラーが発生していた。
CloudFrontのエラーページ設定で403エラーが発生した場合は200と見做してバケットAのindex.htmlを表示する、というカスタマイズをしていたので、バケットBにはアクセスできていないように見えてハマった。
Image from Gyazo

対応

試しにバケットBの階層化をキチンとしてバケットB/signage/mori-dev/index.htmlを生成したところ、/signage/mori-dev/index.htmlで表示することが可能になった。
Image from Gyazo

しかしmori-devの部分は可変であり、ユーザー分階層を用意するわけにはいかない。
S3のプレフィックスにはワイルドカードは使えない。
ということでCloudFront Functionを使用して対応することに。

CloudFront -> 関数 -> 新規作成

function handler(event) {
    var request = event.request;
    var uri = request.uri;
    if (uri.startsWith('/signage/')) {
        // signageパスへのアクセスは全てバケット直下のindex.htmlに
        request.uri = '/index.html';
    }
    return request;
}

作成した関数をディストリビューションに紐づける
Image from Gyazo

これによって/signage/mori-devのようなアクセスは全てバケットBのindex.htmlを見るようになりました。

起きた問題その2

/signage/mori-devへのアクセスでバケットBのindex.htmlを表示するようになったものの、index.htmlからバケットBの同階層にあるbundle.jsが読み込めずに403エラー。

原因

bundle.jsはビヘイビア設定の対象ではないので、バケットA/bundle.jsへアクセスしようとして403エラーが発生していた。
ビルドはWebpackで行っていたので、webpack.config.jsを設定して、ビルド成果物の接頭辞にsignage-resoure-をつけるようにした。
その上で、CloudFrontのビヘイビア設定を追加し、/signage-resoure-*へのアクセスはバケットBを向くように追加
Image from Gyazo

これにて、無事/signage/{userName}へのアクセスでバケットBの静的Webページを正しく表示できるようになりました。
Image from Gyazo

まとめ

S3へのWebホスティングはバケット内での構造化をちゃんとしていないと、存在しないオブジェクトへのアクセスになり403エラーが発生する。
上記が発生した場合に、CloudFrontで403エラーのカスタムエラーレスポンスを行なっていると、原因発見が遠くなってしまう。
CloudFront周りの調査は一時的にキャッシュを無効化して調査することが解決への近道。

18
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
16