IAM policy for Service Account における Authoritative と Non-authoritative

# はじめに

Terraform で、IAM ポリシを管理するための方法として、[IAM policy for Service Account](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam.html) がありますが、それぞれ権限の強さ（Authoritativeness）や影響範囲が異なるため、理解した上で適切に選択する必要があります。

# IAM policy for Service Account

IAM の RBAC をサービスアカウントに適用するための方法として、下記 3 つのリソースセットが用意されています。

- `google_service_account_iam_policy`

サービスアカウントの IAM ポリシを設定し、すでにアタッチされている既存のポリシを置き換える。

- `google_service_account_iam_binding`

特定の IAM ロールに対する権限を付与し、IAM ポリシを更新してメンバーリストにロールを付与する。
サービスアカウントの IAM ポリシ内の他のロールは保持される。

- `google_service_account_iam_member`

IAM ポリシを更新し、新しいメンバーにロールを付与する。
サービスアカウントのロールの他のメンバーは保持される。

# Google Service Accout IAM Policy

- **Authoritative：完全に上書き型 / 強力な制御**

任意のサービスアカウントに対する IAM ポリシ全体を置き換える。

`google_service_account_iam_policy` は、権限セット（IAM ポリシ またはポリシ全体）を指定し、以前に設定されていた IAM ポリシは全て上書き・破棄される。

## 利点

ポリシ全体を厳密に定義・コントロールしたい場合に有用なルールセット。

## 副作用

他の場所からの IAM 設定や、Terraform 管理外での設定が消える可能性があるため、コンフリクトやオーバライドに注意する必要がある。

```hcl
resource "google_service_account_iam_policy" "example" {
  service_account_id = "my-sa@project.iam.gserviceaccount.com"
  policy_data = data.google_iam_policy.sa_policy.policy_data
}
```

対象リソースは 既存の IAM を完全に上書く。
他の `google_service_account_iam_member` や `google_service_account_iam_binding` と併用することで、コンフリクトが発生する可能性があるため、通常はどちらか片方のみを使用することが推奨される。

# Google Service Account IAM Binding

- **ロール単位で Authoritative：一部上書き型**

特定のロールに対して、指定した複数のメンバ（`members`）だけを設定する。（= "このロールに属するメンバ一覧を全てこの内容にする"）

`google_service_account_iam_binding` は、指定されたロールに対するメンバリストのみを置き換えるため、変更内容は他のロールに影響しない。

## 利点

同じロールに複数メンバを一括設定・管理できる。
IAM ロールを限定でき、IAM ポリシの一部分だけを操作したい場合に有用なルールセット。

## 副作用

同じロールに別の場所で付与していたメンバが削除される可能性がある。
このため、ロールの管理は単一の IAM Binding に統一すべき。

```hcl
resource "google_service_account_iam_binding" "example" {
  service_account_id = "my-sa@project.iam.gserviceaccount.com"
  role               = "roles/iam.serviceAccountUser"

  members = [
    "user:alice@example.com",
    "user:bob@example.com",
  ]
}
```

この設定により、[roles/iam.serviceAccountUser](https://cloud.google.com/iam/docs/service-account-permissions#roles) に関しては "alice" と "bob" だけがメンバになります。（他のユーザは削除される）

# Google Service Account IAM Member

- **Non-authoritative：個別追加型**

指定したロールに対して単一のメンバのみを追加する。他のメンバはそのまま保持する。

`google_service_account_iam_member` は、指定されたロールに 1 人分だけを追加するため、他には影響を及ぼさない。

## 利点

他の設定やポリシに影響を与えずに追加できる。
モジュール化や細かな設定（ユーザ等）が必要場合に有用なルールセット。

## 副作用

ロールとメンバが一対一対応であるため、複数のメンバを追加したい場合は冗長になる。
IAM ポリシの全体像が見えにくくなり、管理規模が拡大するとメンテナンスが煩雑化する。

```hcl
resource "google_service_account_iam_member" "example" {
  service_account_id = "my-sa@project.iam.gserviceaccount.com"
  role               = "roles/iam.serviceAccountUser"
  member             = "user:alice@example.com"
}
```

この設定により、既存のポリシに `user:alice@example.com` を追加するだけ。
他のメンバやロールには一切影響しない。

# 比較

| リソース名                           | Authoritativeness           | 操作単位                    | 特徴                                                          |
| :----------------------------------- | :-------------------------- | :-------------------------- | :------------------------------------------------------------ |
| `google_service_account_iam_policy`  | 全体（全面的に上書き）      | ポリシ全体                  | IAM ポリシを完全に置換。他と併用は NG。強力なため注意が必要。 |
| `google_service_account_iam_binding` | ロール単位で Authoritative  | 1 つのロールで一括設定      | 特定のロールの中身（メンバ）を丸ごと設定                      |
| `google_service_account_iam_member`  | Non-authoritative（追加型） | 1 メンバにつき 1 ロール管理 | 既存状態に追加される。柔軟で安全だが冗長になる可能性もある。  |

# ユースケース

| 例                                                     | 推奨リソース                         |
| :----------------------------------------------------- | :----------------------------------- |
| IAM ポリシを完全にコードで定義し、厳密に管理したい場合 | `google_service_account_iam_policy`  |
| 複数メンバを 1 つのロールで一括管理したい場合          | `google_service_account_iam_binding` |
| 少人数に柔軟かつ安全にロールを与えたい場合             | `google_service_account_iam_member`  |

# まとめ

- `google_service_account_iam_policy` は「超強力だが衝突リスクも高い」フル置換型
- `google_service_account_iam_binding` は「役割をまとめて指定したい」場合に最適（同じロール内で見通しが良い）
- `google_service_account_iam_member` は「細かく柔軟に追加したい」場合に安心で使いやすい

IAM policy for Service Account リソースセットは、運用ポリシやチームの構成に応じて適切な使い分けが必要になります。

## 参考・引用

https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam.html

https://stackoverflow.com/questions/63915353/what-is-the-meaning-of-authoritative-and-non-authoritative-for-gcp-iam-bindi