最小権限で Google Cloud(GCP)プロジェクトの費用を表示する

こんにちは、京セラコミュニケーションシステム 石関（@kccs_daisuke-ishizeki）です。

唐突ですが、Google Cloud で請求先アカウントの事前定義ロールを使わずに、プロジェクトの費用を表示するにはどのロール（権限）で表示できるのかご存知でしょうか？
また、最小権限で表示するにはどうすればよいでしょうか。

この記事ではそんなニッチな？内容をご紹介します。

:::note warn
本記事は2023年7月ごろに作成しております。引用している内容は執筆時点での最新となります。
:::

## この記事の対象者

- 請求先アカウントの事前定義ロールを使わず（or 使えない）にプロジェクトの費用を表示したい方
- プロジェクトの費用を表示するために基本ロールを割り当てている方
- プロジェクトの費用は表示できているが、どのように制御されている/できるのか知りたい方

## ドキュメントを確認してみる

まずは公式ドキュメントを確認してみると、以下の記載がありました。

> ユーザーが Cloud 請求先アカウントのすべてのプロジェクトの費用を表示できるようにするには、Cloud 請求先アカウントの費用の表示権限（`billing.accounts.getSpendingInformation`）をユーザーに付与します。ユーザーが特定のプロジェクトの費用を表示できるようにするには、個々のプロジェクトの表示権限（`billing.resourceCosts.get`）をユーザーに付与します。

なんとなく難しく書かれていますが、コンパクトにまとめると以下の関係です。

|                  権限                   |                     できること                     |
| --------------------------------------- | -------------------------------------------------- |
| billing.accounts.getSpendingInformation | 請求先アカウントのすべてのプロジェクトの費用を表示 |
| billing.resourceCosts.get               | 特定のプロジェクトの費用を表示                     |

引用元の公式ドキュメントはこちらです。

https://cloud.google.com/billing/docs/how-to/billing-access?hl=ja#billing-access


## ロールの権限を確認してみる

権限の違いによって、できることが違うことはわかりました。
では、この2つの権限はどのロールに含まれているのでしょうか？

以下の公式ドキュメントに請求先アカウントの事前定義ロールに対する権限が記載されていますが、実際に gcloud コマンドから確認してみました。

https://cloud.google.com/billing/docs/how-to/billing-access?hl=ja#overview-of-cloud-billing-roles-in-cloud-iam

### 請求先アカウントのロール

ここでは`請求先アカウント閲覧者`ロールの権限を確認してみました。

```zsh
ishizeki (arm64):~$% gcloud iam roles describe roles/billing.viewer | grep billing
description: Can view information about billing accounts.
- billing.accounts.get
- billing.accounts.getCarbonInformation
- billing.accounts.getIamPolicy
- billing.accounts.getPaymentInfo
- billing.accounts.getPricing
- billing.accounts.getSpendingInformation ←これ
- billing.accounts.getUsageExportSpec
- billing.accounts.list
- billing.billingAccountPrice.get
- billing.billingAccountServices.get
- billing.billingAccountServices.list
- billing.billingAccountSkuGroupSkus.get
- billing.billingAccountSkuGroupSkus.list
- billing.billingAccountSkuGroups.get
- billing.billingAccountSkuGroups.list
- billing.billingAccountSkus.get
- billing.billingAccountSkus.list
- billing.budgets.get
- billing.budgets.list
- billing.credits.list
- billing.finOpsBenchmarkInformation.get
- billing.finOpsHealthInformation.get
- billing.resourceAssociations.list
- billing.subscriptions.get
- billing.subscriptions.list
name: roles/billing.viewer
```

（ちょっと見づらいですが 8 行目に）請求先アカウントのすべてのプロジェクトの費用を確認できる`billing.accounts.getSpendingInformation`が含まれていることが確認できます。

### 基本ロールにはプロジェクトの費用を表示する権限が含まれている

次に基本ロールの権限を確認してみます。
ここでは`閲覧者`ロールの権限を確認してみました。

```zsh
ishizeki (arm64):~$% gcloud iam roles describe roles/viewer | grep billing
- billing.billingAccountPrice.get
- billing.billingAccountServices.get
- billing.billingAccountServices.list
- billing.billingAccountSkuGroupSkus.get
- billing.billingAccountSkuGroupSkus.list
- billing.billingAccountSkuGroups.get
- billing.billingAccountSkuGroups.list
- billing.billingAccountSkus.get
- billing.billingAccountSkus.list
- billing.finOpsBenchmarkInformation.get
- billing.finOpsHealthInformation.get
- billing.resourceCosts.get ←これ
- cloudasset.assets.exportCloudbillingBillingAccounts
- firebase.billingPlans.get
```

（下から 3 行目に）`billing.resourceCosts.get`が含まれていることが確認できます。
要するに基本ロールにはこの権限が含まれているのでプロジェクトの費用を表示できているわけですね。

逆に`billing.accounts.getSpendingInformation`が含まれていないことも確認できました。

## 事前定義ロールには含まれていない

最後に事前定義ロールの権限を確認してみます。
ここでは`Compute 管理者`ロールの権限を確認してみました。

```zsh
ishizeki (arm64):~$% gcloud iam roles describe roles/compute.admin | grep billing
ishizeki (arm64):~$%
```

費用を表示する権限はどちらも含まれていないことがわかります。

## どのロールを使うべきか

ここまでで、どのロールにどの権限が含まれ制御されているのかわかりました。

`請求先アカウント閲覧者`等のロールは本記事の主旨と外れるため、それ以外のロールで考えます。

- 基本ロール
- 事前定義ロール
- カスタムロール

基本ロールにはプロジェクトの費用を表示できる権限が含まれていますが、その他多くの権限が含まれているため、過剰な権限が割り当てられることになります。
公式ドキュメントにも以下のように、本番環境では基本ロールは付与せず、事前定義ロールまたはカスタムロールを付与するよう案内があるため適していません。

> 基本ロールには、すべての Google Cloud サービスにかかわる多くの権限が含まれます。本番環境では、他に選択肢がない限り、基本ロールを付与しないでください。代わりに、ニーズに合わせて最も制限された事前定義ロールまたはカスタムロールを付与します。

一方、事前定義ロールにプロジェクトの費用を表示できるロールは現状用意されていません。

結論、カスタムロールを作れば良さそうです。

引用元の公式ドキュメントはこちらです。

https://cloud.google.com/iam/docs/using-iam-securely?hl=ja

## 最小権限でプロジェクトの費用を表示する

もうなんとなくわかりますね。

以下の権限を含むカスタムロールを作成しプロジェクトの費用を表示させたい方へ割り当てればOKです。

```
billing.resourceCosts.get
```

実際には合わせて`resourcemanager.projects.get`の権限を含める必要があるため、以下 2 つの権限を含むカスタムロールが最小権限になります。
```
billing.resourceCosts.get
resourcemanager.projects.get
```

:::note warn
権限が不足していると下記のエラーが発生します。
:::

![resourcemanager.projects.get無し.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728315/553b3791-58ba-4805-830f-1d8c6d5246f2.png)

プロジェクトレベルでカスタムロールを毎度作成するのもメンドウなので、組織やフォルダレベルでカスタムロールを用意しておくのも良いと思います。

ご参考まで。

請求に関するカスタムロールの作成の公式ドキュメントはこちらです。

https://cloud.google.com/billing/docs/how-to/custom-roles?hl=ja

## 蛇足

ほとんど書き終わった後に以下のドキュメントを発見😇
（ヒントの部分です）

https://cloud.google.com/billing/docs/onboarding-checklist?hl=ja#important_roles_3