🦔

CloudFront Functions で特定の URL へのリクエストのみに Basic 認証を設定する with Terraform

2022/10/15に公開

はじめに

CloudFront + S3 でホスティングしている Web ページに対し、特定の URL のみに Basic 認証を設定する必要がありました。そのときに対応した内容を備忘録的にまとめておこうと思います。

Basic 認証用の関数を作成する

まずは Basic 認証用の関数を作成していきます。
現時点では全ての URL に対して Basic 認証が設定されます。

src/cloud_functions/basic_auth.js
function handler(event) {
  var request = event.request;
  var headers = request.headers;

  // echo -n ユーザー名:パスワード | base64
  var authString = "Basic aG9nZTpwYXNzd29yZA";

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

  return request;
}

CloudFront Functions のリソースを作成する

使用するリソースは下記です。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_function

先ほど作成した Basic 認証用の関数を設定します。

resource "aws_cloudfront_function" "sample-basic-auth-function" {
  name    = "sample-basic-auth"
  runtime = "cloudfront-js-1.0"
  comment = "Basic認証"
  publish = true 
  code    = file("./src/cloud_functions/basic_auth.js")
}

特定のURLのみに Basic 認証を設定する

本題の「特定の URL のみに Basic 認証を設定」の対応をしていきます。
これを実現するにはどの URL に対してのリクエストかを知る必要があるので、
CloudFront Functions のドキュメントを見ていきます。

CloudFront Functions の関数は event オブジェクトを引数に取ります。
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/functions-event-structure.html

event オブジェクトは request オブジェクトを持っており、その request オブジェクトは uri を持っているのでこれを見れば判定できそうです。
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/functions-event-structure.html#:~:text=IP アドレスです。-,リクエストオブジェクト,-request オブジェクトに

src/cloud_functions/basic_auth.js
function handler(event) {
  var request = event.request;
  var headers = request.headers;
+ var uri = request.uri;

+ // URL に hoge/ が含まれている場合のみ Basic 認証を設定する。それ以外の場合は何もしない。
+ if (!uri.includes('hoge/')) {
+   return request;
+ }

  // echo -n ユーザー名:パスワード | base64
  var authString = "Basic c3Bwb3g6Z1Q3Zjd2NXB5NQ==";

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

  return request;
}

以上で特定の URL のみに Basic 認証を設定できました🎉

参考

下記の記事を参考にさせていただきました🙏

https://dev.classmethod.jp/articles/cloudfront-functions-per-env-terraform/

Discussion