Google Cloud の Essential Contacts を使用する

## はじめに
通常 Google Cloud サービスは、ユーザーと重要な情報を共有に、特定の IAM メンバーのアドレスへ通知する
セキュリティ上アカウントのメール機能を OFF にしていたりすると、IAM メンバーがメール受信できないケースがある

エッセンシャル コンタクト (Essential Contacts) を使用する場合、独自の連絡先リストを指定することで、通知を受け取るユーザーをカスタマイズできる

今回、Essential Contacts について確認したことと、実際にラボ設定したのでその内容を記載する

![Essential Contacts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/e383f1fc-1dac-63cc-e5b7-fc0121e5f121.png)


## 概要

[ドキュメント](https://cloud.google.com/resource-manager/docs/managing-notification-contacts)からの抜粋

### 必要な API

[Essential Contacts API を有効にする](https://console.cloud.google.com/flows/enableapi?apiid=essentialcontacts.googleapis.com&_ga=2.16018354.568551355.1644550687-669251723.1606488380)必要がある

![Essential Contacts API.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/9f5537e6-fabf-fd7c-af56-b3b7a5f02226.png)

### 必要な権限

| 権限内容 | ロールの選択で出る名称| 事前定義ロール | 必要権限 |
|:-:|:-:|:-:|:-:|
| 連絡先の閲覧権限 | エッセンシャル コンタクトの管理者 | roles/essentialcontacts.viewer | essentialcontacts.contacts.get <br> essentialcontacts.contacts.list |
| 連絡先を管理する権限 | エッセンシャル コンタクトの閲覧者 | roles/essentialcontacts.admin | essentialcontacts.contacts.get <br> essentialcontacts.contacts.list <br> essentialcontacts.contacts.create <br> essentialcontacts.contacts.delete <br> essentialcontacts.contacts.update <br>  |

![Essential_Contacts_事前定義ロール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/ec124793-8e85-5d6b-8cb6-fa085db5e424.png)


### 通知のカテゴリ

- 連絡先は、複数の**通知カテゴリ**に割り当てることができる
- **カテゴリに連絡先を追加しない場合**は、**フォールバックの連絡先に送信**される
- フォールバックの連絡先を使用せずに、**カスタムの連絡先を追加することが推奨**されている
- 個人とグループの両方を連絡先として追加でき、人事異動の影響を減らすため、グループを連絡先が推奨

![Essentinal Contacts 通知のカテゴリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/5e3f125c-340c-fc5d-9542-7731863eb735.png)

具体的なカテゴリとフォールバック先は、[ドキュメントの表](https://cloud.google.com/resource-manager/docs/managing-notification-contacts#notification-categories)を参照

### 連絡先の割り当てに関するベスト プラクティス

通知先は組織で継承され、設定する階層での [Google Cloud の推奨](https://cloud.google.com/resource-manager/docs/managing-notification-contacts#contact-inheritance) は下記の通り

| 推奨レベル | 通知のカテゴリ |
|:-:|:-:|
| 組織 | 課金 <br> 法務 <br> セキュリティ |
| フォルダ / プロジェクト | すべて<br> プロダクトの更新情報 <br> セキュリティ <br> 停止 <br> 技術 |

## 設定

下記のような構成になるように設定テストをしたのでその内容を記載する。設定は Terraform で実施する。

![Essential_Contacts_Terrform_設定構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/8b4b2a44-dc80-87e8-0b82-713566135d43.png)


### API 有効化

対象プロジェクトに対して有効化を実施する

```tf
resource "google_project_service" "essentialcontacts_api_enable" {
  service = "essentialcontacts.googleapis.com"
}
```

### 通知先ドメインの制限

組織ポリシーで通知先ドメインを制限する

```tf
### [重要な連絡先] に追加できるメールアドレスのドメインのセットを定義
resource "google_organization_policy" "essentialcontacts_allowedContactDomains" {
  org_id     = "123456789" # 実環境の組織IDを入れる
  constraint = "essentialcontacts.allowedContactDomains"

  list_policy {
    allow {
      values = "@[email_domain]" # 連絡先メールアドレスのドメインを入れる
    }
  }
}
```

### 権限設定


```tf
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/folder
data "google_folder" "infrastructure_folder" {
  folder              = "123456789123" # 実環境のフォルダIDを入れる
  lookup_organization = true
}

data "google_folder" "service1_folder" {
  folder = "234567891234" # 実環境のフォルダIDを入れる
}
```

```tf
# IAM admin
## https://cloud.google.com/resource-manager/docs/managing-notification-contacts#manage-permissions
resource "google_organization_iam_binding" "org_essentialcontacts_admin" {
  org_id = split("/", data.google_folder.infrastructure_folder.organization)[1]
  role   = "roles/essentialcontacts.admin"

  members = [
    "group:gcp-organization-admin@[domain]", # 実環境 IAM メンバーを入れる
    "serviceAccount:terraform@[terraform-project-id].iam.gserviceaccount.com", # 実環境の Terraform でのサービスアカウントを入れる
  ]
}

# IAM viewer
## https://cloud.google.com/resource-manager/docs/managing-notification-contacts#view-permissions
resource "google_folder_iam_binding" "infra_essentialcontacts_viewer" {
  folder = data.google_folder.infrastructure_folder.id
  role   = "roles/essentialcontacts.viewer"

  members = [
    "group:gcp-network-admin@[domain]", # 実環境 IAM メンバーを入れる
  ]
}

resource "google_folder_iam_binding" "service1_essentialcontacts_viewer" {
  folder = data.google_folder.service1_folder.id
  role   = "roles/essentialcontacts.viewer"

  members = [
    "gcp-service1-admin@[domain]", # 実環境 IAM メンバーを入れる
  ]
}

```

### 通知先の設定

```tf
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/essential_contacts_contact
# https://cloud.google.com/resource-manager/docs/managing-notification-contacts#terraform
resource "google_essential_contacts_contact" "org_contact" {
  parent                              = data.google_folder.infrastructure_folder.organization
  email                               = "org.admin@xxx.xxx" # 組織管理者の連絡先メールアドレスを入れる
  language_tag                        = "ja"                               # https://cloud.google.com/resource-manager/docs/managing-notification-contacts#expandable-1
  notification_category_subscriptions = ["BILLING", "LEGAL", "SECURITY", ] # ALL, BILLING, LEGAL, PRODUCT_UPDATES, SECURITY, SUSPENSION, TECHNICAL, TECHNICAL_INCIDENTS 
}

resource "google_essential_contacts_contact" "infrastructure_contact" {
  parent                              = data.google_folder.infrastructure_folder.id
  email                               = "gcp-network-admin@xxx.xxx.xxx" # インフラ管理者の連絡先メールアドレスを入れる
  language_tag                        = "ja"
  notification_category_subscriptions = ["ALL", ] # ALL, BILLING, LEGAL, PRODUCT_UPDATES, SECURITY, SUSPENSION, TECHNICAL, TECHNICAL_INCIDENTS 
}

resource "google_essential_contacts_contact" "service1_contact" {
  parent                              = data.google_folder.service1_folder.id
  email                               = "gcp-service1-admin@xxx.xxx.xxx" # サービス1管理者の連絡先メールアドレスを入れる
  language_tag                        = "ja"
  notification_category_subscriptions = ["ALL", ] # ALL, BILLING, LEGAL, PRODUCT_UPDATES, SECURITY, SUSPENSION, TECHNICAL, TECHNICAL_INCIDENTS 
}
```

### テストメール

`IAM と管理` > `エッセンシャル コンタクト` でメールアイコンをクリックすると、テストメール送信ができる

![Essential_Contacts_Test_Mail_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/a7d1a777-c212-19e5-7b12-703f9730c495.png)

![Essential_Contacts_Test_Mail_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/de06c70b-385e-8eb5-67a5-e7ff8cef92c0.png)

下記のようなテストメールがくる

![Essential_Contacts_Test_Mail_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/b71646cc-64c6-b6ca-255c-ed43bbdab2e4.png)

以上で設定・テスト完了

## おわりに
Essential Contacts を使用して、IAM メンバーの連絡先と分離して、Google Cloud サービスの連絡先(メール先)を設定ができた
企業利用などで連絡先の分離・固定やメンバーに依存しない連絡先管理が必要な際に参考になればと思う

## github
下記 GitHub で Terraform Code 全体例を記載している

https://github.com/suzuyu/terraform-public/tree/main/env/homelab/essentialcontacts

## 参考

https://cloud.google.com/resource-manager/docs/managing-notification-contacts

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