2022/05/21

GoでGCPプロジェクト管理者を識別する

動機

GCPで動作するアプリケーションを作っていると、アプリケーションの管理者=プロジェクトの管理者 であることが多いと思います。開発フェーズか運用フェーズかでそこに割り当てられている人は変わったとしても、この関係は変わりないのが理想と思います。

であれば、プログラムでプロジェクト管理者のアカウントを判断できれば、「アプリケーション管理者のアカウント」をアプリケーションで保持する必要ながなくなって便利です。


プロジェクト管理者のアカウントをコードで取得する手段を探してみたところ、Goで発見しましたので紹介します。


コード

サービスの名称と機能からIdentity and Access Managementあたりかと あたりをつけて探し始めて、たどり着いたのはResource Managerでした。プロジェクト管理者のアカウントを取得するには、以下の様に複数のAPIを経由します。

import ( "context" "os" "strings" "google.golang.org/api/cloudresourcemanager/v1" ) ... // context.Contextを取得 context := context.Background() // Cloud Resource Managerサービスを取得 crmservice, err := cloudresourcemanager.NewService(context) // (1)Resource Managerサービスを取得 if err != nil { // エラー処理 return } // プロジェクトのIAMポリシーを取得 projid := os.Getenv("GOOGLE_CLOUD_PROJECT") // (2)プロジェクトIDを取得 request := new(cloudresourcemanager.GetIamPolicyRequest) iampolicy, err := crmservice.Projects.GetIamPolicy(projid, request).Do() // (3)IAMポリシーを取得 if err != nil { // エラー処理 return } // このプロジェクトの管理者に含まれているか確認 adminuser := false check_end: for _, binding := range iampolicy.Bindings { // (4)各ポリシー for _, member := range binding.Members { // (5)各メンバ if strings.Contains(member, email) { // (6)Eメールアドレスで判断 adminuser = true break check_end } } } // adminuser == tureならプロジェクト管理者

  1.  Cloud Resource Managerサービスを取得します。
  2.  環境変数GOOGLE_CLOUD_PROJECTからプロジェクトIDを取得しています。Cloud Run/Goではこれで取得できましたが、その他のサービスでは同様に取得できるか分かりませんので、確認してください。
  3. プロジェクトのIdentity and Access Managerポリシーを取得します。メソッドチェインの最後のDo()メソッドが実行結果としてPolicyを返してくれます。
  4. Bindingsプロパティがポリシーにバインドされているプリンシパルの配列です。
  5. 各プリンシパルは複数のメンバーを含んでいます。このメンバーには個人アカウントだけではなく、サービスアカウントなども含まれます。
  6. Eメールアドレスでプロジェクト管理者かどうかを判断しています。個人アカウントの場合は先頭に"user:"が付いているので、Eメールアドレスを含んでいるか否かで判断しています。


ライブラリ

今回使ったライブラリのパッケージは以下。

一方でGoogle公式サイトには以下も載っています。

cloud.google.com/go/resourcemanager/apiv2

後者のライブラリは実装されている機能が少なすぎて、今回のように実装できません。というかAPI仕様を見る限り、ほとんど使い物にならないのではないかと思います。

GoのResource Managerに限らず、どのライブラリを使えばいいのか、こんなの見つけたけど使って大丈夫なのかと、迷うことがよくありますが、今回は以上の実装で目的を果たせました。また前者のライブラリは機能も十分そろっていそうなので、その他の用途にも使えると思います。

0 件のコメント:

コメントを投稿