S3+CloudFront+Lambda@EdgeでBasic認証

S3で試験用Webサイトを作るときにBasic認証しておかないとなぁと思って、
少し検証してみることにしました。
検証用なので別にドメインは取得しなくてもいいので今回はサクッと先人の
事例をまんま参照してやりました。


手順はこんな感じ

1.S3サイト作成
 Webhostingの設定、パブリックでの公開はしない

2.CloudFront準備
 CloudFront経由の時のみS3アクセス許可
 キャッシュは無効
  

3.IAMの設定(Lambda@Edge用)
・ポリシーのパラメータ

{
    "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": "*"
        }
    ]
}

・Lambda@Edgeの方とも信頼関係を結んでおく

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "lambda.amazonaws.com",
          "edgelambda.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}


4.Lambda関数設定(トリガーをCloudFrontに設定)
・リージョン
バージニア北部しかCloudFrontトリガーが対応していないので
リージョンはバージニア北部に設定

・Basic認証用LambdaFunction
'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);
    }
    else {
        // Continue request processing if authentication passed
        callback(null, request);
    }
};

・バージョニングで新しいバージョンを発行する。

5.トリガー設定
CloudFrontイベントの箇所を「ビューアリクエスト」にする。

途中、プログラムのコピペミスで503になってやり直ししたり
なぜかキャッシュが残ってBasic認証のパスワードがうまく通らなかったので

一度CloudFrontの設定を消して、もう一回設定しなおしたり
はまったものの、何とかうまく動きました。
サイト単位ではBasic認証がかけられる。一応は公開前のサイトの
検証の際に必要な設定はできるみたい。

ただ、S3にディレクトリ単位でBasic認証をかけたいというニーズは
この方法だと厳しいようだ。
サブディレクトリだけBasic認証する場合はhtmlでフォーム作って
Lambdaで認証通してからとか面倒なことをしないといけないかもしれない模様

というよりそういう場合は素直にEC2でWebサーバ立てろということか、、、
すいませんずぶの素人で・・・

◆参考URL
 https://qiita.com/BYAKheee/items/b3034df2443dde05f31b
   https://dev.classmethod.jp/cloud/aws/cloudfront-lambdaedge-basic-spa/
 http://blog.jicoman.info/2017/10/s3-basic-using-cloudfront-lambda-edge/
 http://developers.goalist.co.jp/entry/2017/05/11/191628
 https://lab.taf-jp.com/cloudfront%E3%81%A7%E3%83%99%E3%83%BC%E3%82%B7%E3%83%83%E3%82%AF%E8%AA%8D%E8%A8%BC/

コメント

このブログの人気の投稿

GASでGoogleDriveのサブフォルダとファイル一覧を出力する

証券外務員1種勉強(計算式暗記用メモ)

マクロ経済学(IS-LM分析)