🦔

Terraform を使って良い感じに Basic 認証できる CloudFront Functions を作成する

2022/07/12に公開
lib version
terraform 1.1.9
hashicorp/aws 4.22.0

terraform.tfvarsmap に好きなだけユーザーとパスワード突っ込んだら適当に Basic 認証できる CloudFront Functions 書き出してくれるのが欲しくてやってみたメモ。

# terraform.tfvars

# Basic 認証に設定するユーザーとパスワードを user = password で指定する。
# ココで必要なだけ指定する。
valid_users = {
  spam = "spamsoamspam",
  egg  = "eggeggegg",
  ham  = "hamhamham"
}
# main.tf

# terraform.tfvars で指定する
variable "valid_users" {
  type = map(string)
}

provider "aws" {
  # CloudFront まわりはヴァージニアリージョンで設定するので region で設定しておく。
  region = "us-east-1"
}

resource "aws_cloudfront_function" "basic_auth" {
  name    = "ExampleBasicAuth"
  runtime = "cloudfront-js-1.0"
  publish = true

  # valid_users で指定した値を javascript 側で使う形に整形して埋め込む。
  # 1. user と password を "user:password" の形に整形
  # 2. base64encode で base64 する
  # 3. "Basic xxxxxxx" の形に整形
  # 4. カンマで連結して一つの文字列にする
  # 5. javascriptの適当なところに差し込む
  code = format(file("basic_auth.js"), join(", ", [
    for u, p in var.valid_users : format("\"Basic %s\"", base64encode("${u}:${p}"))
  ]))
}
// basic_auth.js

function handler(event) {
  // ココに main.tf で整形した認証情報が以下のような形で差し込まれる。
  // [
  //  "Basic aaaaaa",
  //  "Basic bbbbbb",
  //  "Basic ccccc"
  // ]
  var validUsers = [%s]
  var request = event.request;
  var headers = request.headers;

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

terraform plan すれば最終的にどーゆー形で整形されて登録されるのかが確認できる。はず。

あとは terraform apply すれば CloudFront Functions に登録されるので、紐付けたい aws_cloudfront_distribution の default_cache_behaviorordered_cache_behaviorfunction_association に arn を設定してあげれば良い。

...
default_cache_behavior {
  ...
  function_association {
    # Basic 認証なので viewer-request を指定する
    event_type = "viewer-request"
    # ココで紐づける
    function_arn = aws_cloudfront_function.basic_auth.arn
  }
}

これをやってみるに当たって、以下のサイトを参考にさせていただきました。ありがとうございます!

毎度わたしは重箱の隅をつつくような内容ばかり :-P

Discussion