My Note

自己理解のためのブログ

CloudFrontとLambda@Edge ( Nodejs )とS3で静的ページにIPアドレス制限とBasic認証を設定する

はじめに

今回はLambda@Edge( Nodejs14 )を使ってBasic認証とIP制限を設定しました。 本記事ではLambda@Edgeについてしか触れないので、構成やCloudFront、Lambda@Edgeの設定については下記の記事に記載しています。 下記の記事はPython3で実装しており、本記事はそれのNodejs版になります。

yhidetoshi.hatenablog.com

Lambda@Edgeについて

Basic認証とIP制限について

  • allowUsersに許可する User:Password を定義する
  • allowIpBasic認証を必要としない IPアドレスを定義する

Nodejsでbase64デコードする処理は以下のサイトを参考にしています。 docs.aws.amazon.com

  • basicauth.js
'use strict';

var errorResponse = {
    status: '401',
    statusDescription: 'Unauthorized',
    body: 'Authentication Failed',
    headers: {
        'www-authenticate': [
            {
                key: 'WWW-Authenticate', value: 'Basic'
            }
        ]
    },
}

var allowIp = ['X.X.X.X', 'X.X.X.X']

var allowUsers = {
    "admin": "pass1",
    "dev": "pass2"
}


exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const clientIp = request.clientIp

    if (validateClientIp(clientIp)) {
        callback(null, request)
    }

    if (! typeof headers.authorization) {
        callback(null, errorResponse)
    }

    let encodeAuth = headers.authorization[0].value.split(" ");
    let decodeAuth = Buffer.from(encodeAuth[1], 'base64').toString('ascii').split(":");

    const requestUser = decodeAuth[0];
    const requestPassword = decodeAuth[1];
    if (validateAuth(requestUser, requestPassword)) {
        callback(null, request)
    } else {
        callback(null, errorResponse)
    }
};

function validateAuth(user, password) {
    let exist_flag = false
    for (let key in allowUsers) {
        if (user === key && password === allowUsers[key]) {
            exist_flag = true
            return true;
        }
    }
    if (exist_flag === false) {
        return false;
    }
}

function validateClientIp(clientIp) {
    if (allowIp.indexOf(clientIp) !== -1) {
        return true
    } else {
        return false
    }
}

動作確認について

CloudFrontを用意してクライアントから動作確認しなくても、CloudFrontから受け取る eventデータを Lambda@Edgeの テストイベント に設定して確認ができます。 動作確認で設定するのは、 clientIpIPアドレスを、authorizationuser:password をbasic64をエンコードした値を動作確認したい内容に応じて適宜設定します。

echo -n dev:pass2 | base64
ZGV2OnBhc3My
{
    "Records": [
        {
            "cf": {
                "config": {
                    "distributionId": "EXAMPLE"
                },
                "request": {
                    "headers": {
                        "host": [
                            {
                                "key": "Host",
                                "value": "d123.cf.net"
                            }
                        ],
                        "authorization": [
                            {
                                "value": "Basic ZGV2OnBhc3My"
                            }
                        ],
                        "user-name": [
                            {
                                "key": "User-Name",
                                "value": "CloudFront"
                            }
                        ]
                    },
                    "clientIp": "0.0.0.0",
                    "uri": "/index.html",
                    "method": "GET"
                },
                "response": {
                    "status": "200",
                    "statusDescription": "OK",
                    "headers": {
                        "x-cache": [
                            {
                                "key": "X-Cache",
                                "value": "Hello from Cloudfront"
                            }
                        ]
                    }
                }
            }
        }
    ]
}

ソースコードGitHubにあります。

github.com