Skip to main content
友田 陽大
Amazon GuardDuty in production
セキュリティ
AWS
GuardDuty
Terraform
AWS Organizations

Governing GuardDuty Org-Wide with AWS Organizations: Delegated Administrator, Auto-Enable (ALL), All Regions, and a Terraform Multi-Region Implementation

An implementation guide for governing GuardDuty org-wide with AWS Organizations. In code: why you consolidate to a delegated administrator (a dedicated security account) rather than operating from the management account, migrating from the invitation method, why you set auto_enable_organization_members to ALL, org auto-enablement of protection plans, an all-Regions strategy that doesn't miss global service events, a Terraform multi-region implementation with provider alias / for_each, and the least-privilege boundaries between accounts.

Published
Reading time
27 min read
Author
友田 陽大
Share
Contents

"GuardDuty, we did enable it in the production account… but the staging and audit accounts, not yet." — talk with teams running multi-account AWS, and almost without fail this line comes up.

The more accounts grow, the more quietly the "forgot to add GuardDuty" cases accumulate. Every time you carve out a new account, someone enables it by hand, enables it in all Regions, and aligns the protection plans — this manual work, the moment it's forgotten, creates a hole: an "unmonitored account." And attackers come at your weakest account, your weakest Region.

This article is an implementation guide for governing Amazon GuardDuty org-wide with AWS Organizations. Single-account enablement is covered in this pillar article, so this article digs into what comes after — the governance layer of "spreading and maintaining GuardDuty across the whole org, without human hands, with no gaps." It runs through the delegated-administrator model, why you don't operate from the management account, the reason for setting auto_enable_organization_members to ALL, the all-Regions strategy, and a Terraform multi-region implementation using provider alias and for_each.

As the subject matter, I'll weave in the perspective from my experience on a serverless payment platform on multi-account AWS — where I separated accounts for production / staging / audit and implemented IAM, observability, and DR across thembecause it handled actual money, carbon credits, and regional currencies, "not creating a hole in the monitoring net" against account additions and removals was a requirement.

The rule of this article: The specs for the delegated administrator, auto-enablement, Regions, and Terraform resources are based on the AWS official documentation and the Terraform AWS Provider resource specs (as of June 2026). Because GuardDuty is per-Region and specs get revised, always check the latest official information before going to production. And the major premise — GuardDuty is one layer of detection; it does not replace WAF, least-privilege IAM, or encryption. The governance design in this article itself is also run through with the principle of least privilege: "don't concentrate permissions in the management account."


0. Mental model: who configures what, and where

The biggest cause of confusion in org-level GuardDuty governance is that "in which account you configure which resource" is split across three parties. Let's pin this down first.

GuardDuty org governance = a three-tier division of roles: "the management account 'designates' the delegated administrator, the delegated administrator 'governs' all members, and the members are actually 'monitored.'" The resource you configure and the account differ for each.

RoleAccountWhat you configure here
Management account (payer / management)The org's root billing accountOnly the designation of the delegated administrator (aws_guardduty_organization_admin_account)
Delegated administratorA dedicated security / audit accountThe detector, the org setting (auto-enablement), org auto-enablement of protection plans, finding aggregation
Member accountsProduction, staging, each service(Since the delegated administrator auto-enables, in principle hands-off)

Three consequences follow from here. This is the foundation of everything in this article.

  1. The delegated administrator must not be the "management account" (not recommended). AWS officially states "the AWS security best practices follow the principle of least privilege and doesn't recommend" and does not recommend making the management account the delegated administrator. You make a dedicated security account the delegated administrator. The reason is simple: if you collect responsibilities of differing natures — billing, org management, threat detection — into one account, a compromise of that one account drags the whole org in (SRP / least privilege).

  2. The account you configure splits into two. The "designation" of the delegated administrator is done in the management account, while the org setting and auto-enablement are done in the delegated administrator account. In Terraform terms, you need two different providers (= two different roles / states). Confuse this and you get stuck with AccessDenied or "I configured it but it doesn't take effect."

  3. GuardDuty is per-Region. Org governance is also repeated "per Region." AWS Organizations is global, but GuardDuty is Regional. The official wording is "a delegated GuardDuty administrator account is Regional". The designation of the delegated administrator and the org setting both need to be done in each Region you want to enable. This is precisely why Terraform's for_each × provider alias pays off later.

Grasp these three points and you'll see org governance is the three steps "① designate the delegated administrator in the correct account → ② auto-enable all members → ③ roll that out to all Regions." Let's build them in order.


1. Why you don't operate from the management account: the delegated-administrator model

1.1 What is a delegated administrator?

In AWS Organizations, the management account can designate any account within the org as the delegated GuardDuty administrator account. The official definition is — "the management account can designate any account within this organization as the delegated GuardDuty administrator account". The designated account becomes able to enable and manage GuardDuty for all member accounts in the org within that Region ("the administrator account can enable and manage GuardDuty for all the member accounts in the organization within that Region").

1.2 Why not make the management account the delegated administrator

"If I do it in the management account, I get by with one role and it's easier, no?" — technically it's possible. The official docs even acknowledge "Your organization's management account can be the delegated GuardDuty administrator account". But they go on to clearly not recommend it: "However, the AWS security best practices follow the principle of least privilege and doesn't recommend this configuration".

Let me articulate the reasoning structurally.

  • Separate the blast radius of a compromise. The management account holds the strongest permissions in the org — "creating the org, adding/removing accounts, consolidated billing." Add threat-detection operational permissions on top, and a compromise of one account = control of the whole org + disabling of all detection.
  • Minimize the account you operate daily. With the delegated administrator, daily operations occur — triaging findings, editing suppression rules, adjusting protection plans. Doing this in "the management account, which you should rarely touch" is a breeding ground for operational mistakes and excessive permissions.
  • Audit independence. Consolidating detection and aggregation into a dedicated security account keeps the audit trail of "who changed the detection settings" from mixing with the operational noise of running the org.

Separating accounts for production / staging / audit on the payment platform was the same philosophy. "The stronger the permissions an account holds, the less you touch it daily" — GuardDuty's delegated administrator is a mechanism that embodies this principle at the org level. You make a dedicated security-tooling (or audit) account the delegated administrator.

1.3 The "hard constraints" around the delegated administrator (official)

Before designing, let's pin down the official constraints you should know in a table. Not knowing these will trap you later.

ConstraintContent (official)
Member capA maximum of 50,000 members per delegated administrator ("a maximum of 50,000 members"). Exceeding it triggers notification via CloudWatch / Health Dashboard / email
Per-RegionThe delegated administrator is Regional. Designation is needed in each Region you want to enable ("must be added through AWS Organizations in each desired Region")
Same account in all RegionsYou must make the same account the delegated administrator in all Regions. A different delegated administrator per Region is not allowed
Changing the delegated administrator doesn't stop detectionEven if you remove the delegated administrator, members' GuardDuty stays enabled ("GuardDuty still remains enabled for all these member accounts")

Rows 2 and 3 in particular tie directly into Terraform design. "Designation is needed per Region" and "the same account in all Regions" — that is, the code becomes one that applies the same admin_account_id repeatedly across multiple Regions (described later).


2. Organizations method vs. invitation method (and migration)

There are two ways to bundle multiple accounts with GuardDuty. The official docs clearly recommend AWS Organizations integration ("GuardDuty recommends that you integrate with AWS Organizations").

AspectAWS Organizations method (recommended)Invitation method (legacy)
Account associationAutomatic from org membershipThe administrator sends invitations, and each member approves
Onboarding new accountsAutomatic via auto-enablement (ALL/NEW)Manual invitation/approval each time
ScaleSuited for large scale (max 50,000)Small scale / accounts outside the org
Risk of missing accountsLow (structurally automatic)High (missed approvals / missed invitations)
Main useMulti-account governance within the same orgTemporarily bundling external accounts not in the org

2.1 Which to choose

If you're governing a set of accounts under the same AWS Organizations, the Organizations method is the only choice. The invitation method incurs a human step in each account — "an org member approves the invitation" — and this is a breeding ground for missing accounts. An account that forgot to approve can be left outside monitoring forever.

Where the invitation method still has value is limited cases like "I want to temporarily add an external account (a different org's / a business partner's account), not belonging to the org, to finding aggregation." For this article's theme (org-wide governance), we proceed with the Organizations method.

2.2 Migrating from the invitation method to the Organizations method

If you already operate with the invitation method and want to shift to the Organizations method, the idea is simple.

  1. Designate the GuardDuty delegated administrator in the management account (next section).
  2. Set auto_enable_organization_members = "ALL" in the delegated administrator.
  3. Members that were associated via the invitation method are integrated under the delegated administrator's management as members of the org. Note that the delegated administrator's 50,000 cap says "includes member accounts that are added through AWS Organizations or those who accepted the GuardDuty administrator account's invitation" — be aware that invitation-route members count in the same quota.

The iron rule during migration is "to not miss existing members, choose ALL, not NEW" (the reason is in the next section). Before going to production, always verify with a sample finding that "findings get aggregated to the delegated administrator" (see create-sample-findings in the pillar article).


3. Designating the delegated administrator: Terraform on the management-account side

Here's the code. First, just "designate" the delegated administrator in the management account. This itself configures nothing of GuardDuty's internals — it's only a declaration: "entrust GuardDuty management to this account."

# ──────────────────────────────────────────────────────────────
# 【管理(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 is not the management account's ID: what goes here is the delegation target's (the security account's) ID. Confuse it and put the management account's own ID, and you get exactly the non-recommended "management account as delegated administrator" config we wanted to avoid in Section 1.

When you apply this aws_guardduty_organization_admin_account, AWS behind the scenes prepares a service-linked role for GuardDuty in the delegated administrator account, putting the delegated administrator in a state where it can call the org APIs. The moment you designate it, GuardDuty in the delegated administrator account is automatically enabled in that Region (official: "GuardDuty gets enabled automatically only in the current AWS Region").


4. Auto-enabling all members: Terraform on the delegated-administrator side

Once the designation is done, now switch to the delegated administrator account's provider and put in the org setting. This is the heart of governance.

# ──────────────────────────────────────────────────────────────
# 【委任管理者(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"
}

The required arguments of aws_guardduty_organization_configuration are detector_id and auto_enable_organization_members (value is "ALL" / "NEW" / "NONE").

[Important] Don't use the old auto_enable (boolean): the former auto_enable = true/false and datasources { ... } block are deprecated, and per-protection-plan org settings were separated into the aws_guardduty_organization_configuration_feature described later. For new builds, write it with auto_enable_organization_members (a 3-value string) + the _feature resource. Copy-pasting code from old blog articles is a source of deprecation warnings and unintended behavior.

4.1 Why choose ALL — the silent hole of NEW

The choice among the three values directly decides "whether you create a hole in the security net."

ValueTargetsRisk
ALL (recommended)All members, existing + futureNone. Every account in the org at config time immediately becomes a target
NEWOnly members that join going forwardExisting accounts can be left out of scope forever (a silent hole)
NONENo auto-enablementManual management per member. Frequent missing accounts

The pitfall of NEW is serious. Choose NEW and accounts already in the org at "the very moment" you put in the setting do not become targets of auto-enablement. Because only new accounts become targets, existing production / staging accounts can be left without GuardDuty. Against the security goal of "detecting org-wide with no gaps," NEW is a structural hole.

Furthermore, the official docs raise the trap of NEW's order dependency in opt-in Regions. In NEW operation, unless you keep the order "① the member enables the opt-in Region → ② add that member to the org," it becomes "the member account is no longer new to the organization" and NEW doesn't take effect. With ALL, this order problem itself disappears ("the order of these steps is not relevant") — this too is a practical reason to push for ALL.

Only when there's an account you want to intentionally exclude from GuardDuty (e.g. a sandbox), it's safer to individually disable just that one account while keeping ALL, rather than loosening the whole with NEW/NONE.

4.2 What happens when a new account joins

Set up ALL (or NEW), and an account newly created in / invited to the org automatically comes under GuardDuty, without human hands. This is the greatest value of the Organizations method.

In operations like the payment platform, where you separate accounts by role and carve out an account on every service addition, this pays off — the accident of "I created a new account but forgot to add GuardDuty" stops happening structurally. You stop relying on operational carefulness and have the setting (ALL) take it over.


5. Auto-enabling protection plans org-wide too (per-feature)

Beyond foundational detection, protection plans like S3 Protection and Runtime Monitoring can also be "auto-enabled org-wide." What you use is aws_guardduty_organization_configuration_feature.

# 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"
  }
}

The required arguments of aws_guardduty_organization_configuration_feature are detector_id / name / auto_enable (auto_enable is ALL/NEW/NONE). Representative protection-plan features you can specify in name are as follows.

name (feature)What's monitoredOrg auto-enablement judgment
S3_DATA_EVENTSCloudTrail's S3 data eventsALL is the standard (cheap, big effect, spreads ETD correlation org-wide)
EKS_AUDIT_LOGSEKS audit logs (control plane)ALL if the org uses EKS, unneeded if not
RUNTIME_MONITORINGProcesses / syscalls inside containers / hostsThe most expensive, billed per vCPU. Judge whether org-wide ALL or limited to critical WLs
EBS_MALWARE_PROTECTIONAgentless scanning of EBS on EC2-originated findingsALL if EC2-centric
RDS_LOGIN_EVENTSLogin activity of Aurora / RDSEnable for orgs that have DBs
LAMBDA_NETWORK_LOGSLambda's network activity (VPC Flow Logs)Enable if serverless-centric

Articulating the trade-off (per-feature ALL is not uniform): foundational detection and S3 Protection win on cost-effectiveness with org-wide ALL. On the other hand, Runtime Monitoring is billed per vCPU, so "org-wide uniform ALL" is not necessarily optimal. The tug-of-war between the org's detection coverage and cost is covered in detail in the GuardDuty cost-optimization article — since the delegated administrator can see the projected usage per member account, the proper approach is to visualize first, then decide "which features to set ALL and which to limit."

RUNTIME_MONITORING and EKS_RUNTIME_MONITORING are mutually exclusive: on the Terraform Provider, "Only one of two features EKS_RUNTIME_MONITORING or RUNTIME_MONITORING can be added". The current way is to use the consolidated RUNTIME_MONITORING for new setups and control EKS/ECS/EC2 agent management individually with additional_configuration.


6. The all-Regions strategy: don't miss global events

This is the most misunderstood point in org governance. "Just enabling GuardDuty in the Tokyo Region is enough" is dangerous.

6.1 Why enable even unused Regions

GuardDuty is a per-Region service. And events of global services like IAM, STS, S3, CloudFront, and Route 53 receive special treatment. The official explanation is — GuardDuty "replicates those events and processes them in each Region where you have enabled GuardDuty" for these global service events (GSE). That is, global events are replicated and processed in all Regions where you have enabled GuardDuty.

What this means is — in Regions where you haven't enabled GuardDuty, some of these global events are not processed. Attackers come at that spot. The official docs also warn "Threat actors can potentially launch attacks through global services... They can attempt to create unauthorized resources to exploit Regions where you have limited presence" and conclude that you should "enable in all Regions" ("We recommend that you enable GuardDuty in all AWS Regions available in your AWS account"). Both default Regions and opt-in Regions are targets ("including both default and opt-in Regions").

A note on a finding's Region value: a finding originating from a global event may have a finding Region value that differs from the Region where it was actually detected. The official docs note "a finding might show us-east-1 as the Region even if GuardDuty creates the detection in a different Region". When you branch on the Region as a key in automated response (EventBridge), factor in that global events come in with an unexpected Region value.

6.2 Repeating "designation → org setting" per Region

You need to repeat in each Region you want to enable the sequence "designation (management account) → org setting / protection plans (delegated administrator)" from up through Section 5. Official: the delegated administrator "must be added through AWS Organizations in each desired Region", and you must use the same delegated administrator account in all Regions.

Configuring all Regions × each resource by hand is unrealistic. This is where Terraform's provider alias × for_each shows its true worth.

6.3 Notes on opt-in Regions

Opt-in Regions (some Asia-Pacific Regions and the like, which require explicit enablement) have their own notes. Officially, if the delegated administrator opts out of an opt-in Region, even with the NEW/ALL setting it may become unable to enable members where GuardDuty is currently disabled. Furthermore, the aforementioned NEW order-dependency problem is also specific to opt-in Regions. Adopting ALL avoids the order problem, so the ALL recommendation pays off here too.


7. Terraform: a multi-region implementation with provider alias × for_each

Let's build a structure where "the code doesn't bloat linearly as you add Regions." The keys are (1) having a provider alias per Region, and (2) separating state for the delegated-administrator registration and the org setting.

7.1 Design: split state and roles into two

StackExecution accountRoleResponsibility
org-admin-registrationManagement accountOrgGuardDutyAdminSetup (strong, low-frequency)Designating the delegated administrator (for all Regions)
guardduty-org-configDelegated administrator accountGuardDutyDelegatedAdmin (daily operations)detector, org setting, protection plans (for all Regions)

The reason to split into two is precisely Section 1's least privilege. You don't want to run daily operations (adjusting protection plans, etc.) with the management account's high-privilege role. Nor do you want the delegated administrator's operational role to hold the "account designation" permission. Split the state and the roles used for apply naturally split too. The thinking on state separation and drift detection is dug into in the Terraform module-design article.

7.2 Stack ①: designating the delegated administrator (management account, all Regions)

# 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
}

A practical Terraform constraint: the provider block itself cannot be dynamically generated with for_each (the number of providers must be settled before plan). So explicitly enumerate a provider alias per Region and write resources for each alias. If there are many Regions, modularize this enumeration part, or lean toward a structure that calls a "child module taking a Region as an argument" with for_each, as described below.

7.3 Stack ②: the org setting via a cross-region module (delegated administrator)

Since protection plans and org settings have many items, carve out "the setting for one Region" into a child module and call it per Region by passing a provider. With this, "adding a Region = adding one module block" is all it takes.

# 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"
}
# 呼び出し側(委任管理者アカウントの 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 }
}

Apply order (dependency): Stack ② (the org setting) fails unless Stack ① (designating the delegated administrator) is completed in that Region. This is because an undesignated account has no permission to call the org-setting API. Apply in the order ① → ② (since they're separate states, guaranteeing order via CI job dependencies is robust). Keyless apply from CI can ride on the configuration in the OIDC keyless CI/CD article (separating roles for plan and apply).

7.4 Per-member overrides

When you want to keep org-wide uniformity with ALL while changing the protection plan for only specific accounts (e.g. turn off Runtime Monitoring for just a sandbox), you individually override the member account's detector from the delegated administrator. In Terraform you apply aws_guardduty_detector_feature to the member's detector, or manage it individually with an operation equivalent to UpdateMemberDetectors. The principle is "the org-wide default is ALL, and exceptions are explicit, one account at a time" — structurally safer than loosening the whole with NEW/NONE and creating a hole.


8. Finding aggregation, publishing, and the landing zone

8.1 Findings are automatically aggregated to the delegated administrator

Set up the org, and findings from all members and all Regions are automatically aggregated to the delegated administrator account (official: the delegated administrator can "review all generated findings"). The delegated administrator can survey the org-wide security posture at a glance and check the findings and projected usage per member account. This is the practical benefit of the "consolidate detection into a dedicated security account" design.

8.2 Export to S3 and aggregate to Security Hub at the org level

Starting from the delegated administrator, export findings to S3 (long-term retention / analysis) and feed them into AWS Security Hub CSPM to prioritize across other detections (Macie, etc.). For deep-dive investigation, Amazon Detective. "Detect with GuardDuty → aggregate at the delegated administrator → cross-cut at Security Hub → dig deep with Detective" is the royal road of org operation.

The EventBridge → idempotent automated response that turns findings into action is beyond this article's scope, so I leave it to the automated-response / incident-response article. In an org configuration, the standard is to build EventBridge rules starting from findings aggregated in the delegated administrator account.

8.3 Relationship to the landing zone / Control Tower

If you're designing an org from scratch, it's natural to ride on the context of the AWS Control Tower / landing zone. Control Tower typically provisions an Audit account and a Log Archive account. The standard placement is to assign the GuardDuty delegated administrator to this Audit (or a dedicated Security) account — completely consistent with the "a dedicated security account, not the management account" I've said throughout this article.

Retrofitting onto an existing org: even if you don't use Control Tower, this article's configuration applies as-is. What matters is not the tool but the principle — place the delegated administrator in a dedicated account, and auto-enable all Regions with ALL. Control Tower just lays that down "as a convention."


9. Least-privilege boundaries between accounts (IAM design)

Finally, let me make explicit the boundary of the two roles we split in this article. This isn't decoration — it's the main body of the governance design.

RoleWhere it's placedMain allowed operationsDisallowed operations
OrgGuardDutyAdminSetupManagement accountguardduty:EnableOrganizationAdminAccount / Disable... / related organizations:* (minimal)Adjusting protection plans, finding operations, editing suppression rules
GuardDutyDelegatedAdminDelegated administrator accountguardduty:UpdateOrganizationConfiguration / Update*Detector* / CreateFilter (suppression) / referencing findingsAccount designation (registering the delegated administrator), adding/removing org accounts

Let me articulate the design principles.

  • Don't cross the designation permission and the operational permission. The management account's role goes only as far as "designate / un-designate." The delegated administrator's role goes only as far as "daily operations." Make it so neither role can step into the other's domain. This is the main body of separating the blast radius of a compromise.
  • Keep the management account's high-privilege role "low-frequency, approval-required." OrgGuardDutyAdminSetup is used only about when you change the delegated administrator. If touched from CI, limit it to an OIDC role with an environment approval gate (the environment approval in the OIDC article).
  • For APIs where you can narrow Resource, narrow it. Split finding-reference operations into a read-only role, and config-change operations into a role with a permissions boundary.
  • GuardDuty is not a replacement for IAM. A reminder. GuardDuty detects "the misuse of leaked credentials," but least-privilege IAM, keyless authentication, and encryption to avoid leaking are separately needed. GuardDuty plays the "layer that quickly signals indications across the org" within this defense-in-depth.

10. Summary: a GuardDuty org-governance cheat sheet

A quick-reference table for when you're unsure.

  • Method: for multi-account, AWS Organizations integration is the official recommendation. The invitation method is a limited use for bundling external accounts. During migration, ALL so you don't miss existing members.
  • Delegated administrator: don't operate from the management (payer) account (officially not recommended from the least-privilege standpoint). Make a dedicated Security/Audit account the delegated administrator. Designate in the management account (aws_guardduty_organization_admin_account), and configure the org setting in the delegated administrator account.
  • Auto-enablement: auto_enable_organization_members = "ALL" (existing + future) of aws_guardduty_organization_configuration. NEW is a hole where existing accounts silently fall out of scope. The old auto_enable (boolean) / datasources block is deprecated — don't use it.
  • Protection plans: org auto-enablement via aws_guardduty_organization_configuration_feature (name + auto_enable). ALL is standard for S3; Runtime Monitoring is billed per vCPU, so judge org-wide vs. limited. RUNTIME_MONITORING and EKS_RUNTIME_MONITORING are mutually exclusive.
  • Regions: GuardDuty is Regional. Repeat designation → org setting in each Region. The same delegated administrator account in all Regions is required. Global events (IAM/STS/S3/CloudFront/Route 53) are replicated and processed across all enabled Regions, so enable all Regions including unused and opt-in. A finding's Region value can differ from the detection Region.
  • Terraform: providers can't use for_eachenumerate an alias per Region, and modularize one Region's worth and pass the provider. Separate state and roles for ① designation (management account, high-privilege role) and ② org setting (delegated administrator, operational role). Apply in the order ① → ②.
  • New accounts: under ALL, an account that joins the org comes under GuardDuty automatically. Forgetting to add it disappears structurally.
  • Aggregation: findings are auto-aggregated to the delegated administrator. Cross-cut with S3 export, Security Hub, and Detective. Control Tower's Audit account is the standard placement for the delegated administrator.
  • IAM boundaries: don't cross the designation permission and the operational permission. GuardDuty is one layer of detection; it doesn't replace least-privilege IAM, keyless authentication, or encryption.

Org-level GuardDuty is not "the work of manually enabling it in all accounts," but a governance design: "consolidate to the delegated administrator, auto-enable with ALL, and roll out to all Regions with Terraform." The greatest leverage is in guaranteeing — with code, not operational vigilance — a structure where no hole opens in the monitoring net even as accounts grow and shrink.

On the multi-account serverless payment platform, I implemented IAM, observability, and DR across a platform handling actual money, carbon credits, and regional currencies, and supported the production / staging / audit account separation with the structure of code rather than "operational carefulness." I design GuardDuty org governance with the same philosophy — ① place the delegated administrator in a dedicated account to separate the blast radius, ② structurally eliminate missing accounts with ALL × all Regions, and ③ keep "adding a Region = adding one line" with a Terraform multi-region configuration.

"How should I roll out GuardDuty org-wide on my multi-account AWS, where should I place the delegated administrator, and which Regions / which protection plans should I set to ALL?" — from Organizations design through Terraform implementation, least-privilege boundaries between accounts, and finding aggregation, I can accompany you fast and safely, one person × generative AI (Claude Code). Whether retrofitting onto an existing org or starting from the requirements-organizing stage, feel free to consult me.


Reference (official documentation)

友田

友田 陽大

Developer of a METI Minister's Award–winning product. With TypeScript + Python + AWS, I deliver SaaS, industry DX, and production-grade generative AI (RAG) end to end — from requirements to infrastructure and operations — single-handedly.

I can take on the implementation from this article as an engagement

Build a GuardDuty threat-detection foundation and org-wide governance, from design to implementation

From enabling a single account to org-wide activation across all regions via AWS Organizations with a delegated administrator. A reproducible detection foundation in Terraform — least-privilege, idempotent, with zero gaps.

Available for both project-based (contract) and advisory engagements. Start with a free 30-minute consult.

Also worth reading