Google Cloud StorageでBasic認証付きでWeb公開(サービス拡張プラグイン編)
はじめに

Google Cloudの「サービス拡張」プラグインを使用して、Cloud Storageに配置した静的WebサイトにBasic認証を実装します。
前回の記事「Rust × WebAssembly(Wasm) × Edge処理 Google Cloudで「サービス拡張」を試してみた」で紹介した内容を、より実用的な形に発展させました。
これまでGoogle Cloudで静的WebサイトにBasic認証をかける方法をいくつか紹介してきましたが、本記事の方法がもっともオススメです。
概要
Google Cloudのロードバランサーを使用して静的Webサイトを公開している環境を前提として、サービス拡張プラグインを追加してBasic認証を実装します。
Basic認証プラグインを2つに分割する理由
Basic認証の実装を「Basic認証を要求するプラグイン」と「Basic認証の検証と認証ヘッダーを削除するプラグイン」の2つに分けて構成します。
この記事を必要とされている方の多くは、Cloud Storageに静的Webサイトを配置していると思いますが、Cloud StorageはBasic認証ヘッダー付きのアクセスに対応していません。
プラグインを1つだけにした場合、ブラウザでBasic認証のページを閲覧中にサーバー側でBasic認証機能を解除しても、ブラウザを再起動するまでBasic認証ヘッダー付きでアクセスし続けるため、Cloud Storageにアクセスできなくなり、ページが表示できなくなります。
そのため、公開時には「Basic認証を要求するプラグイン」のみを無効化し、「Basic認証の検証と認証ヘッダーを削除するプラグイン」は有効のままにします。
これにより、Cloud StorageへのアクセスからBasic認証ヘッダーが削除され、問題なくページを表示できるようになります。
実装の流れ
- プラグインのアップ先となる、Artifact Registry作成とサービスの有効化
- プラグインをビルドしてArtifact Registryにアップロードする
- サービス拡張プラグインを登録する
- ロードバランサーにサービス拡張プラグインを設定する
プラグインの実装
Google CloudのConsoleで作業を行います。
コンソールのヘッダー右上からCloud Shellを起動します。

Cloud Shellが起動したら、以下の手順でプラグインを実装します。
1. プラグインのアップ先となる、Artifact Registry作成とサービスの有効化
サービス拡張プラグインのアップロード先として、Artifact Registryを作成します。
まず、Artifact RegistryとNetwork Services APIが有効になっていない場合は、有効化しておきます。
# Artifact Registryの有効化(一度だけ実行)
gcloud services enable artifactregistry.googleapis.com
# Network Services APIの有効化(一度だけ実行)
gcloud services enable networkservices.googleapis.com
次に、プラグインの保存場所として、Docker用のArtifact Registryリポジトリを作成します。
gcloud artifacts repositories create service-extensions-wasm-plugin-docker \
--repository-format=docker \
--location=asia \
--project=${GOOGLE_CLOUD_PROJECT} \
--description="サービス拡張プラグイン" \
--async
これらの設定は一度だけ実行すればOKです。
2. プラグインをビルドしてArtifact Registryにアップロードする
サービスプラグインのソースコードをGitHubに公開しています。
GitHubからCloud Shellにクローンして使用してください。
git clone https://github.com/ToMGitHubN/google-cloud-service-extensions-plugins.git
cd google-cloud-service-extensions-plugins
プラグインのビルドとアップロード
クローンしたリポジトリ内のyamlファイルにビルド設定を記述しています。
Cloud Buildを使用してビルドとArtifact Registryへのアップロードを実行します。
Artifact Registryリポジトリ名を別の名前で作成した場合は、cloudbuild.yamlを適宜修正してください。
# Basic認証を要求するプラグインのビルド
gcloud builds submit --config=basic_auth_header_response_docker/cloudbuild.yaml ./basic_auth_header_response_docker
# Basic認証の検証と認証ヘッダーを削除するプラグインのビルド
gcloud builds submit --config=remove_auth_headers_docker/cloudbuild.yaml ./remove_auth_headers_docker
3. サービス拡張プラグインを登録する
アップロードしたプラグインをサービス拡張プラグインとして登録します。
ここからは、Google Cloud Consoleでの作業になります。

ロードバランサーのページに移動し、「サービス拡張」タブをクリックします。

「サービス拡張プラグインを作成」をクリックします。
「Basic認証を要求するプラグイン」を作成
まず、「Basic認証を要求するプラグイン」を作成します。
名前にbasic-auth-header-responseと入力します。
イメージURLには、先ほどビルドしてArtifact Registryにアップロードしたイメージを指定します。
複数のバージョンがある場合は、最新版(latest)を指定してください。
# ${GOOGLE_CLOUD_PROJECT}には自分のプロジェクトIDが入ります
asia-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/service-extensions-wasm-plugin-docker/basic-auth-header-response

「プラグイン作成」をクリックしてプラグインを作成します。
「Basic認証の検証と認証ヘッダーを削除するプラグイン」を作成
同様に、今度は「Basic認証の検証と認証ヘッダーを削除するプラグイン」を作成します。
名前にremove-auth-headersと入力します。
# ${GOOGLE_CLOUD_PROJECT}には自分のプロジェクトIDが入ります
asia-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/service-extensions-wasm-plugin-docker/remove_auth_headers

「プラグイン作成」をクリックしてプラグインを作成します。
4. ロードバランサーにサービス拡張プラグインを設定する
ロードバランサーにサービス拡張プラグインを設定して、Basic認証を有効化します。
「拡張機能」タブに移動し、「拡張機能を作成」をクリックします。

対象のロードバランサーを選択し、拡張の種類は「エッジ拡張」を選択します。

サービス拡張の「チェーン」と「一致条件」について
サービス拡張機能では、複数の「チェーン」を登録できます。
サービス拡張機能の適用条件は「一致条件」で設定します。
上から順番に「一致条件」が評価され、最初に一致したチェーンが実行されます。
最初に条件を満たしたチェーンが実行されると、以降のチェーンは評価されません。
本記事では、「Basic認証を要求するプラグイン」と「認証ヘッダーを削除するプラグイン」の2つの「チェーン」を登録します。
登録順は、「認証ヘッダーを削除するプラグイン」を先に登録し、次に「Basic認証を要求するプラグイン」を登録します。
「認証ヘッダーを削除するプラグイン」の「一致条件」は、ヘッダーにBasic認証がある場合に実行されるように設定します。
Basic認証ヘッダーがある場合は、「認証ヘッダーを削除するプラグイン」が実行された後、通常の通信が行われます。
Basic認証ヘッダーがない場合は、次のチェーンである「Basic認証を要求するプラグイン」が実行され、Basic認証の入力を要求するレスポンスを返します。
「一致条件」にBasic認証の情報を設定することで、プログラムを書き換えることなくBasic認証のID/パスワードを変更できるようになります。
また、Basic認証を無効化したい場合も、「Basic認証を要求するプラグイン」を無効化するだけで済みます。
設定を行う
それでは、具体的な設定を行います。
「名前」には、わかりやすい名前を付けてください。
ここでは、開発環境用としてbasic-auth-extension-devとしました。
「転送ルール」には、設定対象のロードバランサーを選択します。
認証ヘッダーを削除するプラグインの設定
拡張機能チェーンの名前はextension-chain-remove-auth-headersとしました。
ここで重要なのは一致条件の設定です。
一致条件には、Basic認証のAuthorizationヘッダーを設定します。
まず、Basic認証に設定したいID/パスワードをBase64エンコードします。
Cloud Shellで以下のコマンドを実行してください。"user"と"password"を設定したいID/パスワードに変更してください。
# "user:password"を任意のID:パスワードに変更してください
echo -n "user:password" | base64
# 出力例: "dXNlcjpwYXNzd29yZA=="
一致条件のヘッダーには、以下の形式で設定します。
request.headers["Authorization"] == "Basic (ここにBase64エンコードした文字列を入れる)"
上記の例("user:password")の場合は、以下のようになります。
request.headers["Authorization"] == "Basic dXNlcjpwYXNzd29yZA=="
ここまで設定すると、以下のようになります

次に、プラグインを登録します。
名前はextension-remove-auth-headerとしました。
プラグインは、認証ヘッダーを削除するプラグイン「remove-auth-headers」を設定します。
イベントは、「リクエスト ヘッダー」を選択します。

設定が完了したら、「拡張機能チェーンを追加」をクリックして、次のチェーンを追加します。
Basic認証を要求するプラグインの設定
拡張機能チェーンの名前はextension-chain-basic-auth-header-responseとしました。
一致条件は、すべてのリクエストにBasic認証を設定するには、true(すべてヒット)と設定します。
もし、/api/や/static/などの特定のパス以下にBasic認証をかけたくない場合は、以下のように設定することもできます。
request.path.startsWith("/api") == false && request.path.startsWith("/static") == false
次に、プラグインを登録します。
名前はextension-basic-auth-header-responseとしました。
プラグインは、Basic認証を要求するプラグイン「basic-auth-header-response」を設定します。
イベントは、「リクエスト ヘッダー」を選択します。
すべての設定が完了したら、「拡張機能を作成」をクリックして拡張機能を作成します。
作成には数分かかります。
作成完了の表示後も、実際に反映されるまでさらに数分かかることに注意してください。
(AWSのCloudFrontの設定変更と似ています)
(番外編) Basic認証の無効化方法
サービス拡張の「編集」を開きます。
「Basic認証を要求するプラグイン」のチェーンを削除することで、Basic認証を無効化できます。

反映には数分かかります。
まとめ
以上で、Google Cloud Storageでホスティングしている静的WebサイトにBasic認証を実装できました。
サービス拡張プラグインを使用することで、柔軟かつ簡単にBasic認証の有効化/無効化が可能になります。
以上です。お疲れ様でした。
Discussion