Multi-Region GuardDuty and Security Hub at Scale

When you’re running AWS at any meaningful scale — say, more than 50 accounts — the default per-region, per-account configuration of GuardDuty and Security Hub stops being workable. Findings end up scattered across consoles, nobody owns triage, and the operational cost of just knowing what your security posture looks like becomes prohibitive.

This post covers the pattern I’ve used to extend GuardDuty and Security Hub coverage across regions in a delegated administrator model, with notes on the gotchas that aren’t obvious from the AWS documentation alone.

The target architecture

The end state you’re aiming for:

  • A dedicated Security Tooling account as the delegated administrator for both GuardDuty and Security Hub, owned by the security function and tightly access-controlled
  • Regional aggregation for each service in your primary region, ingesting findings from all member accounts across all enabled regions
  • Auto-enable on account creation so that new accounts joining the organisation are protected by default, with no manual steps
  • Cross-region replication of findings into a single pane of glass — typically the primary region your security team operates from
  • Downstream integration into your SIEM, ticketing, or SOAR platform via EventBridge, with a clear ownership model for each finding type

The principle is straightforward: security findings should land in one place, normalised, deduplicated, and routable to the right team automatically. If a security analyst is logging into individual member accounts to view findings, the architecture has failed.

Delegation: the foundation

The first move is delegating GuardDuty and Security Hub administration from the management account to your dedicated Security Tooling account. This is non-negotiable — running security tooling out of the management account violates least privilege and creates a blast radius nobody wants.

# From the management account, delegate GuardDuty admin
aws organizations register-delegated-administrator \
  --account-id $SECURITY_TOOLING_ACCOUNT_ID \
  --service-principal guardduty.amazonaws.com

# And Security Hub
aws organizations register-delegated-administrator \
  --account-id $SECURITY_TOOLING_ACCOUNT_ID \
  --service-principal securityhub.amazonaws.comCode language: PHP (php)

In Terraform, the same delegation looks like this — and crucially, you’ll want this codified rather than click-opsed in the console:

resource "aws_organizations_delegated_administrator" "guardduty" {
  account_id        = var.security_tooling_account_id
  service_principal = "guardduty.amazonaws.com"
}

resource "aws_organizations_delegated_administrator" "securityhub" {
  account_id        = var.security_tooling_account_id
  service_principal = "securityhub.amazonaws.com"
}Code language: JavaScript (javascript)

Once delegated, all subsequent organisation-wide configuration for these services happens from the Security Tooling account, not the management account.

Auto-enable for the organisation

The pattern that saves significant operational pain is configuring auto-enable at the organisation level. New accounts joining the organisation should automatically have GuardDuty and Security Hub enabled, with the standards you’ve decided on already applied. Without this, every new account is a gap in coverage until somebody remembers to manually enrol it.

For Security Hub specifically, auto-enable handles the service itself, but you also need to consider which standards to enable by default. The reasonable baseline in 2026 is AWS Foundational Security Best Practices and CIS AWS Foundations Benchmark v3.0, with PCI-DSS or NIST 800-53 added for accounts in scope.

Regional strategy: the part that catches people out

Here’s where the architecture gets interesting. AWS regional services like GuardDuty and Security Hub are configured per-region, even when administered organisationally. This means you have two extension axes to manage: across accounts (handled by delegation) and across regions (which needs explicit configuration).

The pattern I use is:

  • Enable GuardDuty in every region you have workloads in, plus a couple you don’t. The “regions you don’t” point is deliberate — GuardDuty in unused regions catches activity in regions where you shouldn’t have any, which is often the first sign of credential compromise. The cost is trivial.
  • Enable Security Hub in the same regions, but designate a single primary region as your aggregation point.
  • Configure cross-region aggregation in Security Hub from the primary region, pulling findings from all linked regions into one view.

In Terraform, the cross-region aggregation looks like this:

resource "aws_securityhub_finding_aggregator" "primary" {
  provider     = aws.eu_west_2  # Your primary region
  linking_mode = "ALL_REGIONS"
}Code language: PHP (php)

The ALL_REGIONS linking mode is generally what you want — it pulls findings from every region where Security Hub is enabled into your primary region. Alternatives are SPECIFIED_REGIONS (explicit list) and ALL_REGIONS_EXCEPT_SPECIFIED (allowlist). For most organisations, ALL_REGIONS is operationally simpler.

A subtle but important point: Security Hub’s cross-region aggregation copies findings to the aggregation region, but the source region remains the system of record. When you take action on a finding in the aggregation view, it propagates back to the source region. This matters for automation — your remediation logic should be region-aware.

Extending coverage: a common scenario

A scenario that comes up often: an organisation has GuardDuty and Security Hub enabled in their primary region, but workloads have started spreading to a secondary region for resilience or latency reasons. The secondary region is now a coverage gap.

The extension pattern, assuming delegation is already in place:

  1. Enable GuardDuty in the new region for the delegated administrator account
  2. Use update_organization_configuration to enable auto-enable for the organisation in that region
  3. Repeat for Security Hub, including enabling the standards you want applied
  4. Add the new region to your finding aggregator’s source regions (or rely on ALL_REGIONS mode)
  5. Verify findings are flowing into the aggregation region within 24 hours

The Terraform module pattern that scales well is to take a list of regions as input and instantiate the per-region resources via for_each. This means adding a new region is a one-line change to your module input, not a new module instantiation.

DNS Firewall: the per-account complement

GuardDuty and Security Hub are organisational. DNS Firewall typically isn’t — it’s deployed locally per workload account and VPC, with rules tuned to the workloads in that account. The reason for the asymmetry is that DNS Firewall is an inline control, not a detection service: it needs to be close to the traffic, and its rule sets are workload-specific.

The pattern I’d recommend is a centrally managed Route 53 Resolver Firewall rule group, shared via Resource Access Manager to workload accounts, with each account opting-in their VPCs. This gives you central rule management with local enforcement.

Operational notes

A few things worth flagging from running this pattern in production:

  • Costs scale with findings volume, not just account count. A misconfigured workload generating thousands of similar findings per day will surprise you on the next bill. Set up CloudWatch alarms on Security Hub finding ingestion rates.
  • EventBridge is your friend for routing. Don’t try to build orchestration inside Security Hub itself. Route findings to EventBridge, then fan out to your SIEM, ticketing system, or SOAR. This keeps your integration logic outside the security tooling and easier to evolve.
  • Document what you suppress, and why. Suppressed findings are findings you’ve decided not to act on. That decision deserves to be auditable. Use Security Hub’s automation rules with clear naming and ownership, not console-level suppressions that nobody can later explain.

What good looks like

You’ll know this is working when your security team can answer “what’s our current GuardDuty finding distribution across the estate?” without logging into anything except the aggregation region. When new accounts and new regions inherit the right protection automatically. When the noisy findings have been tuned out and what’s left is genuinely worth a human looking at.

Getting there is mostly Terraform discipline and refusing to let exceptions accumulate. The services do the heavy lifting; the architecture work is making sure they’re configured consistently and the findings flow somewhere useful.