gcloud CLI から Directory API (とくに users )を操作する方法が分からなかったのでソースコードを眺めた
「gcloud CLI から Directory API (とくに users API) をたたく方法」が分からなかったので、ソースコードを眺めて処理を追ってみた備忘録。結論としては結局やっぱりよく分からなかったが、できなさそう。
gcloud CLI には identity サブコマンドがあるが、そのサブコマンドには実は groups しかない。
gcloud identity groups
identity のサブコマンドの ヘルプからもこれから意図された設計であることが分かる。
$ gcloud identity --help | head -3
NAME
gcloud identity - manage Cloud Identity Groups and Memberships resources
ということで、そもそも gcloud CLI から直接的に Cloud Identity の User 操作する方法はないと思われる。 Cloud Identity は Google Cloud のサービスではないと思う(あってる?)ので、むしろ groups が操作できるのが異端なのかもしれない。
というわけで gcloud auth print-access-token
コマンドを使って Directory API の Users を操作できるアクセストークンを発行できないか、というふうに実現方法を変えた。できたところでたぶん実際には使わないんだけど興味本位。
例えば各言語の SDK だとこの方法が提供されていて、例えば Python だと
delegated_credentials = credentials.with_subject('*****@*****.jp')
のような感じで(DWD が適切に設定されている前提で)、 GCP ではなく Cloud Identity 側で権限のあるユーザアカウントのメールアドレスを oatuh の sub に指定することでそのユーザとして Deligation されることができる。
Javascript の SDK のほうが クレームで sub を追加する操作がよりわかりやすい。
const auth = new JWT({subject: "*****@*****.jp"});
というわけで、これと同様のことを gcloud auth print-access-token で実行する方法があるのか、という話になる。
例えば brew で入れた gcloud CLI の場合、コマンドの実体は単なる shell script
$ command -v gcloud
/opt/homebrew/bin//gcloud
$ head -4 /opt/homebrew/bin//gcloud
#!/bin/sh
#
# Copyright 2013 Google Inc. All Rights Reserved.
#
gcloud shell script はソースコードでいうとこれ(※ 謎のミラーリポジトリしか見つからなかったんだけど本家はどこですか?)。ib/gcloud.py
を実行しているだけ(L182)。
ここで大きな問題に気付く。自分は Python をそんなに使ったことがない。いったん無視して進みます。
ib/gcloud.py
これもエラーハンドリングや path の調整をしているだけで、最終的に SDK 本体の gcloud_main.py
を呼んでいる(L128)。
lib/googlecloudsdk/gcloud_main.py
これも必要なサブコマンドのモジュールを取ってきて gcloud オブジェクトを作るかロードしてきてるだけ。
各サブコマンドのモジュールは lib/surface フォルダでサブフォルダに配置されている。
lib/surface
フォルダ
ここに確かにさっきの identity
サブコマンドのフォルダがあって、その中に groups
しかないのも確認できる。
gcloud auth print-access-token
が見たいので、たどると該当のモジュール はこれ。
lib/surface/auth/print_access_token.py
トークンを取り出す処理を見ると、クリデンシャルのオブジェクトの token あるいは acess_token プロパティに保持していることがわかる(2種類あるのは oauth2client と google-auth の両方のライブラリのオブジェクトをサポートしているため。前者は既に非推奨。)
クリデンシャルを作っているのが L122 や L157 のあたりで、 store という、キャッシュを兼ねてクリデンシャルの作成をしているコードが呼ばれている。L32 で Import されている。
また lib/surface/auth/print_access_token.py クラスを見ると、
class FakeCredentials(object):
"""An access token container.
oauth2client and google-auth are both supported by gcloud as the auth library.
credentials in oauth2client store the access token in the "access_token"
filed. google-auth stores it in the "token" filed. We use this fake
credentials class to unify them.
"""
という感じで oauth2client
と google-auth
という2つの OAuth ライブラリがあることが書かれている。前者は既に古く非推奨になっている。
lib/googlecloudsdk/core/credentials/store.py
このコードがやや長いけど、基本的にクリデンシャルのライフサイクル管理を全体的にやっているっぽい。
id_token の取得の処理はここにあるが、 access_token は隣の creds.py
でやってる。
lib/googlecloudsdk/core/credentials/creds.py
ここで、 OAuth の処理は print_access_token.py
でも触れた2種類のライブラリを使っている。
oauth2client
google-auth
前者の oauth2client のほう。
oauth2client/service_account.py
のほうでは create_with_claims
という自由に claim を足してクリデンシャルを作る目的の関数がある。隣の create_delegated
という関数は単に sub
claim を設定する形で create_with_claims
を呼び出している。このあたりの関数を呼べば sub
を設定できるっぽいが、検索してもリポジトリの中で使われている気配はない。
後者の google-auth のほう。with_subject
関数が sub
claim を設定するのに使える。
全体的に OAuth 2.0 Token Exchange を行っている?
Next
気が向いたらもっと読んで更新します。
Discussion