Croud Runで作成したWEBアプリをIAPで認証させる方法
はじめに
Croud Runで作成したWEBアプリは認証機能を持っていないのでIAPを有効にして認証させたい、
そんなユースケースを作りたくて構築してみました。
※2022年10月現在、本機能はプレビュー版のようです。
手順もCloud Load BalancerやサーバーレスNEG(ネットワーク エンドポイント グループ)、OAuth2.0、IAPそしてCloud Runと多岐に渡っており、独自のドメインやSSL証明書も必要だったりして非常に複雑でした。
以下のサイトが良く纏まっていたので参考にしました。
前提条件・制限事項・準備するもの
- 外部HTTP(S)ロードバランサーに設定するSSL証明書のため独自ドメインとDNSのレコード設定が必要です。
- 443通信である必要があります。
- すべての外部リクエストは IAP 経由で承認される必要があります。
システム構成
以下のような構成で構築します。
必要な作業
必要な作業は主に以下の4つです。
- Cloud Runサービスのデプロイ
- IAP の設定
- 外部ロードバランサーの設定
- 許可したいユーザアカウントをIAPに追加
① Cloud Run サービスのデプロイ
コンソールにログインした状態でCloud Runのページを開き、Cloud Run サービスを作成します。
今回はサンプルのWEBアプリケーションをデプロイするので、以下のように設定します。
-
「既存のコンテナ イメージから 1 つのリビジョンをデプロイする」には「us-docker.pkg.dev/cloudrun/container/hello」を指定します。
-
サービス名は自動で「hello」になります。← 記憶しておいてください。
-
リージョンはどこでも構いませんが、今回の設定は「us-central1」とし、これを覚えておきます。
-
Ingressの設定で「内部トラフィックと Cloud Load Balancing からのトラフィックを許可する」にチェックを入れます。
-
認証の設定では「認証が必要」にチェックを入れて作成ボタンを押します。
これでCloud Runによるサンプルアプリ「hello」が作成されました。
② IAPの設定
- OAuth 同意画面の設定
Cloud コンソールから 「APIとサービス」→ 「OAuth 同意画面」を開きます。
未設定の場合は以下のように設定してください。
「アプリ名」および「ユーザーサポートメール 」(アドレス)を入力します。ここにはアプリケーションの名前(任意)とユーザー自身の受信可能なメールアドレスか、Googleグループのアドレスを入力してください。
「デベロッパーの連絡先情報」にメールアドレスを入力します。
一度「保存して次へ」ボタンを押し、設定を保存して元の「OAuth同意画面の設定」画面に戻ります。
「公開ステータス」を今回は「テスト」にします。
「ユーザーの種類」を「外部」にします。
「テストユーザー」の「ADD USERS」ボタンをクリックし、OAuth2.0で認証させる(Cloud RunのWEBアプリにアクセスする)対象のユーザーアカウントを設定します。
- OAuthの認証情報(クライアントIDとシークレット)の設定
Cloud コンソールから 「APIとサービス」→ 「認証情報」を開きます。
画面上部「認証情報を作成」をクリックし「OAuthクライアントID」を選択します。
画面が遷移したら、「アプリケーションの種類」にて「ウェブアプリケーション」を選択します。「作成」をクリックすると、画面にクライアントIDとクライアントシークレットが生成され表示されます。OKを押してください。
作成したOAuth 2.0 クライアント ID をクリックすると、クライアントIDとクライアントシークレットが表示されるので、ここで確認することもできます。
- 「承認済みのリダイレクト URI」に以下のフォーマットのリダイレクトURIを設定してください
https://iap.googleapis.com/v1/oauth/clientIds/CLIENT_ID:handleRedirect
クライアントIDは以下のようなフォーマットです。
75641163784-some-random-number.apps.googleusercontent.com
「保存」をクリックします。以上でOAuth2.0の設定および認証情報の設定は完了です。
③ 外部ロードバランサーの設定
Cloud Runサービスがデプロイされ、IAPが有効になると、次のステップではNEG(Network Endpoint Group)を作成することになります。ネットワークエンドポイントグループ(NEG)は、バックエンドエンドポイントまたはサービスのグループを指定する設定オブジェクトです。完全なドキュメントはこちらで読むことができます。 ネットワークエンドポイントグループの概要
ここからは外部ロードバランサーの設定を、主にCloud Shellからgcloudコマンドを使って行っていきます。
まずはいくつか事前に変数を設定しておきます。
PROJECT_ID=[YOUR_PROJECT_ID]
REGION=[REGION_OF_CLOUD_RUN_DEPLOYED] <= (今回はus-central1)
CLIENT_ID=[YOUR_CLIENT_ID]
CLIENT_SECRET=[YOUR_CLIENT_ID]
CLOUD_RUN_SERVICE=[YOUR_CLOUD_RUN_SERVICE] <=(今回はhello)
- NEGを作成
gcloud compute network-endpoint-groups create cloud-run-iap-neg \
--project $PROJECT_ID \
--region=$REGION \
--network-endpoint-type=serverless \
--cloud-run-service=$CLOUD_RUN_SERVICE
- バックエンドサービスを作成
gcloud compute backend-services create cloud-run-iap-backend \
--load-balancing-scheme=EXTERNAL \
--global \
--iap=enabled,oauth2-client-id=$CLIENT_ID,oauth2-client-secret=$CLIENT_SECRET
- バックエンドサービスにバックエンドとしてサーバーレスNEGを追加
gcloud compute backend-services add-backend cloud-run-iap-backend \
--global \
--network-endpoint-group=cloud-run-iap-neg \
--network-endpoint-group-region=$REGION
- url mapsを作成
gcloud compute url-maps create cloud-run-iap-url-map \
--default-service cloud-run-iap-backend
- 固定IPアドレスを予約します。
gcloud compute addresses create cloud-run-iap-ip \
--network-tier=PREMIUM \
--ip-version=IPV4 \
--global
gcloud compute addresses list --filter cloud-run-iap-ip
次の変数をあなたのオリジナルのドメイン名で更新してください。例:test.example.com
DOMAIN_ADDRESS=[your-domain-address] <= 所有しているドメイン名を設定
- 上記手順で取得した固定IPアドレスをDNSのAレコードに登録し、インターネット上でtest.example.com を名前解決した時に取得した固定IPアドレスが返ってくるように設定します。
- SSL証明書の作成
ここまでの手順でフロントエンド以外のロードバランサーの設定が済んでいるので、Cloudコンソールの「ネットワークサービス」→ 「ロードバランシング」の画面には「cloud-run-iap-url-map」という名前でロードバランサーができているはずです。(見えない場合は画面を一度リロードしてください)
ロードバランサーをクリックし、画面上部の「編集」をクリックしてください。
「フロントエンドの構成」をクリックすると、設定画面が開きますが、「プロトコル」の部分を「HTTPS (HTTPS/2を含む)」に選択すると、既存のSSLの証明書を選択するか、もしくは「新しい証明書を作成」という選択肢が表示されるので、「新しい証明書を作成」をクリックします。以下の画面が表示されます。
今回、証明書の名前は以降のgcloudコマンドで指定するため「cloud-run-iap-cert」としています。
「Google マネージドの証明書を作成する」にチェックを入れます。
「ドメイン」には独自のドメイン名を入力します。
「作成」をクリックするとGoogle マネージドのSSL証明書が作成されます。
- https proxyを作成
gcloud compute target-https-proxies create cloud-run-iap-http-proxy \
--ssl-certificates cloud-run-iap-cert \
--url-map cloud-run-iap-url-map
- グローバルな転送ルールを作成(フロントエンドの作成)
gcloud compute forwarding-rules create cloud-run-iap-forwarding-rule \
--load-balancing-scheme=EXTERNAL \
--network-tier=PREMIUM \
--address=cloud-run-iap-ip \
--global \
--ports 443 \
--target-https-proxy cloud-run-iap-http-proxy
SSL証明書の状態がプロビジョニングとなり、アクティブになるまで30分~1時間(最大24時間)ほど掛かります。以下のような状態になるまで待ちます。
- IAPの動作確認
ここまでくれば9割完了です。ロードバランサーがすべてのコンポーネントをセットアップするまで少し時間をおいてから、期待通りに動作するかテストしてください。
https://独自ドメイン にアクセスすると、google のログインページ(OAuth2.0)にリダイレクトされるはずです。
ログインすると、以下のようなエラーになるはずです。
このエラーはIAPの認証に拒否されたということなので動作として正しいです。
④ 許可したいユーザアカウントを追加
バックエンド・サービスにユーザーを追加する必要があります。許可したいユーザーアカウントをIAPの画面から追加しましょう。
-
Cloud コンソールから「セキュリティ」→ 「Identity-Aware Proxy」にアクセスします。
既に「cloud-run-iap-backend」という名前のバックエンドサービスのIAPが有効になり、「OK」のステータスになっているはずです。
-
画面右ペインにあるペインから「プリンシパルを追加」のボタンをクリックします。
-
アクセス許可したいユーザアカウントを追加し、ロールに「IAP-secured Web App User」を付与して、「保存」をクリックします。
- 設定したドメインURLにて再度ログインできることを確認
少し待ってから、ページを更新してください。以下のようなログイン画面が表示されるはずです。
403 Forbidden "Your client does not have permission to get URL / from this server."というエラーについて
なぜCloud Runのパーミッションを使わず、IAPに認証ユーザーを追加するだけなのか言うと、答えはこうなるからです。
Cloud Runのパーミッションはログインへのリダイレクトを処理せず、ユーザーが必要なパーミッションを持っていない場合、連絡先情報を含む素敵なページを表示しません。笑
設定の削除
# delete the forwarding-rule aka frontend
gcloud -q compute forwarding-rules delete cloud-run-iap-forwarding-rule --global
# delete the http proxy
gcloud -q compute target-https-proxies delete cloud-run-iap-http-proxy
# delete the url map
gcloud -q compute url-maps delete cloud-run-iap-url-map
# delete the backend
gcloud -q compute backend-services delete cloud-run-iap-backend --global
# delete the NEG
gcloud -q compute network-endpoint-groups delete cloud-run-iap-neg --region=$REGION
# delete the ssl certificate
gcloud -q compute ssl-certificates delete cloud-run-iap-cert
# delete the ip address
gcloud -q compute addresses delete cloud-run-iap-ip --global
# delete the cloud run service
gcloud -q run services delete cloud-run-iap --region $REGION
最後に
Cloud RunとIAPを組み合わせることで、最高のセキュリティで保護されたフルマネージドサーバーレスプラットフォームの恩恵を受けることができます。
Discussion