S3静的ウェブホスティング+CloudFront+Lambda@EdgeでBasic認証をかける

先日、Yahoo!ジオシティーズが、2019年3月31日でサービス終了するとのことが公式サイトで発表された。

サービス終了のお知らせ - Yahoo!ジオシティーズ

このニュースに対して、ネットでは、

「ジオシティーズが終わると大量の黒歴史が消える」
「たくさんの黒歴史が闇に葬られることになりそう」
「35歳周辺の人々、黒歴史がインターネットから消滅するのでホッとしてるのでは」

などの声が上がっていた。

【黒歴史】Yahoo!ジオシティーズがサービスを終了 「黒歴史しか残ってない」「ホッとしてるのでは」 : まとめダネ!

そんな状況を見て、

21年も続いたサービスが終了しちゃうのは寂しい感じがするな。ふーん。黒歴史ねぇ……。

なんて思って見ていたのだが……。

あーーーっ!!そういえば、大学生の頃、ジオシティーズ使ってたわ!……まだ残ってたりするんだろうか……

と思い出してしまった。
それで、ちょっと見に行ったら。なんと残っていたのだ。
当時のまま。ある意味、これは「黒歴史」と言えるのかもしれない。

これを社内のLT、通称MLT(MMM Lightning Talk)で話をしたら、思いの外チームメンバーに受けてしまい、

「世界遺産として保護すべきコンテンツ」
「S3に移行するべき」

だとか言われたり、こんな Slack のカスタムリアクションが作られてしまった。
(サイト名に「見聞録」が入っていたため)

懐かしい思いもあるので、保存しておこうとは思うが、「黒歴史」なので、アクセス制限をしなくては!
ということで、前フリが長くなったが、今回は、 S3 の静的ウェブホスティング + CloudFront の環境に、 Lambda@Edge を使ってBasic認証をかける手順を簡単にまとめていく。

S3にバケット作成、アップロード

まずは、S3にバケットを作成する。そして、保存したいファイルをアップロードする。
今回は、ジオシティーズからダウンロードしてきたファイルをそのまま全部突っ込んだ。

次に、静的ウェブホスティングを有効にする。

CloudFront のディストリビューション作成

CloudFront のディストリビューションを作成する。
Origin Domain Name には、先程有効にした静的ウェブホスティングのエンドポイントのURLを入力する。

Lambda@Edge 作成

続いて Lambda@Edge を作成する。
ここでのポイントは、 Lambda を作成するリージョンは、 米国東部(バージニア北部) リージョン としないといけないこと。

Lambda を実行するロールは、「テンプレートから新しいロールを作成」を選択、「基本的な Lambda@Edge のアクセス権限(CloudFront トリガーの場合)」を選ぶ。

コードは下記の通り。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
'use strict';
exports.handler = (event, context, callback) => {

// Get request and request headers
const request = event.Records[0].cf.request;
const headers = request.headers;

// Configure authentication
const authUser = 'hiroshi'; // ユーザー
const authPass = 'yujin'; // パスワード

// Construct the Basic Auth string
const authString = 'Basic ' + new Buffer(authUser + ':' + authPass).toString('base64');

// Require Basic authentication
if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString) {
const body = 'Unauthorized';
const response = {
status: '401',
statusDescription: 'Unauthorized',
body: body,
headers: {
'www-authenticate': [{key: 'WWW-Authenticate', value:'Basic'}]
},
};
callback(null, response);
}

// Continue request processing if authentication passed
callback(null, request);
};

Lambda 関数の制限としては、下記のようなものがあるので注意が必要。
(公式ドキュメントより抜粋)

  • nodejs6.10 または nodejs8.10 ランタイムプロパティを使用して関数を作成する必要があります。
  • VPC 内のリソースにアクセスするように Lambda 関数を設定することはできません。
  • 別の AWS アカウントによって所有されている CloudFront ディストリビューションに Lambda 関数を関連付けることはできません。
  • デッドレターキュー (DLQ) はサポートされていません。
  • 環境変数はサポートされていません。

環境変数は使えないので、Basic認証の、ユーザー、パスワードもべた書きしないといけない。

Lambda トリガー設定

関数を保存したら、トリガーの設定を行う。
「トリガーの追加」項目から、 CloudFront を選ぶ。

下部に、「Lambda@Edge へのデプロイ」が出るので、クリック。

ダイアログが出てくるので、先ほど作成した CloudFront のディストリビューションを選択。
ここでのポイントは、「CloudFront イベント」に、「ビューアーリクエスト」を選択すること。
「デプロイ」をクリックして、デプロイする。

ちなみに、「ビューアーリクエスト」とは、CloudFront がビューワーからリクエストを受信した後のタイミングとなる。
他のリクエストについては、下記の通りとなっているので、 Lambda 関数を実行したい適切なタイミングを指定すること。

あとは、CloudFront の、StatusDeployed になるのを待ってアクセスをしてみる。

無事、Basic認証が有効になった。
(ง°`ロ°)งヨッシャ‼

CloudWatch Logs

Lambda のログを確認する際の注意点としては、

Lambda は、関数が実行される場所に最も近い CloudWatch Logs リージョンで CloudWatch Logs ログストリームを作成する

ということ。
Lambda を作成するのは、米国東部(バージニア北部) リージョン。
ログはアクセス元に近いリージョン。
なので、焦らないように。
各ログストリームの名前の形式は、下記のようになる。

/aws/lambda/us-east-1.function-name

まとめ

いくつかの制限はあるものの、 Lambda 関数を使うと、公式ドキュメントの関数例にも記載があるとおり、Basic認証だけではなくて、かなり幅広いことができるので、今後も機会があれば積極的に使っていきたい。

最後に、一応「黒歴史」に興味ある奇特な方のために、今回設定した CloudFront のURLを置いておく。

http://d34uznjcq34cw.cloudfront.net
Username: コードを見て
Password: コードを見て

【参考URL】
Lambda@Edge - AWS Lambda
Lambda@Edge 関数の例 - Amazon CloudFront
Lambda 関数の要件と制限 - Amazon CloudFront
Serverless: password protecting a static website in an AWS S3 bucket
CloudfrontとS3でBasic認証をかける
S3 + CloudFront + Lambda@Edge でBasic認証

このエントリーをはてなブックマークに追加