前回までのあらすじ

第1回では samekorolab.com を取得し、自分のドメインでSAMEKORO LABを開けるところまで進みました。

今回は、その画面が届くまでの裏側です。CloudFrontとS3をどうつなぎ、なぜS3を直接公開しなかったのかを、自分の判断を中心に振り返ります。

最初はS3だけで公開すればいいと思っていた

SAMEKORO LABはHTML、CSS、JavaScript、画像でできた静的サイトです。最初は、S3にファイルを置き、Webサイトとして公開する形が分かりやすいと思っていました。

ただ、独自ドメインとHTTPSを使いながら、S3は外へ直接見せない構成も試してみたくなりました。利用者がアクセスする場所をCloudFrontへまとめたほうが、今回の配信経路を自分で説明しやすいとも考えました。

そこで、S3はファイル置き場にし、公開側はCloudFrontへ任せることにしました。

CloudFrontをサイトの入口にした

サービスを一つ増やすぶん複雑になるのでは、と少し迷いました。それでも、入口をCloudFrontへまとめれば、守りたい境界を説明しやすくなります。必要なファイルはS3から取得し、独自ドメインとHTTPSもここで受けます。

イメージとしては、CloudFrontが入口、S3が奥の倉庫です。比喩は単純ですが、自分がどちらを公開し、どちらを閉じたいのかが分かりやすくなりました。

公開経路をCloudFrontへ寄せ、S3を非公開にする。その目的に合うかどうかで構成を決めました。

OACでCloudFrontからだけS3へアクセスさせる

S3を非公開のまま使うため、OAC(=CloudFrontからだけS3へアクセスさせる仕組み)を設定しました。

CloudFrontがS3へリクエストするときに署名を付け、そのアクセスだけをS3側で許可します。バケットのパブリックアクセスはブロックしたままです。

OACを作ってCloudFrontへ関連付けたところで、いったん「これで通るはず」と思いました。実際は、どのCloudFrontディストリビューションから、どのオブジェクトを取得してよいか、S3のバケットポリシーにも許可を書く必要があります。片側だけではつながらないことに、ここで気づきました。

今回の構成

設定画面を行き来していると全体を見失いそうになったので、今回組んだ流れを図にしました。

利用者ブラウザ
HTTPS
samekorolab.com独自ドメイン
DNS
Amazon Route 53名前から配信先を案内
Amazon CloudFront公開入口 / 配信
OAC
非公開S3バケット静的ファイルを保存
AWS Certificate ManagerCloudFrontへTLS証明書を提供
S3オブジェクトURLへ直接アクセスAccess denied
CloudFrontを唯一の公開入口にし、OAC経由のアクセスだけを非公開S3バケットで許可。ACMはCloudFrontへ証明書を提供し、S3への直接アクセスは拒否します。

利用者はHTTPSで samekorolab.com を開きます。Route 53がCloudFrontへ案内し、CloudFrontはOAC経由で非公開S3バケットからファイルを取得します。ACMの証明書はCloudFrontへ設定しています。

図へ戻って眺めると、S3は公開経路にいないことがはっきりします。CloudFrontまたは独自ドメインからは表示でき、S3のオブジェクトURLへ直接アクセスしても拒否される。この両方を確認できて、ようやく狙った形になったと感じました。

S3の静的Webサイトホスティングは使わなかった

今回は、S3の静的Webサイトホスティングを有効にしていません。CloudFrontのオリジンには、通常のS3バケットエンドポイントを指定しています。

CloudFrontのDefault Root Object(=CloudFrontディストリビューションのルートURLへアクセスした際に返すファイル)には index.html を設定しました。これは配信ドメインのルートURL向けの設定で、記事のような下層URLへ自動的に index.html を補うものではありません。

そのため現在の記事リンクは、articles/<slug>/index.html まで含めています。二つを同じ仕組みだと思っていたので、実際のURLを試して違いが分かりました。

バケットポリシーでCloudFrontだけを許可した

OACを関連付けたあと、バケットポリシー(S3バケットへのアクセス許可を決める設定)を追加しました。見るポイントは次の3つです。

  • CloudFrontのサービスに
  • S3オブジェクトの取得を
  • このサイトの対象ディストリビューションからだけ許可する

最初にJSON全体を眺めたときは少し身構えました。ただ、許可する相手・操作・対象へ分けると、何を通そうとしているのか追えるようになりました。実際のアカウントIDやARNは記事には載せません。

設定途中で403エラーが出た

設定の途中では、403エラー(=アクセスを拒否された状態)が出ました。S3を閉じた結果なのか、CloudFrontからの道を作り切れていないのか、ここで少し迷いました。どこかの許可がつながっていなければ表示できません。

当時の記録だけでは、原因を一つに特定できていません。確認候補として残しているのは、OACの関連付け、バケットポリシーの対象、S3オリジン、オブジェクトキー、Default Root Objectです。

早く直したくて設定を足したくなりましたが、原因を決めつけず、CloudFrontからS3までを順にたどるほうが確実でした。

狙った構成になっているか確認した

設定後は、今回の環境で実際にアクセスして確認しました。

  • CloudFrontのURLからサイトを表示できる
  • samekorolab.com からも同じサイトを表示できる
  • S3オブジェクトURLへ直接アクセスすると拒否される

CloudFront経由で画面が出たときは、まずほっとしました。そのあとS3へ直接行くと見えないことも確認し、二つがそろって初めて狙った状態だと判断できました。

個人サイトには少し大げさ。でも今回はこれでよかった

最短で公開することより、自分で公開経路をつなぎ、確かめることを優先しました。S3を直接見せず、入口を一つにしたいという判断には合っています。

公開後には、記事カードのリンクが articles/<slug>/ で終わっていたため、下層の index.html が自動では返らず404になりました。リンクを articles/<slug>/index.html へ直して解消しています。詳しい切り分けは、別のトラブル解決記事にできそうです。

設定画面だけでなく、実際のURLまで見る必要があると、ここでも分かりました。

まとめ

SAMEKORO LABは、CloudFrontを公開側に置き、OAC経由で非公開S3から配信する構成にしました。S3への直接アクセスが拒否されることも確認しています。

構成要素は増えましたが、公開する経路と閉じる場所を自分の目的から決められたので、今回はこの形でよかったです。

次回は、公開前の記事まで見えてしまい、サイトの公開範囲を見直した話を書きます。