🌟

Google Cloud Identity Platformのテナント認証を無効にする方法と実装例

2024/09/13に公開

はじめに

以前、Google Cloud Identity Platform(以降Identity Platform)のマルチテナンシー構成におけるパスワードポリシーの設定と更新方法についての記事を書きました。
https://zenn.dev/rescuenow/articles/b5e43fbe44cba7

今回はテナント毎の認証を無効にする処理が必要となりましたのでその実装方法について紹介したいと思います。

Identity Platformやマルチテナンシーについては上記の記事で解説しましたので、そちらを参照してください。

テナント認証の無効化

テナントの認証はテナント作成時には有効になっています。
無効にすることで、テナントに属するユーザは認証ができなくなります。
再度有効にすることで、テナントに属するユーザは再び認証が可能となります。

コンソールでのテナント認証の無効化処理

以下のようにテナントの一覧にトグルがあり、これを切り替えることでテナントへの認証を無効にしたり有効に戻したりできます。

テナントの一覧

GoのSDKにおけるテナント認証の無効化処理

パスワードポリシーの記事でも触れましたが、
GoのSDKにはテナントの更新機能は存在していますが、更新対象が制限されています。

結論としてはSDKがないため、APIによるテナント更新処理を呼び出します。

以降では、実際にテナント認証の無効化をコード例踏まえて解説していきます。

APIを用いたテナント認証の無効化更新手順

手順と言えるほどでもないですが、下記のとおりです。

  1. アクセストークンを取得
  2. テナント更新のAPIを使用して認証無効の設定を更新
    • アクセストークンを指定して、REST APIのテナント更新

これはGoogle Cloudの他のAPIでも同様になります。

1. アクセストークンを取得

GCPでの認証方法は様々あり、どれを使うのが良いか迷うことがありますが、
ユースケースによって適した認証方法を選択するためのフローチャートがドキュメントとして用意されていますので、参考にするとよいでしょう。
https://cloud.google.com/docs/authentication?hl=ja

今回の場合、アクセストークンの取得はサービスアカウントを用いて行います。

2. テナント更新のAPIを使用して認証無効の設定を更新

以下がテナント更新APIの概要です。

項目 詳細
エンドポイント https://identitytoolkit.googleapis.com/v2/projects/プロジェクトID/tenants/テナントID
メソッド PATCH
クエリパラメータ updateMask: string (FieldMask format)
FieldMask FieldMaskの詳細
リクエストボディ Tenantのjson構造体
レスポンスボディ リクエストと同様のTenantのjson構造体

テナントの更新APIは更新したい値をボディに指定しますが、
それとは別に、updateMaskというキーのパラメータを指定する必要があります。
このパラメータは、FieldMaskという特別な形式であり、更新する値と対になっている必要があります。
簡単に言うと、更新対象を含むjsonをボディに指定し、FieldMaskではjson内で更新したい値を.で区切った階層表現で指定します。

FieldMaskについてはパスワードポリシーのブログで解説したので、割愛します。

テナント認証の無効化の設定パラメータはdisableAuthです。
trueで認証を無効に、falseで認証を有効にできます。

テナント更新API
https://cloud.google.com/identity-platform/docs/reference/rest/v2/projects.tenants/patch

Goでの実装

1. アクセストークンを取得

サービスアカウントを使用してGoogle Cloud APIに認証するためのアクセストークンを取得します。
このトークンは、APIリクエストの認証ヘッダーに含める必要があります。

func (t *Tenant) getToken(ctx context.Context, tenantID string) (string, error) {
    // 環境変数にサービスアカウントのcredentialsを保持しています。ファイルから読み込むのと同等
	jsonKey := []byte(os.Getenv("FIREBASE_CREDENTIALS_JSON"))
	// サービスアカウントを使用してアクセストークンを生成
	conf, err := google.CredentialsFromJSON(ctx, jsonKey, "https://www.googleapis.com/auth/cloud-platform")
	if err != nil {
		return "", err
	}

	token, err := conf.TokenSource.Token()
	if err != nil {
		return "", err
	}

	return token.AccessToken, err
}

テナント更新APIでは下記です。
https://cloud.google.com/identity-platform/docs/reference/rest/v2/projects.tenants/patch#authorization-scopes

2. テナント更新のAPIを使用して認証無効の設定を更新

パラメータとボディを整形して、HTTPリクエストを送信します。

// 引数として、更新対象のテナントIDと、先ほど生成したアクセストークンを受け取っています。
func (t *Tenant) updateTenant(tenantID, token string) error {
	projectID := os.Getenv("PROJECT_ID")
	// Identity Toolkit APIのURLを動的に構築
	url := fmt.Sprintf("https://identitytoolkit.googleapis.com/v2/projects/%s/tenants/%s?updateMask=disableAuth", projectID, tenantID)

    // リクエストボディの作成
	requestBody, err := json.Marshal(map[string]interface{}{
		"disableAuth": true,
	})
	if err != nil {
		return err
	}

	req, err := http.NewRequest(http.MethodPatch, url, bytes.NewBuffer(requestBody))
	if err != nil {
		return err
	}
	req.Header.Add("Authorization", "Bearer "+token)
	req.Header.Add("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	fmt.Printf("Response: %s\n", string(respBody))
	return nil
}

まとめ

Identity Platformの解説とマルチテナント構成でのテナント認証の無効化について解説しました。
前回紹介したパスワードポリシーの更新でベースとなる知識があったので、比較的簡単に実装できました。
コンソールで見た際の設定項目とAPIのパラメータ名のギャップがあり、該当するパラメータを探すのに手間取りました。

参考資料

https://cloud.google.com/docs/authentication?hl=ja
https://cloud.google.com/docs/authentication/use-service-account-impersonation?hl=ja

レスキューナウテックブログ

Discussion