S3 Cloudfront でのサブディレクトリへアクセス Lambda@Edge

目次

S3にて静的コンテンツをweb公開するとき、cloudfrontを噛ませると色々なメリットがるため、一般的になっていますが、その時の問題が、s3をstatic web hostingしなければ サブディレクトリがファイル指定しないと参照できない ということがあります。



https://example.com/ → https://example.com/index.html を参照してくれる(cloudfrontのDefault Root Objectの設定にて)
https://example.com/dir/ → https://example.com/dir/index.html を返してくれず403が帰ってくる

この時によくある設定方法としては、

s3でstatic web hostingをONにして、cloudfrontの向き先をS3のエンドポイントに設定するという方法がありますが、

個人的には、static web hostingをするのは、なんのために、cloudfront経由のみでしかs3にアクセスできなくしているのかという感じなので、避けたいところでした。

lambda@Edge を使う

ここで、

lambda@Edge を使うということで、どういうことかというと、 CloudFront ディストリビューションに Lambda 関数に関連付け、CloudFront エッジロケーションでリクエストとレスポンスが傍受することができ、次の CloudFront イベントの発生時に Lambda 関数を実行できます。

ここを参考にさせていただきました。ありがとうございます。

要するに、ざっくりとした流れは

  1. リクエスト
  2. Cloudfrontへのアクセス時にLambda@Edgeが呼ばれ
  3. Lambda@Edgeにて必要な処理をし、Cloudfrontに伝達
  4. Cloudfrontからs3参照
  5. レスポンス

ということで、

https://example.com/dir/

このようなアクセスが来た時に、index.htmlを付加しcloudfrontに通達してくれれば、403になることはありませんね。

Lambda関数を作成

キャプチャです

キャプチャです

これで面倒なロールやアクセス設定はOKです。今は簡単ですね。 (Lambda@EdgeよりCloudfrontへアクセスするようのロールを作成して付与したことになります)

関数のコード

'use strict';
exports.handler = (event, context, callback) => {
  //
  // Extract the request from the CloudFront event that is sent to Lambda@Edge
  var request = event.Records[0].cf.request;
  //
  // Extract the URI from the request
  var olduri = request.uri;
  //
  // Match any '/' that occurs at the end of a URI. Replace it with a default index
  var newuri = olduri.replace(/\/$/, '\/index.html');
  //
  // Log the URI as received by CloudFront and the new URI to be used to fetch from origin
  console.log("Old URI: " + olduri);
  console.log("New URI: " + newuri);
  //
  // Replace the received URI with the URI that includes the index page
  request.uri = newuri;
  //
  // Return to CloudFront
  return callback(null, request);
  //
};

こちらをコピーして貼り付けます。

トリガーの設定

  1. 画面上部、アクションのドロップダウン
  2. 新しいバージョンを発行
  3. 表示されたダイアログにバージョンを記入(未記入でもOK)
  4. 左のトリガーからcloudfrontを選択
  5. 表示されるトリガーの設定にで、cloudfrontのdistribution IDを入れ、cloudfrontのイベントをオリジンリクエスト とします。

これで設定は完了になります。

この後Cloudfrontの指定したdistributionのstatusが In Progressとなります。

まとめ

意外と簡単に設定でき、問題を解決できたかと思います。 同じ悩みの方は是非お試しください。間違っている部分等ありましたらご指摘ください。

U-chan ( Nobuyuki Ukai )

学生時代は建築やデザインを専攻していたが、Yahoo!Japanにエンジニアとして運良く入社し、2年半で波情報を配信する波伝説に転職。3年後、Yahoo!時代の先輩の立ち上げたベンチャーに転職。数年後、伊豆下田に移住し、ゲストハウスを開業しながらリモートでエンジニアを続けたが、焼肉店の開業とともに株式会社UKAIを立ち上げ、法人成り。その後、カフェとゲストハウスをもう一軒開業し、現在は焼肉店、カフェ、ゲストハウス2件目を運営。今季は自社Webサイトの立ち上げ予定!

comments powered by Disqus