はじめに
某中小企業で情シスをしているのですが、とある理由でGCPを触る必要がありまして、初めて状況みてみたところ、無数の用途不明のGCPプロジェクトが乱立している状態ということが判明。
中には消したらまずいものもあるとのことで、まずは削除可否の確認依頼先を棚卸すべく、そのプロジェクトのオーナーロールの人であれば何か知っているであろうということで、各プロジェクトとそのオーナーの一覧を整理するということになりました。
さすがにひとつひとうのプロジェクトを開いてIAMを確認して~とやっていくのはナンセンスかと思いましたので、一覧を出力するスクリプトを作りましたのでそのご紹介です。
スクリプト作成にあたって検討したこと
一覧をスクリプト出力するにあたっては、gcloudというCLIからGCPを操作できるコマンドを使うわけですが、この中に「asset search-all-iam-policies」という全プロジェクト対象に各プロジェクトのIAM出力できるコマンドがあります。
これを一発たたけば特にスクリプトなど不要と当初は思っていたのですが、これだとそのプロジェクト中のIAMしか出力されず、上位の組織から継承しているIAMは出力されないことがわかりました。また、継承しているIAMしか残っていないプロジェクト(退職者が作成したプロジェクトなど)はそもそもプロジェクト自体が出力に載ってこないので、整理の際に漏れが生じるだろうと思いました。
継承しているIAMを含めて出力するには「projects get-ancestors-iam-policy」というコマンドを実行する必要があり、このコマンドは単一のプロジェクトIDを指定して実行する必要があるので、
1.「projects list」コマンドでプロジェクト一覧を取得
2.「projects get-ancestors-iam-policy」で「1」で取得した1つ1つのプロジェクトに対して継承含めたIAMを出力
というステップのスクリプトを作成することになった次第です。
スクリプト
ということで本題のスクリプトです。
このスクリプトをCloud Shellにアップロードして実行します。
※プロジェクトの情報を表示するには、Cloud Shell使用時にログインしているGoogleアカウントがそのプロジェクト中のIAMに登録されている必要があるので、可能であれば組織管理者のアカウントなどを用いて実行した方が漏れが出ないと思います。
#!/bin/bash
# 出力ファイル名の設定
FILE_NAME=iamOwnerList.csv
# 列名の事前出力
echo 'name,projectId,id,members,role' > $FILE_NAME
# for文の「gcloud projects」でプロジェクト名称取得した際、プロジェクト名にスペースなど含まれているとそこで区切られてしまうので、デフォルトの設定をバックアップしてデリミタを改行に設定
IFS_BACKUP=$IFS
IFS=$'\n'
# プロジェクト一覧出力のプロジェクト名とプロジェクトIDのみをCSVで取得してループ処理
for projectInfo in $(gcloud projects list --filter='projectId!=sys-*' --format="csv[no-heading](name,projectId)")
do
# プロジェクト名とプロジェクトIDをカンマ区切りで分解
IFS=',' read -r -a projectInfoArray<<< "$projectInfo"
projectName="${projectInfoArray[0]}"
projectId="${projectInfoArray[1]}"
# そのプロジェクトの継承含めたownerロールのIAM一覧を取得。
# そのままだと継承分のIAMは継承元のプロジェクトIDで表示されて可読性が悪いので、処理中のプロジェクト名とプロジェクトIDを先頭列に付加してCSV出力
gcloud projects get-ancestors-iam-policy $projectId --filter='policy.bindings.members:user AND policy.bindings.role:roles/owner' --flatten="policy.bindings[].members[]" --format="csv[no-heading](id,policy.bindings.members.basename(),policy.bindings.role)" \
| awk -F "," -v awkVar1=$projectName -v awkVar2=$projectId '{print awkVar1 "," awkVar2 "," $1 "," $2 "," $3}' >> $FILE_NAME
# カンマ区切りに設定したデリミタを改行に戻さないと次の要素取得でまたスペースで区切られるので、戻す。
IFS=$'\n'
done
IFS=$IFS_BACKUP
処理対象のプロジェクトの数量によっては結構時間がかかりますが、実行すると下のようなcsvファイルが出力されます。
「yyyyproject」のように、継承しているIAMしかいないプロジェクトはもう作成したアカウントが存在しないと判断して整理していく感じです。
name,projectId,id,members,role
zzzzproject,zzzzproject-371606,zzzzproject-371606,user:zzzzx@gmail.com,roles/owner
zzzzproject,zzzzproject-371606,{IAM継承しているプロジェクトID},user:yyyy@gmail.com,roles/owner
yyyyproject,yyyyproject-371606,{IAM継承しているプロジェクトID},user:yyyy@gmail.com,roles/owner
zzzzproject,zzzzproject-371606,zzzzproject-371606,user:zzzzx@gmail.com,roles/owner
zzzzproject,zzzzproject-371606,{IAM継承しているプロジェクトID},user:yyyy@gmail.com,roles/owner
さいごに
GCPのプロジェクトってGWSのデフォルト設定だと誰でも作れちゃうみたいですね。
そのまま放置しとくといつのまにか知らないGCP環境が乱立していて誰も状況知らない・身に覚えのない請求が。。ってことになりかねないのでGWS使っている企業さんは注意が必要だなと思いました。