AWS S3で公開している静的サイトにBasic認証をかける方法です。
S3の他に、LambdaとCloudFrontの設定が必要になります。
S3バケットの作成
まずはBasic認証をかけたいS3のバケットを用意します。
パブリックアクセスの許可や、Static website hostingの設定は必要ありません。
CloudFrontの設定
Create distribution -> Web側のGet Startedを選択し、CloudFrontの設定に進みます。
Origin Domain Name
にBasic認証をかけたいS3のバケットを指定します。
Origin ID
は自動的に設定されます。
Restrict Bucket Access
を Yes
にします。
Origin Access Identity
は Create a New Identity
にします。
これで Comment
部分は自動で設定されます。
Grant Read Permissions on Bucket
は Yes, Update Bucket Policy
を選択してください。
キャッシュは無効にするので、 Cache Policy
は Managed-CachingDisabled
を選択してください。
Default Root Object
を index.html
等に設定すれば、ルートにアクセスした際のデフォルトファイルを指定可能です。
その他はデフォルト設定でOKです。
ここまで設定したら、Create Distributionを押して作成しましょう。
デプロイが完了したら、指定したS3のバケットポリシーに設定が追加されていることがわかります。
また、 CloudFrontの Error Pages
の設定で、 403
404
エラーの際は /index.html
へリダイレクトするように設定しておきましょう。
この設定がなければ、SPAのサイトではルート以外のURL(例えば /about
など)で画面を更新した際にエラーになってしまいます。
Lambdaの設定
Basic認証を行うためのLambda関数を作成します。
バージニア北部(us-east-1)
から作成を行ってください。
関数名
は basicAuthentication
としています。
ランタイム
は Node.js
です。
デフォルトの実行ロールの変更
では、 AWSポリシーテンプレートから新しいロールを作成
を選択し、
ロール名
に lambda_edge_exec
(任意の名前)、 ポリシーテンプレート - オプション
に 基本的な Lambda@Edge のアクセス権限 (CloudFront トリガーの場合
を設定します。
関数コードの index.js
に下記のコードを貼り付けます。
const authUser = 'user';
と const authPass = 'pass';
の部分で、Basic認証のuserとpassを設定します。
その後 Deploy
ボタンを押してデプロイします。
'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 = '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@Edgeへのデプロイ を選択します。
ディストリビューション
に先程作成したCloudFrontを指定します。
CloudFrontイベント
は ビューアーリクエスト
を選択します。
Lambda@Edgeへのデプロイを確認
にチェックして、デプロイを行います。
CloudFrontを確認すると、 status
が In Progress
になっていることが確認できます。
デプロイが完了すると、CloudFrontのドメインネームにアクセスした際、Basic認証がかけられていることが確認できます。
ちなみに、 バージニア北部(us-east-1)
以外で作ったばかりのS3のバケットにCloudFront経由でアクセスしても、リダイレクトされてしまいます。
しばらく待つか、下記の解決法を参考にしてください。
S3+CloudFrontでS3のURLにリダイレクトされてしまう場合の対処法