S3+CloudFrontの構成で静的なサイトを公開する場合の注意点
最近静的なサイトを公開するためにS3と、サイトをSSLにするため+高速化のためにCloudFrontを組み合わせて構築した際に、サブディレクトリのページを更新すると403が返されてしまう現象に遭遇し、一時間くらいハマったのでメモしておく
なお、このサイト(hakozaru.com)は単にFirebaseでホスティングされているので今まで遭遇することがなかった
構成と設定
すごくオーソドックスな構成(Gatsby+S3+CloudFront)の構成で静的なサイトを構築していた
サーバーレスは偉大である
- S3
- バケットのパブリックアクセスは全て遮断
- CloudFront向けのバケットポリシーだけを設定し、CloudFront経由のアクセスだけを許可
- よって「静的ウェブサイトホスティング」も無効
- CloudFront
- オリジンにはS3バケットそのものを指定↓して配信
と言う感じで特に違和感を感じることもなく、サイトも普通に表示されているように見えた
(ACMを使ってSSL化と、Routes53も使ってるけど関係ないので略)
問題の発生
そんなこんなで構築もある程度終わり、動作確認していたところ、サブディレクトリのページでリロードを行うと403が返されてしまうことが判明した
- トップページなどにあるリンクから
https://example.com/hogehoge
へ移動するのは問題ない - しかし移動後に
https://example.com/hogehoge
をリロードすると403になる
と言う感じだった
問題の検証と原因の特定
イマイチ状況が理解できなかったので、思いつく範囲で色々調べてみた
- Gatsby.jsのビルドは問題なさそうで、ビルドで生成されたファイルがアップロードされた後にS3のバケットを覗いてみるとサブディレクトリは存在していて、
index.html
も存在している https://example.com/hogehoge
に直接アクセスしても403になるけど、https://example.com/hogehoge/index.html
はアクセスできて即https://example.com/hogehoge
へリダイレクトされる
最初Gatsbyに原因があるのか、AWS側に原因があるのかちょっとわからなかったけど、調べてみた感じCloudFrontがサブディレクトリの index.html
を参照できていないっぽいことがわかったので、CloudFrontに絞って調査を進めたところこの記事へ行き着いた
サイトの構成的に「サブディレクトリのインデックスファイルが効かない」状態となっていたということらしい
問題の解消
S3+CloudFrontの構成で静的なサイトを構築する場合、2つの方法があるらしい
- CloudFront のオリジンにS3バケットそのものを指定する構成
- CloudFront のオリジンにS3バケットのStatic website hostingのエンドポイントを指定する構成
静的なサイトを公開すると言う点において違いはありませんが、若干違いがあり表にしてみると
と言う感じ
↑で説明した通り、僕が構築していたサイトの構成はここで言う構成1の状態なので、CloudFrontのサブディレクトリのインデックスファイルは使えなかった
と言うことで一旦構成2の状態にしてサイトを公開し、セキュリティ部分に関してはできることを随時対応している
(もしかしたらパスに index.html
を強制するようにして、構成1に戻すかもしれないが、今のところ未定。やりながら考える)
なお、 S3バケットのStatic website hostingのエンドポイントを指定する
とはどう言うことなのかですが
↑でスクショを貼ったCloudFrontのOrigin Domain Nameに、S3バケットの静的ウェブサイトホスティングを有効にした際に表示されるURL(http://バケット名.s3-website-リージョン.amazonaws.com
)を入れればOKです
いやー知らなかった、とても勉強になりました