お問い合わせ

S3 Website Hosting 向けに Lambda 関数で Basic Auth を実装する

制作・開発
profile

Muntasir Ahmed MUFTI

本記事は、英語で公開されている下記記事の日本語翻訳版です。
Implement Basic AUth using lambda function for S3 Website Hosting

S3 Website Hostingに対して、Pythonで書いたLambda@Edge 関数を使い、AWS CloudFrontで Basic認証を実装するには、以下の手順で進めます。

Basic認証を実装するための手順は次のとおりです。
Lambda 関数を作成する:
・認証を処理するLambda関数を作成します。
・Authorizationヘッダの内容を読み取り、ユーザー名とパスワードが正しいかどうかを確認します。
Lambda 関数を deploy(AWS 上で実行できる状態にする)する:
・AWS Lambda コンソール上で、作成した Lambda 関数を deploy します。
・なお、Lambda@Edge で利用する関数は us-east-1 リージョン から複製される仕組みのため、このリージョンで利用可能になっていることを必ず確認してください。
Lambda 関数を 実行タイミング(トリガー)として 組み込む
・具体的には、CloudFront ディストリビューションを新しく作成するか、すでにあるディストリビューションの設定を更新し、ユーザーからのリクエストを受け取った際などにLambda 関数が実行されるように設定します。

以下に、手順を順番に説明します。

Step 1: Lambda 関数を作成する

import base64

def lambda_handler(event, context):

    # Get the request object

    request = event['Records'][0]['cf']['request']

    # Get the headers

    headers = request['headers']

    # Define the username and password

    USERNAME = 'your_username'

    PASSWORD = 'your_password'

    # Encode the username and password

    auth_string = f"{USERNAME}:{PASSWORD}"

    encoded_auth_string = base64.b64encode(auth_string.encode()).decode()

    # Check for Authorization header

    if 'authorization' in headers:

        auth_header = headers['authorization'][0]['value']

        # Check if the Authorization header matches the encoded auth string

        if auth_header == f"Basic {encoded_auth_string}":

            return request

    # If no valid Authorization header is present, return a 401 Unauthorized response

    return {

        'status': '401',

        'statusDescription': 'Unauthorized',

        'headers': {

            'www-authenticate': [{'key': 'WWW-Authenticate', 'value': 'Basic'}],

            'content-type': [{'key': 'Content-Type', 'value': 'text/html'}]

        },

        'body': '<html><body><h1>Unauthorized</h1></body></html>'

    }

Step 2: Lambda 関数を deployする

AWS Lambda コンソールを開きます。
「Create function」をクリックします。
「Author from scratch」を選択します。
関数名を入力し、ランタイムに Python 3.x を選択します。
「Create function」をクリックします。
先ほどのコードを、関数のコードエディタにコピー&ペーストします。
最後に「Deploy」をクリックします。

Step 3: Lambda 関数を CloudFront に関連付ける

AWS CloudFront コンソールを開きます。
Basic 認証を設定したい CloudFront ディストリビューションを選択します。
「Behaviors」タブをクリックします。
認証を適用したい Behavior を選択し、「Edit」をクリックします。
「Lambda Function Associations」セクションで、イベントタイプに Viewer Request を選択します。
先ほど作成した Lambda 関数を選択します。
最後に「Yes, Edit」をクリックして設定を保存します。

Notes(注意点)

・Lambda@Edge を利用するため、Lambda 関数は us-east-1リージョン に作成されている必要があります。
・USERNAME と PASSWORD 変数は、使用したい認証情報に合わせて変更してください。
・なお、Basic 認証はセキュリティ面で万全とは言えないため、本番環境では OAuth や JWT など、より安全な認証方式の利用を検討してください。
この設定では、ユーザーからのリクエストごとに Basic 認証のチェックが行われます。認証情報が正しい場合は、そのまま CloudFront にリクエストが渡されます。認証に失敗した場合は、401 Unauthorized のレスポンスが返されます。

======= 以下のようなエラーが発生した場合は、次の手順を実施してください ========

edgelambda.amazonaws.com および lambda.amazonaws.com に必要な権限を付与するためには、
IAM ロールの 信頼関係(Trust Relationship) を調整する必要があります。

以下に、その設定手順を説明します。

Step 1: 信頼関係(Trust Relationship)を更新する

AWS IAM コンソールを開きます。
左側のメニューから「Roles」をクリックします。
pythonbaseauth-role-6qoa0e7x というロールを検索します。
ロール名をクリックして、ロールの詳細画面を開きます。
「Trust relationships」タブをクリックします。
「Edit trust relationship」ボタンをクリックします。

Step 2: 信頼関係ポリシードキュメントを修正する

信頼関係の設定に、edgelambda.amazonaws.comlambda.amazonaws.com の両方が含まれていることを確認する必要があります。
以下は、更新後の信頼関係ポリシードキュメントの例です。

{

  "Version": "2012-10-17",

  "Statement": [

    {

      "Effect": "Allow",

      "Principal": {

        "Service": "lambda.amazonaws.com"

      },

      "Action": "sts:AssumeRole"

    },

    {

      "Effect": "Allow",

      "Principal": {

        "Service": "edgelambda.amazonaws.com"

      },

      "Action": "sts:AssumeRole"

    }

  ]

}

{

上記の JSON を、現在の信頼関係ポリシードキュメントと置き換え、「Update Trust Policy」をクリックします。

Step 3: ロールに必要な権限が付与されていることを確認する

Lambda 関数を実行するために、IAM ロールに必要な権限が付与されていることを確認します。
まだ設定されていない場合は、AWSLambdaBasicExecutionRole ポリシーを追加してください。

「Permissions」タブを開きます。
「Attach policies」をクリックします。
AWSLambdaBasicExecutionRole ポリシーを検索し、ロールに追加します。

Step 4: Lambda@Edge 関数を再度 deploy する

信頼関係の更新と必要な権限の付与が完了したら、
Lambda@Edge 関数を CloudFront ディストリビューションに あらためて deploy します。

日本語翻訳:K. Shimazaki

関連投稿

blog-thumb

AIによる認知能力低下?

AIによる認知能力低下? —— MITの研究結果とこれからのエンジニアリング ...

blog-thumb

Contact Form 7 がメール送信に失敗したときに、PostSMTP で通知を受け取る方法

本記事は、英語で公開されている弊社ブログ記事の日本語翻訳版です。
英語元記事:How to Send Notifications via PostSMTP When Contact Form 7 Fails to Send an Email

blog-thumb

Laravel で既存のテーブル構造をコピーする方法

本記事は、英語で公開されている弊社ブログ記事の日本語翻訳版です。
英語元記事:How to Copy an Existing Table Structure in Laravel