Google CloudのIAM（ロール）のパーミッションをdiffで比較する

## 課題
Google CloudでIAMの事前定義ロールを比較する際に「ロールとパーミッションの対応関係」や「ロールが所有するパーミッション」の把握が難しいと感じることが多々あります。


Googleのドキュメントから詳細を確認することはできますが、記載されている内容が常に最新とは限らず、また目視で探すとそれなりに時間もかかってしまいます。

**ロールとパーミッションの対応関係を調べる場合**

https://cloud.google.com/iam/docs/understanding-roles#predefined

![スクリーンショット 2024-10-12 20.24.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/b909a063-a8c8-d20e-f1d0-d3e3ec5cb725.png)

**パーミッションからロールを逆引きする場合**

https://cloud.google.com/iam/docs/permissions-reference


![スクリーンショット 2024-10-12 20.26.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/172b2c50-8672-1e00-2c89-fb344563e85a.png)

そこで、この記事ではCLIを使ったロールとパーミッションの比較方法をご紹介します。



## gcloudコマンドでの確認方法

gcloud CLIをインストールし、`gcloud iam roles describe`を実行することでロールの詳細を表示することができます。

https://cloud.google.com/sdk/docs/install?hl=ja

※Cloud Shellを利用している場合はインストール不要です。


```shell
# 事前定義ロールの場合
# - xxxの箇所にロールの名称を指定
gcloud iam roles describe roles/xxx

# カスタムロールの場合
# - NNNの箇所にカスタムロールに割り当てられた番号を指定。
# - projectかorganizationのいずれかを必ず指定する
gcloud iam roles describe NNN --project projectName
gcloud iam roles describe NNN --organization organizationName
```

## 1) BigQuery AdminとBigQuery Studio Adminを比較

まずBigQuery AdminとBigQuery Studio Adminのパーミッションを比較してみることにします。

それぞれのパーミッションを一覧表示してみましょう。

### BigQuery Admin

```
gcloud iam roles describe roles/bigquery.admin
```



```
description: Administer all BigQuery resources and data
etag: AA==
includedPermissions:
- bigquery.bireservations.get
- bigquery.bireservations.update
- bigquery.capacityCommitments.create
- bigquery.capacityCommitments.delete
- bigquery.capacityCommitments.get
- bigquery.capacityCommitments.list
- bigquery.capacityCommitments.update
- bigquery.config.get
- bigquery.config.update
- bigquery.connections.create
- bigquery.connections.delegate
- bigquery.connections.delete
- bigquery.connections.get
- bigquery.connections.getIamPolicy
- bigquery.connections.list
- bigquery.connections.setIamPolicy
- bigquery.connections.update
- bigquery.connections.updateTag
- bigquery.connections.use
- bigquery.dataPolicies.create
- bigquery.dataPolicies.delete
- bigquery.dataPolicies.get
- bigquery.dataPolicies.getIamPolicy
- bigquery.dataPolicies.list
- bigquery.dataPolicies.setIamPolicy
- bigquery.dataPolicies.update
- bigquery.datasets.create
- bigquery.datasets.createTagBinding
- bigquery.datasets.delete
- bigquery.datasets.deleteTagBinding
- bigquery.datasets.get
- bigquery.datasets.getIamPolicy
- bigquery.datasets.link
- bigquery.datasets.listEffectiveTags
- bigquery.datasets.listSharedDatasetUsage
- bigquery.datasets.listTagBindings
- bigquery.datasets.setIamPolicy
- bigquery.datasets.update
- bigquery.datasets.updateTag
- bigquery.jobs.create
- bigquery.jobs.delete
- bigquery.jobs.get
- bigquery.jobs.list
- bigquery.jobs.listAll
- bigquery.jobs.listExecutionMetadata
- bigquery.jobs.update
- bigquery.models.create
- bigquery.models.delete
- bigquery.models.export
- bigquery.models.getData
- bigquery.models.getMetadata
- bigquery.models.list
- bigquery.models.updateData
- bigquery.models.updateMetadata
- bigquery.models.updateTag
- bigquery.readsessions.create
- bigquery.readsessions.getData
- bigquery.readsessions.update
- bigquery.reservationAssignments.create
- bigquery.reservationAssignments.delete
- bigquery.reservationAssignments.list
- bigquery.reservationAssignments.search
- bigquery.reservations.create
- bigquery.reservations.delete
- bigquery.reservations.get
- bigquery.reservations.list
- bigquery.reservations.update
- bigquery.routines.create
- bigquery.routines.delete
- bigquery.routines.get
- bigquery.routines.list
- bigquery.routines.update
- bigquery.routines.updateTag
- bigquery.rowAccessPolicies.create
- bigquery.rowAccessPolicies.delete
- bigquery.rowAccessPolicies.getIamPolicy
- bigquery.rowAccessPolicies.list
- bigquery.rowAccessPolicies.overrideTimeTravelRestrictions
- bigquery.rowAccessPolicies.setIamPolicy
- bigquery.rowAccessPolicies.update
- bigquery.savedqueries.create
- bigquery.savedqueries.delete
- bigquery.savedqueries.get
- bigquery.savedqueries.list
- bigquery.savedqueries.update
- bigquery.tables.create
- bigquery.tables.createIndex
- bigquery.tables.createSnapshot
- bigquery.tables.createTagBinding
- bigquery.tables.delete
- bigquery.tables.deleteIndex
- bigquery.tables.deleteSnapshot
- bigquery.tables.deleteTagBinding
- bigquery.tables.export
- bigquery.tables.get
- bigquery.tables.getData
- bigquery.tables.getIamPolicy
- bigquery.tables.list
- bigquery.tables.listEffectiveTags
- bigquery.tables.listTagBindings
- bigquery.tables.replicateData
- bigquery.tables.restoreSnapshot
- bigquery.tables.setCategory
- bigquery.tables.setColumnDataPolicy
- bigquery.tables.setIamPolicy
- bigquery.tables.update
- bigquery.tables.updateData
- bigquery.tables.updateTag
- bigquery.transfers.get
- bigquery.transfers.update
- bigquerymigration.translation.translate
- dataform.compilationResults.create
- dataform.compilationResults.get
- dataform.compilationResults.list
- dataform.compilationResults.query
- dataform.config.get
- dataform.config.update
- dataform.locations.get
- dataform.locations.list
- dataform.releaseConfigs.create
- dataform.releaseConfigs.delete
- dataform.releaseConfigs.get
- dataform.releaseConfigs.list
- dataform.releaseConfigs.update
- dataform.repositories.commit
- dataform.repositories.computeAccessTokenStatus
- dataform.repositories.create
- dataform.repositories.delete
- dataform.repositories.fetchHistory
- dataform.repositories.fetchRemoteBranches
- dataform.repositories.get
- dataform.repositories.getIamPolicy
- dataform.repositories.list
- dataform.repositories.queryDirectoryContents
- dataform.repositories.readFile
- dataform.repositories.setIamPolicy
- dataform.repositories.update
- dataform.workflowConfigs.create
- dataform.workflowConfigs.delete
- dataform.workflowConfigs.get
- dataform.workflowConfigs.list
- dataform.workflowConfigs.update
- dataform.workflowInvocations.cancel
- dataform.workflowInvocations.create
- dataform.workflowInvocations.delete
- dataform.workflowInvocations.get
- dataform.workflowInvocations.list
- dataform.workflowInvocations.query
- dataform.workspaces.commit
- dataform.workspaces.create
- dataform.workspaces.delete
- dataform.workspaces.fetchFileDiff
- dataform.workspaces.fetchFileGitStatuses
- dataform.workspaces.fetchGitAheadBehind
- dataform.workspaces.get
- dataform.workspaces.getIamPolicy
- dataform.workspaces.installNpmPackages
- dataform.workspaces.list
- dataform.workspaces.makeDirectory
- dataform.workspaces.moveDirectory
- dataform.workspaces.moveFile
- dataform.workspaces.pull
- dataform.workspaces.push
- dataform.workspaces.queryDirectoryContents
- dataform.workspaces.readFile
- dataform.workspaces.removeDirectory
- dataform.workspaces.removeFile
- dataform.workspaces.reset
- dataform.workspaces.searchFiles
- dataform.workspaces.setIamPolicy
- dataform.workspaces.writeFile
- dataplex.projects.search
- resourcemanager.projects.get
- resourcemanager.projects.list
name: roles/bigquery.admin
stage: GA
title: BigQuery Admin
```

### BigQuery Studio Admin


```
gcloud iam roles describe roles/bigquery.studioAdmin
```

```
description: Combination role of BigQuery Admin, Dataform Admin, and Notebook Runtime
  Admin.
etag: AA==
includedPermissions:
- aiplatform.notebookRuntimeTemplates.apply
- aiplatform.notebookRuntimeTemplates.create
- aiplatform.notebookRuntimeTemplates.delete
- aiplatform.notebookRuntimeTemplates.get
- aiplatform.notebookRuntimeTemplates.getIamPolicy
- aiplatform.notebookRuntimeTemplates.list
- aiplatform.notebookRuntimeTemplates.setIamPolicy
- aiplatform.notebookRuntimeTemplates.update
- aiplatform.notebookRuntimes.assign
- aiplatform.notebookRuntimes.delete
- aiplatform.notebookRuntimes.get
- aiplatform.notebookRuntimes.list
- aiplatform.notebookRuntimes.start
- aiplatform.notebookRuntimes.update
- aiplatform.notebookRuntimes.upgrade
- aiplatform.operations.list
- bigquery.bireservations.get
- bigquery.bireservations.update
- bigquery.capacityCommitments.create
- bigquery.capacityCommitments.delete
- bigquery.capacityCommitments.get
- bigquery.capacityCommitments.list
- bigquery.capacityCommitments.update
- bigquery.config.get
- bigquery.config.update
- bigquery.connections.create
- bigquery.connections.delegate
- bigquery.connections.delete
- bigquery.connections.get
- bigquery.connections.getIamPolicy
- bigquery.connections.list
- bigquery.connections.setIamPolicy
- bigquery.connections.update
- bigquery.connections.updateTag
- bigquery.connections.use
- bigquery.dataPolicies.create
- bigquery.dataPolicies.delete
- bigquery.dataPolicies.get
- bigquery.dataPolicies.getIamPolicy
- bigquery.dataPolicies.list
- bigquery.dataPolicies.setIamPolicy
- bigquery.dataPolicies.update
- bigquery.datasets.create
- bigquery.datasets.createTagBinding
- bigquery.datasets.delete
- bigquery.datasets.deleteTagBinding
- bigquery.datasets.get
- bigquery.datasets.getIamPolicy
- bigquery.datasets.link
- bigquery.datasets.listEffectiveTags
- bigquery.datasets.listSharedDatasetUsage
- bigquery.datasets.listTagBindings
- bigquery.datasets.setIamPolicy
- bigquery.datasets.update
- bigquery.datasets.updateTag
- bigquery.jobs.create
- bigquery.jobs.delete
- bigquery.jobs.get
- bigquery.jobs.list
- bigquery.jobs.listAll
- bigquery.jobs.listExecutionMetadata
- bigquery.jobs.update
- bigquery.models.create
- bigquery.models.delete
- bigquery.models.export
- bigquery.models.getData
- bigquery.models.getMetadata
- bigquery.models.list
- bigquery.models.updateData
- bigquery.models.updateMetadata
- bigquery.models.updateTag
- bigquery.readsessions.create
- bigquery.readsessions.getData
- bigquery.readsessions.update
- bigquery.reservationAssignments.create
- bigquery.reservationAssignments.delete
- bigquery.reservationAssignments.list
- bigquery.reservationAssignments.search
- bigquery.reservations.create
- bigquery.reservations.delete
- bigquery.reservations.get
- bigquery.reservations.list
- bigquery.reservations.update
- bigquery.routines.create
- bigquery.routines.delete
- bigquery.routines.get
- bigquery.routines.list
- bigquery.routines.update
- bigquery.routines.updateTag
- bigquery.rowAccessPolicies.create
- bigquery.rowAccessPolicies.delete
- bigquery.rowAccessPolicies.getIamPolicy
- bigquery.rowAccessPolicies.list
- bigquery.rowAccessPolicies.overrideTimeTravelRestrictions
- bigquery.rowAccessPolicies.setIamPolicy
- bigquery.rowAccessPolicies.update
- bigquery.savedqueries.create
- bigquery.savedqueries.delete
- bigquery.savedqueries.get
- bigquery.savedqueries.list
- bigquery.savedqueries.update
- bigquery.tables.create
- bigquery.tables.createIndex
- bigquery.tables.createSnapshot
- bigquery.tables.createTagBinding
- bigquery.tables.delete
- bigquery.tables.deleteIndex
- bigquery.tables.deleteSnapshot
- bigquery.tables.deleteTagBinding
- bigquery.tables.export
- bigquery.tables.get
- bigquery.tables.getData
- bigquery.tables.getIamPolicy
- bigquery.tables.list
- bigquery.tables.listEffectiveTags
- bigquery.tables.listTagBindings
- bigquery.tables.replicateData
- bigquery.tables.restoreSnapshot
- bigquery.tables.setCategory
- bigquery.tables.setColumnDataPolicy
- bigquery.tables.setIamPolicy
- bigquery.tables.update
- bigquery.tables.updateData
- bigquery.tables.updateTag
- bigquery.transfers.get
- bigquery.transfers.update
- bigquerymigration.translation.translate
- compute.reservations.get
- compute.reservations.list
- dataform.compilationResults.create
- dataform.compilationResults.get
- dataform.compilationResults.list
- dataform.compilationResults.query
- dataform.config.get
- dataform.config.update
- dataform.locations.get
- dataform.locations.list
- dataform.releaseConfigs.create
- dataform.releaseConfigs.delete
- dataform.releaseConfigs.get
- dataform.releaseConfigs.list
- dataform.releaseConfigs.update
- dataform.repositories.commit
- dataform.repositories.computeAccessTokenStatus
- dataform.repositories.create
- dataform.repositories.delete
- dataform.repositories.fetchHistory
- dataform.repositories.fetchRemoteBranches
- dataform.repositories.get
- dataform.repositories.getIamPolicy
- dataform.repositories.list
- dataform.repositories.queryDirectoryContents
- dataform.repositories.readFile
- dataform.repositories.setIamPolicy
- dataform.repositories.update
- dataform.workflowConfigs.create
- dataform.workflowConfigs.delete
- dataform.workflowConfigs.get
- dataform.workflowConfigs.list
- dataform.workflowConfigs.update
- dataform.workflowInvocations.cancel
- dataform.workflowInvocations.create
- dataform.workflowInvocations.delete
- dataform.workflowInvocations.get
- dataform.workflowInvocations.list
- dataform.workflowInvocations.query
- dataform.workspaces.commit
- dataform.workspaces.create
- dataform.workspaces.delete
- dataform.workspaces.fetchFileDiff
- dataform.workspaces.fetchFileGitStatuses
- dataform.workspaces.fetchGitAheadBehind
- dataform.workspaces.get
- dataform.workspaces.getIamPolicy
- dataform.workspaces.installNpmPackages
- dataform.workspaces.list
- dataform.workspaces.makeDirectory
- dataform.workspaces.moveDirectory
- dataform.workspaces.moveFile
- dataform.workspaces.pull
- dataform.workspaces.push
- dataform.workspaces.queryDirectoryContents
- dataform.workspaces.readFile
- dataform.workspaces.removeDirectory
- dataform.workspaces.removeFile
- dataform.workspaces.reset
- dataform.workspaces.searchFiles
- dataform.workspaces.setIamPolicy
- dataform.workspaces.writeFile
- dataplex.projects.search
- resourcemanager.projects.get
- resourcemanager.projects.list
name: roles/bigquery.studioAdmin
stage: GA
title: BigQuery Studio Admin
```

descriptionとしてBigQuery Adminでは`Administer all BigQuery resources and data`、BigQuery Studio Adminでは`Combination role of BigQuery Admin, Dataform Admin, and Notebook Runtime Admin.`と記載があります。

どちらも割り当てられているパーミッションは似ているようですが、量が多いためdiffを取ることにします。



### colordiffで差分確認
colordiffを利用し差分に色を付けます。

```shell
sudo apt install colordiff
```

以下のコマンドは、`gcloud iam roles describe bigquery.admin` と `gcloud iam roles describe roles/bigquery.studioAdmin` の出力結果を一時的な仮想ファイルとして扱い、その差分を diff コマンドで比較します。

```shell
colordiff -u <(gcloud iam roles describe roles/bigquery.admin) <(gcloud iam roles describe roles/bigquery.studioAdmin)
```
※ `-u`オプションは比較結果を「unified（統合差分）」形式で表示しますが、 `-y`とすると比較結果を左右に並べて表示することもできます。


コマンドを実行すると以下のような形で出力されました。


![スクリーンショット 2024-10-12 21.12.30（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/fee44225-ba31-95b9-5204-baa9fb272060.png)



BigQuery Adminに以下のパーミッションを追加した事前定義ロールがBigQuery Studio Adminであることが分かります。


```
- aiplatform.notebookRuntimeTemplates.apply
- aiplatform.notebookRuntimeTemplates.create
- aiplatform.notebookRuntimeTemplates.delete
- aiplatform.notebookRuntimeTemplates.get
- aiplatform.notebookRuntimeTemplates.getIamPolicy
- aiplatform.notebookRuntimeTemplates.list
- aiplatform.notebookRuntimeTemplates.setIamPolicy
- aiplatform.notebookRuntimeTemplates.update
- aiplatform.notebookRuntimes.assign
- aiplatform.notebookRuntimes.delete
- aiplatform.notebookRuntimes.get
- aiplatform.notebookRuntimes.list
- aiplatform.notebookRuntimes.start
- aiplatform.notebookRuntimes.update
- aiplatform.notebookRuntimes.upgrade
- aiplatform.operations.list
- compute.reservations.get
- compute.reservations.list
```


aiplatformはNotebook関連、computeはコンピュートリソース（VMインスタンスなど）の予約に関する権限です。

今後のBigQuery Studio利用を考えると、BigQuery Adminが必要な場合はBigQuery Studio Adminを付与しておくといいかもしれませんね。

## 2) roles/ownerに不足している権限を確認

「オーナーなのに必要な作業に対してパーミッションが足りない」というケースが稀にあります。

例えば以下のコマンドでは「roles/ownerは存在せず、比較対象には存在する行」を抽出することができます。

`roles/owner` と `roles/iam.serviceAccountTokenCreator` を比較してみます。

```
diff <(gcloud iam roles describe roles/owner) <(gcloud iam roles describe roles/iam.serviceAccountTokenCreator) | grep '^>'
```

出力として以下のような差分が抽出できました。

```
> - iam.serviceAccounts.getAccessToken
> - iam.serviceAccounts.getOpenIdToken
> - iam.serviceAccounts.implicitDelegation
> - iam.serviceAccounts.signBlob
> - iam.serviceAccounts.signJwt
```

つまり、オーナーロールではこれらのパーミッションが不足しており、オーナーがすべてのパーミッションを所有していないことが分かります。

オーナー権限ではパーミッションが多いため、このような比較においてもdiffが役立つことが分かります。


## まとめ

diffを利用することで、ロールごとのパーミッションを簡単に比較できるようになりました。

## 参考になりそうなサイト

https://blog.pokutuna.com/entry/compare-gcp-iam-role-permissions

https://iret.media/73609