CloudFront FunctionsとLambda@Edgeの比較と実践

tiga

それぞれの概要と違い

CloudFront FunctionsとLambda@Edgeの概要について、以下に要点を表形式でまとめました。

※その他の違いや詳細については、AWSドキュメント「CloudFront Functions と Lambda@Edge の違い」をご参照ください。

項目CloudFront FunctionsLambda@Edge
概要簡単な処理、低レイテンシ要求の処理複雑な処理、大規模なトラフィック、長時間実行の処理
プログラミング言語JavaScript (ECMAScript 5.1 準拠)Node.js と Python
関数の持続時間サブミリ秒最大 5 秒 (Viewer request、Viewer response)
最大 30 秒 (Origin request、Origin response)
スケール量毎秒 1000 万 件1 リージョンあたり毎秒 1万 件まで
対応するCloudFront イベントViewer request
Viewer response
Viewer request
Viewer response
Origin request
Origin response

Viewer Request/ResponseとOrigin Request/Responseについて

  • Viewer Request
    • クライアント(ユーザー)が CloudFront にリクエストを送信した直後に実行される
  • Viewer Response
    • CloudFront がクライアントにレスポンスを返す直前に実行される
  • Origin Request
    • CloudFront がオリジンサーバー(例: S3やEC2)にリクエストを送信する直前に実行される
  • Origin Response
    • オリジンサーバーから CloudFront にレスポンスが戻ってきた直後に実行される

Viewer Request/Response と Origin Request/Response のトリガーを使い分けることで、CloudFront 関数や Lambda@Edge を適切に活用し、キャッシュの前後でコンテンツを効率的に操作できます。

CloudFront Functions で利用できない機能が必要な場合でも、Lambda@Edge を使ってキャッシュの前後でコンテンツを操作できます。

参考)Introducing CloudFront Functions – Run Your Code at the Edge with Low Latency at Any Scale

料金比較

項目CloudFront FunctionsLambda@Edge
リクエスト料金100 万回あたり 0.1 USD100万件あたり USD 0.60
コンピューティング料金なしあり(128 MB-秒の使用につき 0.00000625125 USD)
無料枠あり(1 か月あたり 200 万件の CloudFront 関数呼び出し)なし

※AWSドキュメント「Amazon CloudFront の料金
※AWSドキュメント「AWS Lambda 料金」

料金の例

1か月に100万回リクエストされ、1か月のコンピューティング時間が合計100万 秒(毎回の実行時間が 100 ミリ秒)であった場合、発生する料金は以下のように計算されます。

項目CloudFront FunctionsLambda@Edge
1 か月のコンピューティング料金なし1000,000 × 0.00000625125 USD
= 6.3 USD
1 か月のリクエスト料金100 万回あたり 0.1 USD100万件あたり USD 0.60
無料枠あり(1 か月あたり 200 万件)なし
合計0 USD(※無料枠が適用された場合)6.9 USD

CloudFront FunctionでBasic認証+IP制限の実装

私がCloudFront Functionを触ったことがなく、CloudFront Functionでどの程度の処理なら出来るかのイメージが分からないので、とりあえずCloudFront Functionを使ってBasic認証+IP制限の実装をやってみようと思います!

  • 全体の流れ
    • ステップ1: S3 作成
    • ステップ2: CloudFront 作成
    • ステップ3: S3 バケットポリシー編集
    • ステップ4: (練習)リダイレクト用のCloudFront Functions作成)
    • ステップ5: CloudFront FunctionでBasic認証+IP制限を実装

ステップ1: S3作成

  • 今回オリジンをS3にするため、S3を作成します。

作成後、以下のフォルダ構成でフォルダ・HTMLファイルを作成し、S3バケットへのアップロードをします。

フォルダ構成はこちらになります。

/
  └── index.html
  └── management/
      └── index.html
<!DOCTYPE html>
<html lang="ja">
<h1>Welcome</h1>
</html>
<!DOCTYPE html>
<html lang="ja">
<h1>Welcome manager</h1>
</html>

ステップ2:  CloudFront 作成

  • 続いて、CloudFrontを作成します。
  • 作成する際にいくつかの項目を設定します。
    • Origin domain:ステップ1で作成したS3を選択
    • オリジンへのアクセス制御方法:OACを使用
      • Create new OACをクリックして、任意の名前で作成可能
    • 今回は検証のため、ウェブアプリケーションファイアウォール (WAF)は有効にせず作成
スクリーンショット 2024-11-18 9.35.59.png
スクリーンショット 2024-11-18 9.35.16.png
  • CloudFront 作成後にAWSマネジメントコンソール上部に以下の通知が来るので、「ポリシーをコピー」をクリックお願いします。ステップ3の「S3バケットポリシー編集」で使用します。
スクリーンショット 2024-11-18 9.40.21.png

ステップ3: S3バケットポリシー編集

  • ステップ2の最後にコピーしたポリシーをステップ1で作成したS3のバケットポリシーに設定します。

例:

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{S3リソース名}/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "{CloudFrontのArn}"
                }
            }
        }
    ]
}

一度アクセスできるか確認

CloudFrontのコンソールにて、ステップ2で作成したCloudFrontのディストリビューションドメイン名をコピーしてアクセスしてみます。
そのドメインに/index.htmlを足してアクセスし、「Welcome」と表示されればOKです!

例:https://xxxxxxxxxxx.cloudfront.net/index.html

スクリーンショット 2024-11-18 10.02.23.png
スクリーンショット 2024-11-19 8.53.46.png

練習:リダイレクト用のCloudFront Functions作成

ここで一度練習を入れました!必要ない方は飛ばしていただいても大丈夫です!

https://xxxxxxxxxxx.cloudfront.netにアクセスした際に、https://xxxxxxxxxxx.cloudfront.net/index.htmlにリダイレクトされるように設定します。

  • CloudFrontのコンソールにて、ビヘイビアを作成します。
    • パスパターンを/
    • オリジンに作成したS3を設定
スクリーンショット 2024-11-18 10.16.38.png
  • 作成後の設定画面がこちらになります。
スクリーンショット 2024-11-18 10.18.42.png
  • 続きまして、CloudFrontのコンソールのサイドメニューから関数をクリックし、CloudFront Functionsを作成します。
スクリーンショット 2024-11-18 10.20.53.png
  • 続いて実行するコードを記載し保存します。
function handler(event) {
    var request = event.request;
    var uri = request.uri;

    // リクエストパスが `/` の場合に `index.html` を追加
    if (uri === "/") {
        request.uri += "index.html";
    }

    return request;
}
スクリーンショット 2024-11-18 10.23.40.png
  • 続いて実行するコードをテストをするために、テスト画面にて項目のURLパスを/にして関数をテストします。
スクリーンショット 2024-11-18 10.25.28.png
  • このように成功すればOKです!
スクリーンショット 2024-11-18 10.27.53.png

実行結果に記載されているコンピューティング使用率が50以上であれば、関数コードの最適化するか、Lambda@Edgeへの移行が必要になります。

:::note info

  • コンピューティング使用率の値:
  • 1 ~ 50 — この機能は最大許容時間を快適に下回っており、スロットリングなしで実行されます。
  • 51 ~ 70 — 関数は最大許容時間に近づいています。関数コードを最適化することを検討してください。
  • 71 ~ 100 — 関数が最大許容時間に非常に近いか、それを超えています。ディストリビューションに関連付けた場合、CloudFront は、この関数をスロットリングする可能性があります。

参考)AWSコンソール画面の説明文より抜粋
:::

  • テストを実行した後、「関数を発行」をクリックすると、ディストリビューションに関連付けの設定画面が表示されるので、作成したディストリビューションのキャッシュビヘイビア/を関連付けることができます。
スクリーンショット 2024-11-18 10.36.32.png
  • クライアント(ユーザー)が CloudFront にリクエストを送信した直後に実行されるようにしたいので、イベントタイプでViewer Requestを選択しています。
スクリーンショット 2024-11-20 15.53.06.png
  • 関連付けが完了したのち、https://xxxxxxxxxxx.cloudfront.netにアクセスし、/index.htmlの内容が表示されていればOKです!
スクリーンショット 2024-11-18 10.43.09.png

ステップ4: CloudFront FunctionでBasic認証+IP制限を実装

それでは、先ほど実施していただいた手順と同じように、CloudFront FunctionでBasic認証+IP制限を実装していきます。
https://xxxxxxxxxxx.cloudfront.net/management/index.htmlへアクセスする際に、指定したIPアドレスからのアクセスのみを許可し、さらにBasic認証を要求する実装になります。

  • CloudFrontのコンソールにて、ビヘイビアを作成します。
    • パスパターンを/management/*
    • オリジンに作成したS3を設定
スクリーンショット 2024-11-19 16.48.38.png
  • 作成後の設定画面がこちらになります。
スクリーンショット 2024-11-19 16.49.54.png
  • 再度新規のCloudFunctionsを作成し、以下のコードを記載し保存します。
  • 以下の三つの部分を変更してコードを使用してください。
    • XX.XX.XX.XX  :あなたの利用しているIPアドレス
    • yourUsername :任意のユーザー名
    • yourPassword :任意のパスワード
function handler(event) {
    var request = event.request;
    var headers = request.headers;
    var clientIP = event.viewer.ip;

    console.log('Client IP:'+clientIP);

    // アクセス許可するIPリスト
    var IP_WHITE_LIST = {
        'XX.XX.XX.XX': true, // 要変更
    };

    // Basic認証のユーザー名とパスワード
    var credentials = {
        username: "yourUsername", // 要変更
        password: "yourPassword", // 要変更
    };

    // Basic認証のためにユーザー名とパスワードを Base64 でエンコード
    var encodedAuth = Buffer.from(credentials.username + ':' + credentials.password).toString('base64');
    var expectedAuthHeader = 'Basic ' + encodedAuth;

    // クライアントIPが許可されているかを確認
    var isPermittedIp = IP_WHITE_LIST[clientIP] || false;
    console.log(isPermittedIp);

    if (isPermittedIp) {
        // Authorizationヘッダーの有無と認証情報をチェック
        if (headers.authorization && headers.authorization.value === expectedAuthHeader) {
            console.log("Authorization successful for IP:"+clientIP);
            return request;  // 認証成功
        } else {
            console.log("Authorization failed for IP:"+clientIP);
            // 認証失敗時に401レスポンスを返す
            return {
                statusCode: 401,
                statusDescription: 'Unauthorized',
                headers: {
                    'www-authenticate': { value: 'Basic realm="Enter credentials"' },
                },
            };
        }
    } else {
        // 許可されていないIPの場合403レスポンスを返す
        console.log("Forbidden access for IP:"+clientIP);
        return {
            statusCode: 403,
            statusDescription: 'Forbidden',
        };
    }
}
  • 想定外のIPアドレスからのアクセスが禁止されていることを確認するために、テスト画面にて以下の設定を行い、実行します。
    • URLパス:/management/index.html
    • IPアドレス:1.2.3.4
スクリーンショット 2024-11-20 15.18.43.png
  • テストを実行した結果、ステータスが403 ForbiddenとなっていればOKです。この結果により、IPアドレス1.2.3.4からのアクセスが適切に禁止されていることが確認できます。
スクリーンショット 2024-11-20 15.19.09.png
  • 次に、CloudFront Functionsに登録されているIPアドレスからのアクセスが許可されているかを確認するため、テスト画面にて以下の設定を行い、実行します。
    • URLパス:/management/index.html
    • IPアドレス:あなたの利用しているIPアドレス
スクリーンショット 2024-11-20 15.19.48.png
  • テストを実行した結果、ステータスが401 UnauthorizedとなっていればOKです!401 Unauthorizedエラーは、IPアドレスからのアクセスが許可された後に、Basic認証においてエラーとなっているだけです。つまり、このテスト結果から、ご利用のIPアドレスからのアクセスが許可されていることが確認できます。
スクリーンショット 2024-11-20 15.21.08.png
  • テストを実行した後、「関数を発行」をクリックすると、ディストリビューションに関連付けの設定画面が表示されるので、作成したディストリビューションのキャッシュビヘイビア/manager/*を関連付けることができます。
スクリーンショット 2024-11-20 15.30.44.png
  • 関連付けたあと、アクセスするとBasic認証を求められます。
スクリーンショット 2024-11-21 17.18.21.png
  • ユーザー名とパスワードを入力し、「Welcome manager」と表示されればOKです!
スクリーンショット 2024-11-21 9.57.44.png

まとめ

CloudFront FunctionsとLambda@Edgeの比較と実践を行いました!
これまでLambda@Edgeを利用して実装していたものをCloudFront Functionsに移行することも検討してみると良いかもしれません。
CloudFront Functionsの導入を検討されている方々にとって、少しでも参考になれば幸いです!

AUTHOR
tiga
tiga
記事URLをコピーしました