# GuardDuty を AWS Organizations で全社一括統制する：委任管理者・自動有効化（ALL）・全リージョン・Terraform マルチリージョン実装

> GuardDutyをAWS Organizationsで全社統制する実装ガイド。なぜ管理アカウントで運用せず委任管理者（専用セキュリティアカウント）に集約するのか、招待方式からの移行、auto_enable_organization_membersをALLにする理由、保護プランの組織自動有効化、グローバルサービスイベントを取りこぼさない全リージョン戦略、provider alias/for_eachによるTerraformマルチリージョン実装、そしてアカウント間の最小権限境界までをコードで解説します。

- 公開日: 2026-06-27
- 著者: 友田 陽大
- タグ: セキュリティ, AWS, GuardDuty, Terraform, AWS Organizations
- URL: https://tomodahinata.com/blog/aws-guardduty-multi-account-organizations-delegated-administrator-terraform-guide
- カテゴリ: Amazon GuardDuty 本番運用
- 総合ガイド: https://tomodahinata.com/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide

## 要点

- マルチアカウントの GuardDuty は AWS Organizations 統合が公式推奨。運用は管理（payer）アカウントではなく、専用のセキュリティ用アカウントを『委任管理者（delegated administrator）』に指名して集約する——最小権限の原則そのもの
- 委任管理者は管理アカウントで登録し、組織設定（auto_enable_organization_members）は委任管理者アカウントで設定する。`ALL` を選べば既存＋将来の全メンバーが対象になり、サイレントな穴が生まれない（`NEW` だけだと既存アカウントが永久に対象外になり得る）
- GuardDuty はリージョン単位。委任管理者の指名・組織設定・自動有効化は『有効化したい各リージョンで』繰り返す必要がある。グローバルサービスイベント（IAM/STS/S3/CloudFront/Route 53）は各リージョンに複製・処理されるため、未使用・opt-in リージョンも含め全リージョン有効化が公式推奨
- Terraform では provider alias と for_each でリージョンを増やしてもコードが線形に増えない構造にする。委任管理者の登録（管理アカウント側）と組織設定・保護プラン自動有効化（委任管理者アカウント側）は別 state・別ロールで分離する
- 新規アカウントが組織に join すると ALL の設定下で自動的に GuardDuty 配下に入る。アカウント追加のたびに『入れ忘れ』が起きる余地を、運用の注意ではなく構造で消せる

---

「GuardDuty、本番アカウントでは有効にしたんですけど……ステージングと監査用アカウントは、まだなんですよね」——マルチアカウントの AWS を運用しているチームと話すと、ほぼ必ずこの台詞が出ます。

アカウントが増えるほど、GuardDuty の「入れ忘れ」が静かに増えます。新しくアカウントを切るたびに、誰かが手で有効化し、全リージョンで有効化し、保護プランを揃える——この手作業は、**忘れた瞬間に「監視されていないアカウント」という穴**を生みます。そして攻撃者は、いちばん手薄なアカウント・いちばん手薄なリージョンを突いてきます。

この記事は、**Amazon GuardDuty を AWS Organizations で全社一括統制する**ための実装ガイドです。単一アカウントでの有効化は[こちらのピラー記事](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide)で扱っているので、本記事はその先——**「組織全体に、人手を介さず、漏れなく GuardDuty を広げ、維持する」**という統制レイヤーに絞って深掘りします。委任管理者モデル、なぜ管理アカウントで運用しないのか、`auto_enable_organization_members` を `ALL` にする理由、全リージョン戦略、そして provider alias と `for_each` を使った **Terraform のマルチリージョン実装**までを通します。

題材として、私がマルチアカウント AWS 上の[サーバーレス決済プラットフォーム](/case-studies/payment-platform-reliability)で **本番／ステージング／監査用にアカウントを分離し、IAM・可観測性・DR を横断実装**した経験——**実際の金銭・カーボンクレジット・地域通貨を扱うため、アカウントの増減に対して「監視の網に穴を作らない」ことが要件だった**——という視点も交えます。

> **この記事のルール**：委任管理者・自動有効化・リージョン・Terraform リソースの仕様は **AWS 公式ドキュメントおよび Terraform AWS Provider のリソース仕様（2026年6月時点）** に基づきます。GuardDuty はリージョン単位・仕様は改定されるため、本番投入前に必ず公式の最新情報を確認してください。そして大前提——**GuardDuty は検知の一層であり、WAF・最小権限の IAM・暗号化を代替しません**。本記事の統制設計そのものも、**「管理アカウントに権限を集中させない」最小権限の原則**に貫かれています。

---

## 0. メンタルモデル：誰が・どこで・何を設定するのか

組織での GuardDuty 統制が混乱する最大の原因は、**「どのアカウントで、どのリソースを設定するのか」が3者に分かれている**ことです。ここを最初に固定します。

> **GuardDuty の組織統制 ＝「管理アカウントが委任管理者を“指名”し、委任管理者が全メンバーを“統制”し、メンバーが実際に“監視される”」という三層の役割分担。設定するリソースもアカウントも、それぞれ別。**

| 役割 | アカウント | ここで設定するもの |
| --- | --- | --- |
| **管理アカウント（payer / management）** | 組織のルート支払いアカウント | 委任管理者の**指名のみ**（`aws_guardduty_organization_admin_account`） |
| **委任管理者（delegated administrator）** | 専用のセキュリティ／監査アカウント | detector、組織設定（自動有効化）、保護プランの組織自動有効化、finding 集約 |
| **メンバーアカウント** | 本番・ステージング・各サービス | （委任管理者が自動有効化するので、原則ノータッチ） |

ここから3つの帰結が出ます。これが本記事のすべての土台です。

1. **委任管理者は「管理アカウント」であってはならない（推奨されない）。** AWS 公式は *"the AWS security best practices follow the principle of least privilege and doesn't recommend"* と明言し、**管理アカウントを委任管理者にすることを推奨していません**。専用のセキュリティ用アカウントを委任管理者にします。理由は単純で、**支払い・組織管理・脅威検知という性質の違う責務を1アカウントに集めると、その1アカウントの侵害が全社を巻き込む**からです（SRP／最小権限）。

2. **設定するアカウントが2つに割れる。** 委任管理者の「指名」は**管理アカウントで**、組織設定や自動有効化は**委任管理者アカウントで**実行します。Terraform で言えば、**2つの異なる provider（＝2つの異なるロール／state）**が必要になります。ここを混同すると、`AccessDenied` か「設定したのに効かない」で詰まります。

3. **GuardDuty はリージョン単位。組織統制も「リージョンごと」に繰り返す。** AWS Organizations はグローバルですが、GuardDuty は Regional です。公式いわく *"a delegated GuardDuty administrator account is Regional"*。委任管理者の指名も、組織設定も、**有効化したい各リージョンで**行う必要があります。だからこそ後半で **Terraform の `for_each` × provider alias** が効いてきます。

この3点を押さえると、組織統制は **「①委任管理者を正しいアカウントに指名し → ②全メンバーを自動有効化し → ③それを全リージョンに展開する」** の3ステップだと分かります。順に作ります。

---

## 1. なぜ管理アカウントで運用しないのか：委任管理者モデル

### 1.1 委任管理者（delegated administrator）とは

AWS Organizations では、管理アカウントが組織内の任意のアカウントを **委任管理者（delegated GuardDuty administrator account）** に指名できます。公式の定義はこうです——*"the management account can designate any account within this organization as the delegated GuardDuty administrator account"*。指名されたアカウントは、**そのリージョンで、組織内の全メンバーアカウントの GuardDuty を有効化・管理できる**ようになります（*"the administrator account can enable and manage GuardDuty for all the member accounts in the organization within that Region"*）。

### 1.2 管理アカウントを委任管理者にしない理由

「管理アカウントでやればロールも1つで済むし楽では？」——技術的には可能です。公式も *"Your organization's management account can be the delegated GuardDuty administrator account"* と認めています。**しかし続けて *"However, the AWS security best practices follow the principle of least privilege and doesn't recommend this configuration"* と明確に推奨しません。**

理由を構造で言語化します。

- **侵害の影響範囲（blast radius）を分ける。** 管理アカウントは「組織の作成・アカウントの追加削除・一括請求」という、組織で最も強い権限を持ちます。ここに脅威検知の運用権限まで足すと、**1アカウントの侵害＝組織全体の支配＋全検知の無効化**になりかねません。
- **日常運用するアカウントを最小化する。** 委任管理者では finding のトリアージ、抑制ルールの編集、保護プランの調整など**日常的な操作**が発生します。これを「めったに触らないべき管理アカウント」で行うのは、操作ミス・過剰権限の温床です。
- **監査の独立性。** セキュリティ専用アカウントに検知・集約を寄せると、「誰が検知設定を変えたか」の監査線が、組織運用の操作ノイズと混ざりません。

決済プラットフォームで **本番／ステージング／監査用にアカウントを分離**したのも同じ思想です。**「強い権限を持つアカウントほど、日常的に触らない」**——GuardDuty の委任管理者は、この原則を組織レベルで体現する仕組みです。専用の `security-tooling`（または `audit`）アカウントを委任管理者にします。

### 1.3 委任管理者まわりの“硬い制約”（公式）

設計前に知っておくべき公式の制約を表で固定します。これを知らないと後で詰みます。

| 制約 | 内容（公式） |
| --- | --- |
| **メンバー上限** | 委任管理者1つあたり **最大 50,000 メンバー**（*"a maximum of 50,000 members"*）。超過すると CloudWatch / Health Dashboard / メールで通知 |
| **リージョン単位** | 委任管理者は Regional。**有効化したい各リージョンで指名が必要**（*"must be added through AWS Organizations in each desired Region"*） |
| **全リージョンで同一アカウント** | 全リージョンで**同じアカウント**を委任管理者にする必要がある。リージョンごとに別の委任管理者は**不可** |
| **委任管理者の変更は検知を止めない** | 委任管理者を外しても、メンバーの GuardDuty は有効のまま（*"GuardDuty still remains enabled for all these member accounts"*） |

特に2行目・3行目が Terraform 設計に直結します。「リージョンごとに指名が要る」かつ「全リージョンで同一アカウント」——つまり **同じ `admin_account_id` を、複数リージョンに対して繰り返し適用する**コードになります（後述）。

---

## 2. Organizations 方式 vs 招待方式（と移行）

GuardDuty でマルチアカウントを束ねる方法は2つあります。公式は **AWS Organizations 統合を明確に推奨**しています（*"GuardDuty recommends that you integrate with AWS Organizations"*）。

| 観点 | **AWS Organizations 方式（推奨）** | 招待方式（レガシー） |
| --- | --- | --- |
| アカウントの紐付け | 組織のメンバーシップから自動 | 管理者が招待を送り、各メンバーが**承認** |
| 新規アカウントの取り込み | **自動有効化（ALL/NEW）で自動** | 手動で都度招待・承認 |
| スケール | 大規模向き（最大 50,000） | 小規模・組織外アカウント向き |
| 取りこぼしリスク | **低い**（構造的に自動） | 高い（承認漏れ・招待漏れ） |
| 主な用途 | 同一組織のマルチアカウント統制 | 組織に入っていない外部アカウントを一時的に束ねる |

### 2.1 どちらを選ぶか

**同じ AWS Organizations 配下のアカウント群を統制するなら、Organizations 方式の一択**です。招待方式は「組織のメンバーが招待を承認する」という人手のステップが各アカウントに発生し、これが**取りこぼしの温床**になります。承認を忘れたアカウントは、永久に監視外のまま残り得ます。

招待方式が今も価値を持つのは、**「組織に属していない外部アカウント（別組織・別取引先のアカウント）を一時的に finding 集約に加えたい」**といった限定ケースです。本記事のテーマ（全社統制）では Organizations 方式で進めます。

### 2.2 招待方式から Organizations 方式への移行

既に招待方式で運用していて Organizations 方式へ寄せる場合、考え方はシンプルです。

1. 管理アカウントで GuardDuty の**委任管理者を指名**する（次章）。
2. 委任管理者で **`auto_enable_organization_members = "ALL"`** を設定する。
3. 招待方式で紐付いていたメンバーは、組織のメンバーとして委任管理者の管理下に**統合される**。なお委任管理者の50,000上限は *"includes member accounts that are added through AWS Organizations or those who accepted the GuardDuty administrator account's invitation"* とあり、**招待経由のメンバーも同じ枠で数える**点に注意します。

移行時の鉄則は **「既存メンバーを取りこぼさないために、`NEW` ではなく `ALL` を選ぶ」**ことです（理由は次章）。移行は本番投入前に、サンプル finding で「委任管理者に finding が集約されるか」を必ず検証します（[ピラー記事](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide)の `create-sample-findings` 参照）。

---

## 3. 委任管理者を指名する：管理アカウント側の Terraform

ここからコードです。**まず管理アカウントで委任管理者を“指名”するだけ**。これ自体は GuardDuty の中身を何も設定しません——「このアカウントに GuardDuty 管理を委ねる」という宣言だけです。

```hcl
# ──────────────────────────────────────────────────────────────
# 【管理(management/payer)アカウントで実行する provider】
# このスタックは「委任管理者の指名」だけを担う。中身の設定はしない。
# ──────────────────────────────────────────────────────────────
provider "aws" {
  alias  = "management"
  region = "ap-northeast-1"
  assume_role {
    # 管理アカウントの「組織管理用ロール」を引き受ける。
    # 日常運用ではめったに使わない、強い権限のロール。
    role_arn = "arn:aws:iam::${var.management_account_id}:role/OrgGuardDutyAdminSetup"
  }
}

# GuardDuty の委任管理者を、専用 security アカウントに指名する。
# これは「指名」であって、GuardDuty の検知設定ではない点に注意。
resource "aws_guardduty_organization_admin_account" "delegate" {
  provider         = aws.management
  admin_account_id = var.security_account_id # 例: 専用 security-tooling / audit アカウント
}
```

> **`admin_account_id` は管理アカウントの ID ではない**：ここに入れるのは**委任先**（security アカウント）の ID です。混同して管理アカウント自身の ID を入れると、まさに 1 章で避けたかった「管理アカウントが委任管理者」という非推奨構成になります。

この `aws_guardduty_organization_admin_account` を適用すると、AWS が裏側で **GuardDuty のサービスにリンクされたロール**を委任管理者アカウントに用意し、委任管理者が組織 API を呼べる状態になります。指名した瞬間、**そのリージョンでは委任管理者アカウントの GuardDuty が自動で有効**になります（公式：*"GuardDuty gets enabled automatically only in the current AWS Region"*）。

---

## 4. 全メンバーを自動有効化する：委任管理者側の Terraform

指名が済んだら、**今度は委任管理者アカウント側の provider** に切り替えて、組織設定を入れます。ここが統制の心臓部です。

```hcl
# ──────────────────────────────────────────────────────────────
# 【委任管理者(security-tooling)アカウントで実行する provider】
# detector / 組織設定 / 保護プラン自動有効化 は、すべてこちら側で行う。
# ──────────────────────────────────────────────────────────────
provider "aws" {
  alias  = "security"
  region = "ap-northeast-1"
  assume_role {
    role_arn = "arn:aws:iam::${var.security_account_id}:role/GuardDutyDelegatedAdmin"
  }
}

# 委任管理者アカウント自身の detector。
# 指名時に自動有効化されるが、Terraform 管理下に置いて構成をコード化する。
resource "aws_guardduty_detector" "security" {
  provider                     = aws.security
  enable                       = true
  finding_publishing_frequency = "FIFTEEN_MINUTES" # 自動対応の遅延を縮める（ピラー記事 6章）
}

# 組織メンバーの自動有効化。これが「全社に漏れなく広げる」中核。
#   ALL  = 既存 + 将来すべてのアカウントを有効化（推奨：サイレントな穴を作らない）
#   NEW  = 今後 join するアカウントのみ（既存は対象外のまま残り得る）
#   NONE = 自動有効化しない
resource "aws_guardduty_organization_configuration" "this" {
  provider                         = aws.security
  detector_id                      = aws_guardduty_detector.security.id
  auto_enable_organization_members = "ALL"
}
```

`aws_guardduty_organization_configuration` の必須引数は `detector_id` と **`auto_enable_organization_members`**（値は `"ALL"` / `"NEW"` / `"NONE"`）です。

> **【重要】旧 `auto_enable`（boolean）は使わない**：かつての `auto_enable = true/false` や `datasources { ... }` ブロックは **deprecated** で、保護プランごとの組織設定は後述の `aws_guardduty_organization_configuration_feature` に分離されました。新規構築では **`auto_enable_organization_members`（3値の文字列）＋ `_feature` リソース**で書きます。古いブログ記事のコードをコピペすると deprecation 警告や意図しない挙動の原因になります。

### 4.1 なぜ `ALL` を選ぶのか——`NEW` のサイレントな穴

3値の選択は「セキュリティの網に穴を作るかどうか」を直接決めます。

| 値 | 対象 | リスク |
| --- | --- | --- |
| **`ALL`（推奨）** | **既存＋将来**の全メンバー | なし。設定時点で組織にいる全アカウントが即対象になる |
| `NEW` | **今後 join する**メンバーのみ | **既存アカウントが永久に対象外**のまま残り得る（サイレントな穴） |
| `NONE` | 自動有効化しない | メンバーごとに手動管理。取りこぼし多発 |

**`NEW` の落とし穴**は深刻です。`NEW` を選ぶと、**設定を入れた“その瞬間”に既に組織にいたアカウントは、自動有効化の対象になりません**。新規アカウントだけが対象になるため、**既存の本番・ステージングアカウントが GuardDuty なしのまま放置**され得ます。「全社で漏れなく検知する」というセキュリティの目的に対して、`NEW` は構造的な穴です。

さらに公式は **opt-in リージョンでの `NEW` の順序依存**という罠も挙げています。`NEW` 運用では「①メンバーが opt-in リージョンを有効化 → ②そのメンバーを組織に追加」の順を守らないと、*"the member account is no longer new to the organization"* となり `NEW` が効きません。**`ALL` ならこの順序問題自体が消える**（*"the order of these steps is not relevant"*）——これも `ALL` を推す実務的な理由です。

意図的に GuardDuty から除外したいアカウント（たとえばサンドボックス）がある場合のみ、`ALL` のまま**個別にそのアカウントだけ無効化**する方が、`NEW`/`NONE` で全体を緩めるより安全です。

### 4.2 新規アカウントが join したらどうなるか

`ALL`（または `NEW`）を設定しておくと、**組織に新しく作られた／招待されたアカウントは、人手を介さず自動的に GuardDuty 配下に入ります**。これが Organizations 方式の最大の価値です。

決済プラットフォームのように **アカウントを役割ごとに分離**し、サービス追加のたびにアカウントを切る運用では、これが効きます——**「新しいアカウントを作ったけど GuardDuty 入れ忘れた」という事故が、構造的に起きなくなる**。運用の注意深さに頼るのをやめ、設定（`ALL`）に肩代わりさせるわけです。

---

## 5. 保護プランも組織で自動有効化する（per-feature）

基盤検知だけでなく、**S3 Protection・Runtime Monitoring などの保護プランも「組織全体で自動有効化」**できます。使うのは `aws_guardduty_organization_configuration_feature` です。

```hcl
# S3 Protection を組織全体で自動 ON。
# 全アカウントで S3 データイベントを監視し、ETD の S3 攻撃シーケンス相関を全社で効かせる。
resource "aws_guardduty_organization_configuration_feature" "s3_org" {
  provider    = aws.security
  detector_id = aws_guardduty_detector.security.id
  name        = "S3_DATA_EVENTS"
  auto_enable = "ALL" # ここも ALL（既存+将来の全メンバー）
}

# Runtime Monitoring を組織で自動 ON し、各環境のエージェント配置も自動管理させる。
# ★コストが vCPU 比例で増えるため、「全社一律 ALL」は慎重に。重要ワークロードに絞る判断もあり。
resource "aws_guardduty_organization_configuration_feature" "runtime_org" {
  provider    = aws.security
  detector_id = aws_guardduty_detector.security.id
  name        = "RUNTIME_MONITORING"
  auto_enable = "ALL"

  additional_configuration {
    name        = "EKS_ADDON_MANAGEMENT"         # EKS のエージェントを自動デプロイ・更新
    auto_enable = "ALL"
  }
  additional_configuration {
    name        = "ECS_FARGATE_AGENT_MANAGEMENT" # Fargate タスクにサイドカーを自動注入
    auto_enable = "ALL"
  }
  additional_configuration {
    name        = "EC2_AGENT_MANAGEMENT"         # EC2 のエージェントを SSM 経由で自動管理
    auto_enable = "ALL"
  }
}
```

`aws_guardduty_organization_configuration_feature` の必須引数は **`detector_id` / `name` / `auto_enable`**（`auto_enable` は `ALL`/`NEW`/`NONE`）です。`name` に指定できる代表的な保護プラン機能は次のとおりです。

| `name`（feature） | 監視対象 | 組織自動有効化の判断 |
| --- | --- | --- |
| `S3_DATA_EVENTS` | CloudTrail の S3 データイベント | **`ALL` が定番**（安価・効果大・ETD 相関を全社で広げる） |
| `EKS_AUDIT_LOGS` | EKS 監査ログ（コントロールプレーン） | EKS を使う組織なら `ALL`、使わないなら不要 |
| `RUNTIME_MONITORING` | コンテナ／ホスト内のプロセス・syscall | **vCPU 課金で最も高い**。全社 `ALL` か重要WLに絞るかを要判断 |
| `EBS_MALWARE_PROTECTION` | EC2 起因 finding 時に EBS をエージェントレススキャン | EC2 中心なら `ALL` |
| `RDS_LOGIN_EVENTS` | Aurora / RDS のログインアクティビティ | DB を持つ組織で有効 |
| `LAMBDA_NETWORK_LOGS` | Lambda のネットワーク活動（VPC Flow Logs） | サーバーレス中心なら有効 |

> **トレードオフの言語化（per-feature の `ALL` は一律ではない）**：基盤検知と S3 Protection は **全社 `ALL` が費用対効果で勝ちます**。一方 **Runtime Monitoring は vCPU 比例課金**なので、「全社一律 `ALL`」が必ずしも最適とは限りません。組織の検知網羅性とコストの綱引きは、[GuardDuty のコスト最適化記事](/blog/aws-guardduty-cost-optimization-pricing-finops-guide)で詳しく扱います——**委任管理者からはメンバーアカウント別の想定使用量が見える**ので、まず可視化してから「どの feature を `ALL` にし、どれを限定するか」を決めるのが正攻法です。

> **`RUNTIME_MONITORING` と `EKS_RUNTIME_MONITORING` は排他**：Terraform Provider 上、*"Only one of two features EKS_RUNTIME_MONITORING or RUNTIME_MONITORING can be added"*。新規は統合版の `RUNTIME_MONITORING` を使い、`additional_configuration` で EKS/ECS/EC2 のエージェント管理を個別に制御するのが現行の書き方です。

---

## 6. 全リージョン戦略：グローバルイベントを取りこぼさない

ここが組織統制で最も誤解されるポイントです。**「東京リージョンだけ GuardDuty を入れておけば十分」は危険**です。

### 6.1 なぜ未使用リージョンも有効化するのか

GuardDuty はリージョン単位のサービスです。そして **IAM・STS・S3・CloudFront・Route 53 などのグローバルサービスのイベント**は、特別な扱いを受けます。公式の説明はこうです——GuardDuty はこれらのグローバルサービスイベント（GSE）を *"replicates those events and processes them in each Region where you have enabled GuardDuty"*。つまり**グローバルイベントは、あなたが GuardDuty を有効化している全リージョンに複製・処理される**。

これが意味するのは——**GuardDuty を有効化していないリージョンでは、これらグローバルイベントの一部が処理されない**。攻撃者がそこを突きます。公式も *"Threat actors can potentially launch attacks through global services... They can attempt to create unauthorized resources to exploit Regions where you have limited presence"* と警告し、結論として **「全リージョンで有効化すべき」**（*"We recommend that you enable GuardDuty in all AWS Regions available in your AWS account"*）。default リージョンも opt-in リージョンも対象です（*"including both default and opt-in Regions"*）。

> **finding のリージョン値の注意**：グローバルイベント由来の finding は、**finding の `Region` 値が、実際に検知したリージョンと異なる**ことがあります。公式は *"a finding might show us-east-1 as the Region even if GuardDuty creates the detection in a different Region"* と注意しています。自動対応（EventBridge）でリージョンをキーに分岐するとき、**グローバルイベントは想定外のリージョン値で飛んでくる**ことを織り込んでおきます。

### 6.2 リージョンごとに「指名 → 組織設定」を繰り返す

5 章までの「指名（管理アカウント）→ 組織設定・保護プラン（委任管理者）」という一連を、**有効化したい各リージョンで繰り返す**必要があります。公式：委任管理者は *"must be added through AWS Organizations in each desired Region"*、かつ**全リージョンで同一の委任管理者アカウント**を使う必要があります。

手で全リージョン × 各リソースを設定するのは非現実的です。ここで **Terraform の provider alias × `for_each`** が本領を発揮します。

### 6.3 opt-in リージョンの注意

opt-in リージョン（アジアパシフィックの一部など、明示的に有効化が必要なリージョン）には固有の注意があります。公式いわく、**委任管理者が opt-in リージョンから opt-out すると、`NEW`/`ALL` 設定でも、現在 GuardDuty が無効なメンバーを有効化できなくなる**ことがあります。さらに前述の **`NEW` の順序依存問題**も opt-in リージョン特有です。**`ALL` を採れば順序問題は回避できる**ため、ここでも `ALL` 推奨が効きます。

---

## 7. Terraform：provider alias × for_each によるマルチリージョン実装

「リージョンを増やしてもコードが線形に膨らまない」構造を作ります。鍵は **(1) リージョンごとに provider alias を持つ、(2) 委任管理者の登録と組織設定で state を分ける**ことです。

### 7.1 設計：state とロールを2つに割る

| スタック | 実行アカウント | ロール | 責務 |
| --- | --- | --- | --- |
| **`org-admin-registration`** | 管理アカウント | `OrgGuardDutyAdminSetup`（強い・低頻度） | 委任管理者の指名（全リージョン分） |
| **`guardduty-org-config`** | 委任管理者アカウント | `GuardDutyDelegatedAdmin`（日常運用） | detector・組織設定・保護プラン（全リージョン分） |

**2つに割る理由**は、まさに 1 章の最小権限です。管理アカウントの強権ロールで日常運用（保護プランの調整など）を回したくない。委任管理者の運用ロールに「アカウント指名」の権限を持たせたくもない。**state を分ければ、apply に使うロールも自然に分かれます**。state 分離と drift 検知の考え方は[Terraform モジュール設計の記事](/blog/terraform-module-design-state-isolation-drift-detection-guide)で深掘りしています。

### 7.2 スタック①：委任管理者の指名（管理アカウント・全リージョン）

```hcl
# variables.tf
variable "guardduty_regions" {
  description = "GuardDuty を有効化する全リージョン（未使用・opt-in 含む）"
  type        = set(string)
  default     = ["ap-northeast-1", "us-east-1", "eu-west-1"] # 実際は対象を網羅する
}
variable "management_account_id" { type = string }
variable "security_account_id" { type = string }

# 各リージョンの provider を alias で定義する。
# ★ Terraform の制約: provider は for_each で動的生成できないため、対象リージョンを明示列挙する。
provider "aws" {
  alias  = "mgmt_apne1"
  region = "ap-northeast-1"
  assume_role { role_arn = "arn:aws:iam::${var.management_account_id}:role/OrgGuardDutyAdminSetup" }
}
provider "aws" {
  alias  = "mgmt_use1"
  region = "us-east-1"
  assume_role { role_arn = "arn:aws:iam::${var.management_account_id}:role/OrgGuardDutyAdminSetup" }
}
provider "aws" {
  alias  = "mgmt_euw1"
  region = "eu-west-1"
  assume_role { role_arn = "arn:aws:iam::${var.management_account_id}:role/OrgGuardDutyAdminSetup" }
}

# 各リージョンで同一の security アカウントを委任管理者に指名する。
# 全リージョンで同じ admin_account_id（公式の必須要件）。
resource "aws_guardduty_organization_admin_account" "apne1" {
  provider         = aws.mgmt_apne1
  admin_account_id = var.security_account_id
}
resource "aws_guardduty_organization_admin_account" "use1" {
  provider         = aws.mgmt_use1
  admin_account_id = var.security_account_id
}
resource "aws_guardduty_organization_admin_account" "euw1" {
  provider         = aws.mgmt_euw1
  admin_account_id = var.security_account_id
}
```

> **Terraform の現実的な制約**：`provider` ブロック自体は `for_each` で動的生成できません（provider の数はプラン前に確定している必要がある）。そのため**リージョンごとに provider alias を明示列挙**し、各 alias に対してリソースを書きます。リージョンが多い場合は、**この列挙部分をモジュール化**するか、後述のように「リージョンを引数に取る子モジュール」を `for_each` で呼ぶ構成に寄せます。

### 7.3 スタック②：組織設定をリージョン横断モジュールで（委任管理者）

保護プランや組織設定は項目が多いので、**「1リージョン分の設定」を子モジュールに切り出し**、リージョンごとに provider を渡して呼びます。これで「リージョン追加＝module ブロックを1つ足す」だけになります。

```hcl
# modules/guardduty-org-region/variables.tf
variable "finding_publishing_frequency" {
  type    = string
  default = "FIFTEEN_MINUTES"
}

# modules/guardduty-org-region/main.tf
# このモジュールは「呼び出し側が渡した1つの provider（=1リージョン）」に対して
# detector + 組織設定 + 保護プランを一式作る。リージョンの知識はモジュール内に持たない（ETC）。
# 呼び出し側から provider を受け取る前提なので、configuration_aliases を宣言する。
terraform {
  required_providers {
    aws = {
      source                = "hashicorp/aws"
      configuration_aliases = [aws]
    }
  }
}

resource "aws_guardduty_detector" "this" {
  enable                       = true
  finding_publishing_frequency = var.finding_publishing_frequency
}

resource "aws_guardduty_organization_configuration" "this" {
  detector_id                      = aws_guardduty_detector.this.id
  auto_enable_organization_members = "ALL" # 全社・漏れなく
}

resource "aws_guardduty_organization_configuration_feature" "s3" {
  detector_id = aws_guardduty_detector.this.id
  name        = "S3_DATA_EVENTS"
  auto_enable = "ALL"
}
```

```hcl
# 呼び出し側（委任管理者アカウントの provider を各リージョン分用意して渡す）
provider "aws" {
  alias  = "sec_apne1"
  region = "ap-northeast-1"
  assume_role { role_arn = "arn:aws:iam::${var.security_account_id}:role/GuardDutyDelegatedAdmin" }
}
provider "aws" {
  alias  = "sec_use1"
  region = "us-east-1"
  assume_role { role_arn = "arn:aws:iam::${var.security_account_id}:role/GuardDutyDelegatedAdmin" }
}

# リージョンを足したいときは、provider alias と module 呼び出しを1つ追加するだけ。
module "guardduty_apne1" {
  source    = "./modules/guardduty-org-region"
  providers = { aws = aws.sec_apne1 }
}
module "guardduty_use1" {
  source    = "./modules/guardduty-org-region"
  providers = { aws = aws.sec_use1 }
}
```

> **適用順序（依存関係）**：スタック②（組織設定）は、スタック①（委任管理者の指名）が**そのリージョンで完了した後**でないと失敗します。指名されていないアカウントでは、組織設定 API を呼ぶ権限がないからです。**①→②の順で apply** します（別 state なので、CI のジョブ依存で順序を保証するのが堅牢）。鍵レスな CI からの apply は[OIDC 鍵レス CI/CD の記事](/blog/github-actions-oidc-keyless-cicd-aws-gcp-guide)の構成（`plan` と `apply` でロールを分ける）に乗せられます。

### 7.4 メンバー個別のオーバーライド

`ALL` で全社一律にしつつ、**特定アカウントだけ保護プランを変えたい**（例：サンドボックスだけ Runtime Monitoring を切る）場合は、委任管理者から**メンバーアカウントの detector を個別に上書き**します。Terraform では `aws_guardduty_detector_feature` をメンバーの detector に対して適用するか、`UpdateMemberDetectors` 相当の操作で個別管理します。原則は **「全社デフォルトは `ALL`、例外は明示的に1アカウントずつ」**——`NEW`/`NONE` で全体を緩めて穴を作るより、構造的に安全です。

---

## 8. finding 集約・publishing・ランディングゾーン

### 8.1 finding は委任管理者に自動集約される

組織を組むと、**全メンバー・全リージョンの finding が委任管理者アカウントに自動集約**されます（公式：委任管理者は *"review all generated findings"* できる）。委任管理者は組織全体のセキュリティ姿勢を一望でき、メンバーアカウントごとの finding と想定使用量を確認できます。これが「セキュリティ専用アカウントに検知を寄せる」という設計の実利です。

### 8.2 組織レベルで S3 へエクスポート・Security Hub へ集約

委任管理者を起点に、finding を **S3 にエクスポート**（長期保管・分析）し、**AWS Security Hub CSPM** に流して他の検知（Macie 等）と横断的に優先順位づけします。深掘り調査は **Amazon Detective**。「GuardDuty で検知 → 委任管理者で集約 → Security Hub で横断 → Detective で深掘り」が組織運用の王道です。

finding を行動に変える **EventBridge → 冪等な自動対応**は、本記事の範囲を超えるため[自動対応・インシデントレスポンスの記事](/blog/aws-guardduty-eventbridge-automated-remediation-incident-response-guide)に譲ります。組織構成では、**委任管理者アカウントに集約された finding を起点に EventBridge ルールを組む**のが定石です。

### 8.3 ランディングゾーン / Control Tower との関係

新規に組織を設計するなら、**AWS Control Tower / ランディングゾーン**の文脈に乗せるのが自然です。Control Tower は典型的に **`Audit` アカウントと `Log Archive` アカウント**を用意します。GuardDuty の委任管理者は、この **`Audit`（または専用 `Security`）アカウントに割り当てる**のが定番配置です——本記事で一貫して言ってきた「管理アカウントではなく専用セキュリティアカウント」と完全に一致します。

> **既存組織への後付け**：Control Tower を使っていなくても本記事の構成はそのまま適用できます。重要なのはツールではなく原則——**委任管理者を専用アカウントに置き、`ALL` で全リージョン自動有効化する**こと。Control Tower はそれを“規約として”敷いてくれるだけです。

---

## 9. アカウント間の最小権限境界（IAM 設計）

最後に、本記事で2つに割ったロールの**境界**を明示します。これは飾りではなく、統制設計の本体です。

| ロール | 置き場所 | 許す主な操作 | 許さない操作 |
| --- | --- | --- | --- |
| `OrgGuardDutyAdminSetup` | 管理アカウント | `guardduty:EnableOrganizationAdminAccount` / `Disable...` / 関連 `organizations:*`（最小限） | 保護プラン調整・finding 操作・抑制ルール編集 |
| `GuardDutyDelegatedAdmin` | 委任管理者アカウント | `guardduty:UpdateOrganizationConfiguration` / `Update*Detector*` / `CreateFilter`（抑制）/ finding 参照 | アカウント指名（委任管理者の登録）・組織のアカウント追加削除 |

設計原則を言語化します。

- **指名権限と運用権限を交差させない。** 管理アカウントのロールは「指名・解除」まで。委任管理者のロールは「日常運用」まで。**どちらのロールも、もう一方の領域に踏み込めない**ようにします。これが侵害の影響範囲を分ける本体です。
- **管理アカウントの強権ロールは“低頻度・要承認”に。** `OrgGuardDutyAdminSetup` は委任管理者を変えるときくらいしか使いません。CI から触るなら、`environment` 承認ゲート付きの OIDC ロールに限定します（[OIDC 記事](/blog/github-actions-oidc-keyless-cicd-aws-gcp-guide)の environment 承認）。
- **`Resource` を絞れる API は絞る。** finding 参照系は読み取り専用ロールに、設定変更系は権限境界（permissions boundary）付きロールに分けます。
- **GuardDuty は IAM の代替ではない。** 念押しです。GuardDuty は「漏れた認証情報の悪用」を**検知**しますが、漏らさないための最小権限 IAM・鍵レス認証・暗号化は別途必要です。GuardDuty はこの多層防御の中で「組織横断で兆候を早く知らせる層」を担います。

---

## 10. まとめ：GuardDuty 組織統制チートシート

迷ったときの早見表です。

- **方式**：マルチアカウントは **AWS Organizations 統合が公式推奨**。招待方式は組織外アカウントを束ねる限定用途。移行時は **`ALL`** で既存メンバーを取りこぼさない。
- **委任管理者**：**管理（payer）アカウントでは運用しない**（公式が最小権限の観点で非推奨）。専用の `Security`/`Audit` アカウントを委任管理者に。指名は**管理アカウントで**（`aws_guardduty_organization_admin_account`）、組織設定は**委任管理者アカウントで**。
- **自動有効化**：`aws_guardduty_organization_configuration` の **`auto_enable_organization_members = "ALL"`**（既存＋将来）。`NEW` は既存アカウントがサイレントに対象外になる穴。**旧 `auto_enable`（boolean）/`datasources` ブロックは deprecated**——使わない。
- **保護プラン**：`aws_guardduty_organization_configuration_feature`（`name` + `auto_enable`）で組織自動有効化。S3 は `ALL` が定番、**Runtime Monitoring は vCPU 課金なので全社一律か限定かを要判断**。`RUNTIME_MONITORING` と `EKS_RUNTIME_MONITORING` は排他。
- **リージョン**：GuardDuty は Regional。**指名→組織設定を各リージョンで繰り返す**。**全リージョンで同一の委任管理者アカウント**が必須。グローバルイベント（IAM/STS/S3/CloudFront/Route 53）は全有効リージョンに複製・処理されるため、**未使用・opt-in 含め全リージョン有効化**。finding の `Region` 値は検知リージョンと異なり得る。
- **Terraform**：provider は `for_each` 不可 → **リージョンごとに alias を列挙**し、**1リージョン分を子モジュール化**して provider を渡す。**①指名（管理アカウント・強権ロール）と ②組織設定（委任管理者・運用ロール）で state とロールを分離**。①→②の順で apply。
- **新規アカウント**：`ALL` 下では組織に join したアカウントが**自動で GuardDuty 配下**に入る。入れ忘れが構造的に消える。
- **集約**：finding は委任管理者に**自動集約**。S3 エクスポート・Security Hub・Detective で横断。Control Tower の `Audit` アカウントが委任管理者の定番配置。
- **IAM 境界**：**指名権限と運用権限を交差させない**。GuardDuty は検知の一層であり、最小権限 IAM・鍵レス認証・暗号化を代替しない。

組織での GuardDuty は「全アカウントで手動有効化する作業」ではなく、**「委任管理者に集約し、`ALL` で自動有効化し、全リージョンに Terraform で展開する」という統制の設計**です。最大のレバレッジは、**アカウントが増減しても監視の網に穴が空かない構造**を、運用の注意ではなくコードで担保することにあります。

私はマルチアカウントの[サーバーレス決済プラットフォーム](/case-studies/payment-platform-reliability)で、**実際の金銭・カーボンクレジット・地域通貨を扱う基盤の IAM・可観測性・DR を横断実装**し、本番／ステージング／監査用のアカウント分離を「運用の注意深さ」ではなく**コードの構造**で支えてきました。GuardDuty の組織統制も同じ思想で設計します——**①委任管理者を専用アカウントに置いて影響範囲を分け、②`ALL` × 全リージョンで取りこぼしを構造的に消し、③Terraform のマルチリージョン構成で「リージョン追加＝1行追加」に保つ**。

**「自社のマルチアカウント AWS に GuardDuty をどう全社展開し、委任管理者をどこに置き、どのリージョン・どの保護プランを `ALL` にするか」——Organizations 設計から Terraform 実装、アカウント間の最小権限境界、finding 集約まで、一人 × 生成AI（Claude Code）で速く・安全に伴走できます。** 既存組織への後付けでも、要件整理の段階からでも、お気軽にご相談ください。

---

### 参考（公式ドキュメント）

- [Managing GuardDuty accounts with AWS Organizations](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_organizations.html) — 委任管理者の概念・50,000上限・Regional 制約・opt-in リージョンの注意・管理アカウントを委任管理者にしない推奨
- [Multiple accounts in Amazon GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_accounts.html) — Organizations 方式 vs 招待方式・委任管理者とメンバーの関係・公式推奨
- [Amazon GuardDuty Regions and endpoints](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_regions.html) — 全リージョン有効化の推奨・リージョン別の機能差
- [GuardDuty foundational data sources（global service events）](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_data-sources.html) — グローバルサービスイベント（IAM/STS/S3/CloudFront/Route 53）の全リージョン複製・処理、finding の Region 値が異なり得る注意
- [Terraform: aws_guardduty_organization_configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_organization_configuration) — `auto_enable_organization_members`（ALL/NEW/NONE）・`datasources` ブロックの deprecation
- [Terraform: aws_guardduty_organization_configuration_feature](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_organization_configuration_feature) — `name`/`auto_enable`・`additional_configuration`（EKS_ADDON_MANAGEMENT ほか）・RUNTIME_MONITORING と EKS_RUNTIME_MONITORING の排他
- [Terraform: aws_guardduty_organization_admin_account](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_organization_admin_account) — 管理アカウントで委任管理者を登録する `admin_account_id`
