この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どうも!大阪オフィスの西村祐二です。
特定のユーザにしかログインできないように、 サイト自体にBasic認証をかけたい時があると思います。
今回はS3でホスティングするSPAを想定して、 Amazon CloudFrontとAWS Lambda@Edgeを使ってBasic認証をかけたいと思います。
構成図
完成画面
完成後下記のような挙動になります。 ブラウザ上にURLを入力してアクセスすると、Basic認証の画面が表示されます。 認証が通ったら、S3に保存されているWEBページが表示されます。
作業手順
- S3でSPA用のバケット作成
- CloudFrontのディストリビューションを作成
- Lambda@Edge用のLambda関数作成
- 作成したLambda関数でトリガーをCloudFrontに設定
S3での作業
SPAの静的ファイルを設置するためにバケットを作成します。 リージョンは「東京リージョン」で作成しています。 バケット名は今回「test-lambda-edge」としました。 ログ出力用に「test-lambda-edge-log」も一緒に作成しておくとよいかもしれません。
テストファイルを配置
SPAを想定して、今回下記の静的ファイル「index.html」をS3バケットの「test-lambda-edge」に設置しておきます。
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test Basic Authentication</title>
</head>
<body>
<p>Hello World!! Passed Basic Authentication!</p>
</body>
</html>
S3カスタムオリジンで利用するため、Webホスティング設定は実施しません。
CloudFrontのディストリビューションを作成
▼マネージメントコンソールから作成していきます。「Create Distribution」をクリックします。
▼Webを選択します。
▼下記のように設定していきます。
▼TTLは各自適当な設定を行ってください。今回コンテンツの更新をすぐ確認したかったため、無効化しています。
確認
▼作成したディストリビューションが「Deployed」であることを確認します。
▼HTTPでアクセスできないこと
▼HTTPSでアクセスできること
Lambda関数の作成
次にCloudFrontのエッジロケーションに配置するLambda関数を作成していきます。
IAMロールの作成
まず、Lambda@Edge用のIAMロールとポリシーの設定を行います。
▼IAMのマネージメントコンソールから設定していきます。
▼「信頼されたエンティティ」でLambdaをクリックし「次へ」のボタンをクリックします。
▼作成するロールにアタッチするポリシーを作成します。
▼新しいタブが開き、ポリシーを作成する画面に移動します。 JSONのタブをクリックして、下記のポリシーを貼り付けます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"lambda:GetFunction",
"lambda:EnableReplication*",
"iam:CreateServiceLinkedRole",
"cloudfront:CreateDistribution",
"cloudfront:UpdateDistribution"
],
"Resource": "*"
}
]
}
▼ポリシーの名前を「test-lambda_edge_exection」としてポリシーを作成します。
▼ロール作成のタブに戻り、「更新」ボタンをクリックし、検索窓から検索し、作成したポリシーを選択し、次へ行きます。
▼ロール名を「test-lambda_edge_exection」としてロールを作成します。
▼信頼関係に「edgelambda」を追加します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"edgelambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
これで、IAMロールとポリシーの設定は完了です。
Lambda@Edgeの注意点
※2018/1/5時点の情報となります。 通常の作成方法とは異なりいくつかハマりポイントがあります。Lambda関数を作成する前に、Lambda@Edgeの注意点についてまとめておきます。
詳細はドキュメントを参照ください。
- ランタイム:Node.js 6.10のみ対応?
- リージョン:米国東部(バージニア北部)で作成する必要あり
- メモリサイズ:128MBまで
- 実行時間:
- ビューワーリクエストおよびビューワーレスポンスイベント:1秒
- オリジンリクエストおよびオリジンレスポンスイベント:3秒
- Lambda関数のファイルサイズ:1MBまで
- バージョニングを使用する必要あり、$Latest は指定できない
- /tmp は利用不可
- 環境変数, Dead Letter Queue, Amazon VPCsは利用不可
Lambda@Edgeのイベント
今回行うBasic認証はビューアリクエストのイベントに該当します。
Lambda関数の作成
▼マネージメントコンソールから作成していきます。
▼「一から作成」を選び、名前「S3-basic-authentication」、ランタイム「Node.js 6.10」、作成したIAMロールを設定して関数を作成します。
▼実行時間の設定をビューアリクエストの制限をこえないように「1秒」に設定します。
実際のプログラムはこちらを参考にさせていただきました。
'use strict';
exports.handler = (event, context, callback) => {
// Get request and request headers
const request = event.Records[0].cf.request;
const headers = request.headers;
console.log('request: ' + JSON.stringify(request));
// Configure authentication
const authUser = 'user';
const authPass = 'pass';
// 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をCloudFrontのエッジロケーションに配置するためにトリガーをCloudFrontに設定するのですが CloudFront イベントを $LATEST またはエイリアスと関連付けることはできません。
そのため、バージョン設定を行う必要があります。
▼アクションから「新しいバージョンを発行」をクリックします。
▼バージョンを発行します。
▼発行されたら下記のような表示がされます。
トリガー設定
Lambda@Edgeとして、CloudFrontのエッジロケーションにLambda関数を設定するためには Lambda関数のトリガーをCloudFrontにする必要があります。
▼作成したディストリビューションのIDを設定し、イベントに「ビューアリクエスト」を設定し追加します。
▼その後「保存」ボタンをクリックすると、CloudFrontのディストリビューションのステータスが「In Progress」になります。
▼ステータスが「Deployed」になったら、エッジロケーションにLambda関数のデプロイが完了したということになります。
Basic認証の動作確認
CloudFrontのURLにアクセスしてみると想定通り Basic認証のログインアラートが表示されています。
さいごに
いかがだったでしょうか。
Amazon CloudFrontとAWS Lambda@EdgeでSPAのBasic認証をやってみました。 Lambda@Edgeはエッジロケーションへのデプロイまで時間がかかったり 作成時に制限などがありますが、いろいろなことに活用できそうだなと思いました。
誰かの参考になれば幸いです。
参考サイト
http://blog.jicoman.info/2017/10/s3-basic-using-cloudfront-lambda-edge/
https://qiita.com/sumikawa@github/items/0344a2920f2438dea3b5
https://gist.github.com/lmakarov/e5984ec16a76548ff2b278c06027f1a4
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-edge.html#lambda-edge-testing-debugging