WebサイトにCloudFront Functionを設定したら接続が503エラーとなったのでトラブルシュートしてみた

2021.07.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部の若槻です。

今回は、WebサイトにCloudFront Functionを設定したら接続が503エラーとなったのでトラブルシュートをした際の話です。

CloudFront Functionを設定したら503エラーが発生

前回のエントリでCloudFront + S3な構成の静的ウェブサイトにCloudFront Functionを設定しました。

その際にこのエントリ中では触れていませんでしたが、実装の検証をする中で設定前にはアクセスできていたWebサイトにCloudFront Functionを設定したら接続が503エラーとなる時がありました。

その時に使用したCloudFront Functionのコードは下記です。Lambda@Edgeでは同じコードで問題なく動いていました。

lambda/basic-authentication/index.js

exports.handler = (event) => {
  const request = event.request;
  const headers = request.headers;

  // echo -n user:pass | base64
  const authString = "Basic dXNlcjpwYXNz";

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

  return request;
}

上記をCDKデプロイして、Webサイトに接続すると下記のように503エラーが発生しました。

503 ERROR
The request could not be satisfied.

The CloudFront function associated with the CloudFront distribution is invalid or could not run. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.

Generated by cloudfront (CloudFront)
Request ID: SWBACG0l6Yl9xl5VDpRafMfdmjySTCaRLAxuCAA877pZvQ4Z1Gu8DY==

調査、原因

5XXエラーということはサーバー側で何かしらのエラーが発生しており、直前に設定したCloudFront Functionがほぼほぼ原因でしょう。しかしLambda@Edgeでは動いていたコードがなぜ?という気持ちです。

ということで調査のためにAWSコンソールから情報を確認してみます。まずCloudFront > Telemetry > Monitoring で[Functions]タブを開いてみると先ほど作成したFunctionがあったので選択して[View function metrics]をクリックしてみます。

すると通常のLambdaのページでも見られるようなメトリクスのダッシュボードが見られました。ページを下の方へスクロールすると、

[Execution Erros]で先ほど発生したと思わしきエラーも確認できました。

ページを上へ戻り、次は[View function logs]をクリックしてみます。

するとCloudWatch Logsのページが開くのですが、log groupが存在しない旨のエラーとなりました。

実行時に自動でlog groupが作成される通常のLambdaと異なり、CloudFront Functionは明示的にlog groupを作成する必要があるのでしょうか。(これについてはまたの機会にやってみます)

次にCloudFront > Functionsを開くと先ほど作成したFunctionがあるのでこちらも開いてみます。

Functionの設定をするためのコンソールが開けました。CDKで実装時は使用しませんでしたが、手動設定する場合はこちらから出来そうです。

[Test]タブからはコードのテストが出来そうです。[Test]をクリックしてみます。

すると実行がエラーとなりエラーメッセージが出力されました。

どうやらCloudFront Functionではconstが使えないようです。

Error Message: The CloudFront function associated with the CloudFront distribution is invalid or could not run. SyntaxError: Token "const" not supported in this version in 2

[Build]タブに戻りコードを編集してconstvarに変更してみます。[Save]で変更を保存します。

exports.handler = (event) => {
  var request = event.request;
  var headers = request.headers;

  // echo -n user:pass | base64
  var authString = "Basic dXNlcjpwYXNz";

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

  return request;
}

[Test]タブに戻り再度テストを実行するとまた実行エラーとなりました。

CloudFront Functionではexportsが使えないようです。

Error Message: The CloudFront function associated with the CloudFront distribution is invalid or could not run. ReferenceError: "exports" is not defined in 1

また[Build]タブに戻りコードを下記のようにexportsを使用しない記述に変更してみます。[Save]で変更を保存します。

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

もう一度テストを実行してみると今度は成功しました。ステータスが401となっておりちゃんとFunctionによるBasic認証の要求が働いているようです。

テストが成功したコードを使用してCDKデプロイし、Webサイトにアクセスしてみると次はちゃんとエラーなく動作しました。

おわりに

前回のエントリでのBufferと同様に、今回のconstexportsなど、Lambda@Edgeでは当たり前のように使えていたモジュールがCloidFront Functionでは使えないことにより遭遇したトラブルでした。というのもCloudFront Functionのランタイムは「ECMAScript 5.1 compliant」だからです。

最新のフルセットのNode.jsランタイムを使わないことにより、読み込むモジュールを軽量化してFunctionの実行の高速化を図っているのでしょうね。

参考

以上