Claude CodeでIAM Recommenderを使いGCPの過剰ロールを絞る手順
GCPのIAM Recommenderが出すロール推奨をClaude Codeに読ませ、外す候補と代替ロールの変更案を作らせる手順。適用は人がgcloudで実行する分担と、denyルールの限界をまとめます。
Claude CodeでIAM Recommenderを使いGCPの過剰ロールを絞る手順
GCPのIAM Recommenderは、過去90日の権限の使用状況から「このロールは外せる」「このロールに置き換えられる」という推奨を出します。Claude Codeには、この推奨を読んで変更案の一覧にまとめるところまでを任せます。IAMポリシーを書き換える操作は、人がgcloudで実行します。
読み取りと書き込みで担当を分けると、Claude Codeに渡す権限が小さく済みます。
IAM Recommenderは何を出し、どこまでが推奨なのか
IAM Recommenderは、プリンシパル(ユーザー、サービスアカウントなど)に付いたロールのうち、使われていない権限を洗い出す仕組みです。ロールの権限数と、直近90日に実際に使われた権限を比べて、ロールごとの推奨を作ります。付与から90日未満のロールは、付与後の使用実績が比較の対象です。
推奨の種類は、サブタイプで見分けられます。外すだけの REMOVE_ROLE と、別のロールに置き換える REPLACE_ROLE が基本です。バケットやBigQueryデータセットに付けたロール向けの派生もあり、APIで絞り込むときのキーになります。
置き換えの推奨は、既存のカスタムロールか、1つ以上の事前定義ロールを示します。プロジェクトに付けたロールに限っては、新しいカスタムロールの作成を提案することもあります。サービスエージェントを除き、推奨がプリンシパルの権限を増やす方向になることはありません。
推奨の生成に効く数字
観測期間の上限
90日
使用実績はこの範囲まで
最短観測期間の既定
90日
プロジェクトのロールは30日・60日に変更可
新規カスタムロール提案の上限
100個
組織のカスタムロールが100個以上だと提案されない
推奨が出ない・当てにならないのはどんなときか
変更案の作成を始める前に、推奨の対象外になる条件を押さえておきます。ここを知らずに「推奨が空だから問題なし」と読むと、過剰な権限が残ります。
- 条件付きのロールバインディングには、ポリシーインサイトが作られません。条件付きで付けた権限は、このやり方では洗えません
- ロールの付与から最短観測期間が過ぎていないと、推奨が出ません。既定は90日で、プロジェクトレベルの推奨に限って30日か60日に短縮できます。短くすると早く推奨が出る一方、精度が下がる可能性があります
- サービスエージェントの推奨は、Owner・Editor・Viewerを付けたものだけが対象です。それ以外のロールのサービスエージェントには出ません
- 観測期間は最大90日です。四半期や年次で動くバッチのように、90日より長い周期でしか使わない権限は、使われていない扱いになりえます
- IAM以外のアクセス制御は考慮されません。Cloud StorageのACLやKubernetesのRBACを併用している環境では、適用前に影響を確かめる必要があります
- 新しいカスタムロールを作って適用するのは、Google Cloudコンソールからだけです。gcloudで取れる推奨は、変更案の元ネタとして使います
条件付きバインディングが多い組織では、Recommenderの一覧に出ない権限の棚卸しを、別の手段で補うことになります。
先にClaude Codeの権限を絞る
一覧の取得は読み取りだけなので、Claude Codeに許可してかまいません。書き込み系のコマンドは、denyで止めておきます。プロジェクトの .claude/settings.json に次のように書きます。
{
"permissions": {
"allow": [
"Bash(gcloud recommender recommendations list *)",
"Bash(gcloud projects get-iam-policy *)"
],
"deny": [
"Bash(gcloud projects remove-iam-policy-binding *)",
"Bash(gcloud projects add-iam-policy-binding *)",
"Bash(gcloud projects set-iam-policy *)"
]
}
}ルールはdeny、ask、allowの順に評価され、最初に当たったものが結果を決めます。広いdenyは、より狭いallowがあっても優先されます。つまり remove-iam-policy-binding をdenyに置けば、allowの書き方に関係なく止まります。mark-claimed などの推奨の状態を変えるコマンドは、ここでは許可に入れていません。実行のたびに確認が出るので、人が判断する場面と重なります。
ルールの確認と編集は /permissions でできます。コマンドの詳しい使い方はClaude Codeの/permissionsコマンドにまとめています。
Claude Codeを動かす認証情報も絞る
denyはコマンド文字列に対する制御です。認証情報側にも壁を置くと二重になります。推奨の閲覧に必要なのは、閲覧用のロールです。ドキュメントでは、推奨を見るには roles/iam.roleViewer と roles/recommender.iamViewer を、適用や却下までするには roles/recommender.iamAdmin を、対象のプロジェクト・フォルダ・組織に付けるよう案内しています。
Claude Codeを動かす端末では、前者の閲覧系だけを持つアカウントでgcloudにログインしておきます。IAMを書き換える権限を持つアカウントでの作業は、人が別のターミナルで行います。Claude Code側のdenyをすり抜けても、認証情報が閲覧だけなら書き換えは通りません。
推奨を取得して変更案を作らせる
取得するコマンドは、リソースの種類とIDを指定した list です。プロジェクトならこうなります。
gcloud recommender recommendations list \
--location=global \
--recommender=google.iam.policy.Recommender \
--project=my-project \
--format=json > recommendations.json出力は推奨のJSON配列です。ロールを外す推奨なら、recommenderSubtype が REMOVE_ROLE で、content.operationGroups[].operations[] に action: remove と、対象のメンバーとロールを示す pathFilter が入ります。primaryImpact には、外すと失われる権限の数が出ます。lastRefreshTime は、推奨がいつ更新されたかを示します。
このJSONをClaude Codeに読ませて、変更案をMarkdownにまとめさせます。依頼文は、出力の形と禁止事項を先に決めておくと安定します。
recommendations.json を読んで、IAM変更案を plan.md にまとめてください。
- 推奨ごとに、対象メンバー、現在のロール、サブタイプ、失われる権限数、
lastRefreshTime、推奨ID(name の末尾)を表にする
- REMOVE_ROLE は「外す」、REPLACE_ROLE は代替ロールを並べる
- 条件付きバインディング、サービスエージェント、グループは別表にする
- gcloud の書き込み系コマンドは実行しない。人が実行するコマンドを
コードブロックで書くところまでとする例えば次のような形になります。公式ドキュメントの例にあるCompute Admin(roles/compute.admin)のサービスアカウントを題材にした書き方で、実環境の出力ではありません。
| 推奨ID | メンバー | 現在のロール | 提案 | 失われる権限数 |
|---|---|---|---|---|
| fb927dc1-… | メンバーserviceAccount:id-…@example-project | 現在のロールroles/compute.admin | 提案外す(REMOVE_ROLE) | 失われる権限数708 |
ここで大事なのは、Claude Codeに「外してよいか」の最終判断を書かせないことです。推奨は使用実績という過去の事実から作られます。実績に現れない用途、たとえば年に1度の障害対応用の権限などは、人がサービスの運用者に尋ねて決める領域です。plan.mdには、確認が必要な推奨に「運用者に確認」の欄を設けるよう頼んでおくと、レビューの手が止まりません。
適用は人がgcloudで実行する
plan.mdを人が確認したら、次の順で進めます。
- 推奨の状態を
CLAIMEDにして、適用中に推奨が変わらないようにします - 置き換えの推奨なら、代替ロールの付与を先に行います
- 不要になったロールのバインディングを外します
- 推奨の状態を
SUCCEEDEDかFAILEDに更新します
mark-claimed は、推奨のIDとetagを指定して実行します。etagは list の出力の etag フィールドです。
gcloud recommender recommendations mark-claimed RECOMMENDATION_ID \
--location=global \
--recommender=google.iam.policy.Recommender \
--project=my-project \
--etag=ETAGロールを外すコマンドは、プロジェクトのIAMポリシーからバインディングを1つ消す remove-iam-policy-binding です。メンバーとロールを必ず指定します。
gcloud projects remove-iam-policy-binding my-project \
--member='serviceAccount:id-1234567890@example-project.iam.gserviceaccount.com' \
--role='roles/compute.admin'ドキュメントには、適用の手順として「プロジェクトの許可ポリシーを取得し、推奨を反映するように変更して設定する」という記述があります。バインディングを1つ消すだけなら上のコマンドで足ります。ロールの置き換えで複数のバインディングを同時に動かす場合は、get-iam-policy で現在の状態を保存してから作業すると、戻すときの手がかりが残ります。
実行後は、状態を更新します。適用できたなら mark-succeeded、できなかったなら mark-failed です。コンソールから適用した推奨は、90日以内なら履歴から元に戻せます。gcloudで手動適用した場合の巻き戻しは、取っておいたポリシーが頼りです。
作業の順番をどう決めるか
最初に手を付けるのは、失われる権限数が大きく、かつ運用者が不要と答えたものです。ドキュメントの例のように、使われていないCompute Adminを持つサービスアカウントがその典型で、外した効果が大きく出ます。逆に、サービスエージェントやグループが絡む推奨は、影響範囲が読みにくいので後回しにします。
推奨を処理したあとは、もう一度 list を実行します。置き換えで付けた代替ロールに対しても、時間が経てば新しい推奨が出ます。絞り込みは1回で終わらず、観測期間が一巡するごとに繰り返す作業です。
denyルールが止めないもの
先に書いたdenyは、Claude Codeが生成するコマンドの文字列に対するルールで、gcloudそのものへの制限ではありません。ドキュメントは、Bashのdenyルールを「Claudeが普通に書く形を止めるもの」と位置づけ、セキュリティ境界ではないと明記しています。Bash(rm *) が /bin/rm や bash -c 'rm …' を止めないのと同じ型で、gcloud を別のパスで呼んだり、sh -c に包んだりした形は、別のルールか許可モードの判断になります。
対策は2つ重ねます。1つは前の節の閲覧専用の認証情報で、コマンドの形に依存しません。もう1つは、PreToolUseフックでコマンド全文を検査する方法です。フックの allow が、denyやaskのルールを飛び越えることはなく、exit code 2で止めるフックは、allowルールよりも優先されます。
この考え方はGCP以外のCLIにも使えます。本番へのデプロイを止める設計はClaude CodeでSalesforce CLIの権限を切る手順でも扱っています。
AWSのAccess Analyzerや、MCPでの制御とどう違うか
AWSでは、アクセスアナライザーのアクティビティから最小権限のポリシーを作る流れがあります。Claude CodeでIAM最小権限をAccess Analyzerから作る手順は、ポリシーを生成する方式です。IAM Recommenderは、既存のロールに対して外す・置き換えるという推奨を返す方式で、成果物がポリシー文書でなく推奨の一覧になる点が違います。
Google CloudのMCPサーバーを使う場合の権限制御は、Google CloudのMCPサーバーをIAMで権限制御するが扱っています。こちらは、Claudeに渡すMCPツールの側をIAMで絞る話です。この記事は逆に、GCPのIAMそのものを、Claude Codeの助けを借りて小さくしていく作業を扱っています。
つまずきやすい点
- 推奨が1件も出ない場合は、ロールの付与から最短観測期間が経っているか、バインディングに条件が付いていないかを確かめます。推奨が出ていない理由は、ロールの付与時期と条件の有無でほぼ切り分けられます
lastRefreshTimeが古い推奨は、現在の使われ方と合わない可能性があります。適用前に、ドキュメントが求めるとおり、いつ更新された推奨かを見ます- etagが一致しないとmark系のコマンドは失敗します。
listを取り直し、新しいetagで実行し直します - 新規のカスタムロール作成を含む推奨は、プロジェクトに
iam.roles.createが必要です。ドキュメントは、Role ViewerでなくRole Administrator(roles/iam.roleAdmin)を付けるよう案内しています - フォルダや組織の推奨を扱うときは、
--projectを--folderや--organizationに替えます
まとめ
IAM Recommenderの推奨は、使われていない権限を教えてくれますが、使われていないことと、外してよいことは別の話です。Claude Codeには取得と整理を任せ、外す判断と適用は人が持つ分担にすると、事故の入る余地が小さくなります。Claude Code側のdenyに加えて、閲覧専用の認証情報を使えば、コマンドの書き方が変わっても書き込みは通りません。条件付きバインディングと90日より長い周期の権限は、Recommenderが見ない領域として別に点検してください。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。