1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

それぞれの概要と違い

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

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

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

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

料金の例

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

項目 CloudFront Functions Lambda@Edge
1 か月のコンピューティング料金 なし 1000,000 × 0.00000625125 USD
= 6.3 USD
1 か月のリクエスト料金 100 万回あたり 0.1 USD 100万件あたり 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
index.html
<!DOCTYPE html>
<html lang="ja">
<h1>Welcome</h1>
</html>
management/index.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への移行が必要になります。

  • コンピューティング使用率の値:
    • 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の導入を検討されている方々にとって、少しでも参考になれば幸いです!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?