📙

AWS Cloudfrontについて

2024/07/05に公開

Cloudfrontとは

AWSのCDNサービスです。
https://aws.amazon.com/jp/cloudfront/

オリジンアクセス

S3を選択している場合

Public

S3バケットがインターネット経由で公開されている状態です。この設定を使用する場合、バケットの設定で「パブリックアクセスを許可」する必要があります。

Origin access control settings (recommended)

S3バケットへのアクセスをCloudFront経由のみに制限する機能です。この設定を用いると、バケットはインターネット経由で直接アクセスされることなく、CloudFrontを介したリクエストのみを許可します。

Legacy access identities

OAI(Origin Access Identity)を指します。これは、CloudFrontがS3のバケットに安全にアクセスするために使用される、より古い方式のアクセス方法です。

ビューワー

ビューワープロトコルポリシー

クライアント(ビューワー)がCloudFrontディストリビューションにアクセスする際に使用するプロトコル(HTTPまたはHTTPS)を制御します。

許可された HTTP メソッド

クライアントがCloudFrontディストリビューションに対して実行できるHTTPメソッドを指定します。

OPTIONSは通常、クロスオリジンリソース共有(CORS)で前もって通信を許可するかどうかを確認する際に使われます。

キャッシュキーとオリジンリクエスト

キャッシュキー

CloudFrontがWebページや画像などのコンテンツをキャッシュする際に使用する識別子です。このキーによって、CloudFrontは保存しているコンテンツを特定し、ユーザーのリクエストに応じて素早くコンテンツを提供できます。

例えば、あるユーザーがWebページをリクエストすると、CloudFrontはそのリクエストのURLを見て、キャッシュされたコンテンツの中から該当するものを探します。このURLがキャッシュキーの基本形です。

オリジンリクエスト

CloudFrontはコンテンツをキャッシュして高速に配信するサービスですが、リクエストされたコンテンツがキャッシュにない場合、またはキャッシュされているコンテンツが古くなっている場合(期限切れの場合)、CloudFrontは「オリジンサーバー」と呼ばれる元の場所(S3など)にリクエストを送り、新しいコンテンツを取得します。

これを「オリジンリクエスト」と呼びます。

例:AllViewerExceptHostHeaderを選択、ユーザーがブラウザから「 https://www.example.com/news 」へアクセスする場合

転送される情報: URLの「/news」部分、その他のヘッダー情報(ユーザーエージェント、クッキーなど)、可能性があればクエリパラメータ。
転送されない情報: 「Host: www.example.com」という部分です。これは、CDNやプロキシサーバーが自動的に管理するため、明示的にオリジンサーバーに送る必要がない情報です。

キャッシュ削除

アップロードするファイルを変更した際は必ずCloudFrontのキャッシュ削除を行うようにしてください。
https://blog.denet.co.jp/cloudfront_auto/

オブジェクトパスに/*(ワイルドカード)を使用すると、指定されたディレクトリ下の全てのファイルやサブディレクトリのキャッシュが削除されます。

AWS CLIでキャッシュを削除する

https://repost.aws/ja/knowledge-center/cloudfront-clear-cache

aws cloudfront create-invalidation --distribution-id <ディストリビューションのID> --paths "/*"

Basic認証

CloudFront Functionsを使ってBasic認証を実装します。

使用したいユーザー名とパスワード("ユーザー名:パスワード")をBase64エンコーディング形式に変換します。
出力された文字列をパスワードとして使用するので、コピーしておいてください。

echo -n "admin:password" | base64

関数の内容にしてください。

function handler(event) {
  var request = event.request;
  var headers = request.headers;

  var authString = "Basic 出力された文字列";

  if (
    typeof headers.authorization === "undefined" ||
    headers.authorization.value !== authString
  ) {
    return {
      statusCode: 401,
      statusDescription: "Unauthorized",
      headers: {
        "www-authenticate": { value: "Basic" } 
      }
    };
  }

  return request;
}

関数をデプロイするために、必ず発行を押してください。

関数の関連付けを行ってください。同一のトリガーポイントに複数の関数を設定することはできません。

Basic認証が適用されているか確認してください。

https://iret.media/95931

トリガーポイント

Viewer Request

ユーザーからのリクエストが CloudFront エッジに到達したとき。

Origin Request

CloudFrontがリクエストをオリジンサーバーへ転送する前。

Origin Response

オリジンサーバーから CloudFront へのレスポンスが返されたとき。

Viewer Response

CloudFront がユーザーへのレスポンスを返す前。

CloudFront Functions

関数の実行時間などが限られているため、簡単な処理に向いています。実行速度が非常に速く、料金が安いです。

Lambda@Edge

より複雑なデータ処理やAWSサービスとの連携が必要な場合に使用できますが、料金が高いです。
https://aws.amazon.com/jp/lambda/edge/

カスタムページの作成

特定のHTTPステータスコードを受け取ったときに表示するデフォルトのエラーページをカスタマイズすることができます。

S3バケット内のカスタムエラーページへのパスなどを入力してください。

This XML file does not appear to have any style information associated with it. The document tree is shown below.

CloudFrontで、下記のような表示が出る場合があります。

今回はNext.jsをS3にデプロイしている場合ですが、URLを直打ちすると表示されます。
https://ディストリビューションドメイン名 だと問題なく表示されますが、https://ディストリビューションドメイン名/news のようなURLを直打ちするとエラーが出ます。

直打ちではなく、ページ内のボタンからrouter.pushを使用してアクセスする場合は問題なく表示されると思います。これは、Next.js のサーバーサイドとクライアントサイドのルーティングの違いに起因します。

Next.js プロジェクトで直接 URL を入力してアクセスする場合と、ページ内のボタンから router.push を使用してアクセスする場合で挙動が異なる理由は、主に Next.js のサーバーサイドとクライアントサイドのルーティングの違いに起因します。

  • router.pushを使った場合
    これはクライアントサイドのナビゲーションです。
    Next.js はブラウザ上で既にロードされているJavaScriptを使用して、新しいページコンテンツを取得し、ページ遷移を行います。

  • ブラウザのアドレスバーにURLを直接入力してアクセスした場合
    このリクエストはサーバーサイドで処理されます。
    Next.jsではなく、S3およびCloudFrontの設定がリクエストを処理します。
    この場合、指定されたパスに対応する静的ファイル(HTML, JavaScript, CSS など)が存在しないと、404 エラーなどが発生します。

解決策

  • フォールバックページの設定
    CloudFrontでカスタムエラーページの設定(今回の場合は403)を行ってください。

The parameter FunctionAssociationArn is invalid; basic-authentication was not found or is not published.

指定した関数が見つからないか、まだ公開されていないことを示しています。

関数のステータスを確認して、デプロイ済みになっていることを確認してください。

The CloudFront function associated with the CloudFront distribution is invalid or could not run.

関連付けられているCloudFront functionが正しくない

終わりに

何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉

Discussion