【CloudFront】Basic認証を実装したい
CloudFront に Basic 認証をかけたーーい!
ということで、
S3 がオリジンの CloudFront で公開している WEB アプリに Basic 認証をかけます。
Terraformを使って設定していきます
・バージョン
$ terraform providers -version
Terraform v1.4.2
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v4.67.0
実装方針
上記を見ると、CloudFront Functions で簡単に実装できるみたいです。
CloudFront Functions とは?
まずは、デフォルトディレクトリインデックスの実装に必要なCloudFront Functionsについて。
特定のイベントタイプに対して、事前に定義している JavaScript の関数を実行できる機能のこと。
イベントタイプには2種類あり、
- ビューワーリクエスト:ビューワーからリクエストを受信したとき
- ビューワーレスポンス:ビューワーにレスポンスを返す前
リクエスト(レスポンス)ヘッダーの操作やリダイレクト処理などを実現できます。
公式ドキュメントは ↓ です。目を通してみるといいと思います
CloudFront Functions の料金
公式サイトより、
100 万件の呼び出しあたり 0.10 USD です (1 回の呼び出しごとに 0.0000001 USD)。
また、無料枠として
各月 2,000,000 件の CloudFront Function 呼び出し
が設けられています。
実装
事前準備
Basic 認証では、
ブラウザから、ユーザ名とパスワードをコロン ":" でつなぎ Base64 でエンコードして送信します。
Cloudfront Fuctions で送信された文字列(認証情報)が正しいか判断します。
そのため、Base64 でエンコードされた文字列を用意しておき、JavaScript 内で判定する際に使用します。
今回は、
ユーザ名:hisui
パスワード:hisuipw
具体的には下記コマンドでエンコードされた文字列を用意します
$ echo -n "hisui:hisuipw" | base64
aGlzdWk6aGlzdWlwdw==
この文字列を次の Cloudfront Fuctions で使用します
CloudFront Functions
CloudFront Functions で実行する関数はこちらのコードをそのまま使います
js ファイルを作成し、tf ファイルから参照するようにします。
function handler(event) {
var request = event.request;
var headers = request.headers;
// echo -n user:pass | base64
var authString = "Basic aGlzdWk6aGlzdWlwdw==";
if (
typeof headers.authorization === "undefined" ||
headers.authorization.value !== authString
) {
return {
statusCode: 401,
statusDescription: "Unauthorized",
headers: { "www-authenticate": { value: "Basic" } },
};
}
return request;
}
authString にユーザー名, パスワードを base64 でエンコードしたものを指定し、
認証情報を送信していないもしくは、誤った認証情報を送信しているときに 401 を返します。
ヘッダーの"www-authenticate" に"Basic"を指定し、Basic 認証を使うとブラウザに伝えます
つまり、
認証情報を送信していない初めのリクエストに対して 401 と Basic 認証を使うことを伝えます。
2回目以降は送られてきた認証情報を判定し、
・あっている場合は、認証を通し、
・空欄もしくは間違っている場合は再度 Basic 認証でユーザー名とパスワードをききます
詳しく知りたい方は下記 2 つをご覧ください
Terraform
resource "aws_cloudfront_distribution" "main" {
...
default_cache_behavior {
...
# CloudFront Functionsの紐づけ
function_association {
event_type = "viewer-request"
function_arn = aws_cloudfront_function.main.arn
}
}
...
}
...
# CloudFront Functions
resource "aws_cloudfront_function" "main" {
name = "function"
runtime = "cloudfront-js-1.0"
comment = "Basic認証"
publish = true
code = file("./CloudFront_Functions/function.js")
}
aws_cloudfront_distribution > default_cache_behavior ブロック内で CloudFront Functions を紐づけていきます
プロパティ | 説明 |
---|---|
event_type | どのイベントタイプで実行するか viewer-request に対して関数を実行します |
function_arn | 後ほど定義する CloudFront Functions の ARN を指定します |
aws_cloudfront_function にて、CloudFront Functions を定義します。
プロパティ | 説明 |
---|---|
name | CloudFront Functions の名前 |
runtime | ランタイム。2023/07 現在、cloudfront-js-1.0 のみ指定可能 |
comment | コメント。 |
publish | 関数をデプロイするかどうか。デフォルトは true。 テストなどをしたい方はデプロイしない(false) ことも可能。 |
code | 関数のソースコード。先ほど作成した js ファイルを相対パスで指定。 |
plan , apply
$ terraform plan
$ terraform apply -auto-approve
ダウンタイムはなかったと思います。。。
動作確認
CloudFront のドメインにアクセスして、下記のように Basic 認証が表示されます。
ここで、
ユーザ名:hisui
パスワード:hisuipw
を入力し、認証できれば OK です!
参考記事
Discussion