The aws:securityhub/findingAggregator:FindingAggregator resource, part of the Pulumi AWS provider, configures Security Hub finding aggregation: which regions send findings to a central home region. This guide focuses on three capabilities: all-regions aggregation, explicit region selection, and region exclusion patterns.
The aggregator requires Security Hub to be enabled in each region before it can pull findings. The examples are intentionally small. Combine them with your own Security Hub Account configuration and regional enablement strategy.
Aggregate findings from all available regions
Organizations with multi-region deployments often need a single view of security findings across their entire AWS footprint.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.securityhub.Account("example", {});
const exampleFindingAggregator = new aws.securityhub.FindingAggregator("example", {linkingMode: "ALL_REGIONS"}, {
dependsOn: [example],
});
import pulumi
import pulumi_aws as aws
example = aws.securityhub.Account("example")
example_finding_aggregator = aws.securityhub.FindingAggregator("example", linking_mode="ALL_REGIONS",
opts = pulumi.ResourceOptions(depends_on=[example]))
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/securityhub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := securityhub.NewAccount(ctx, "example", nil)
if err != nil {
return err
}
_, err = securityhub.NewFindingAggregator(ctx, "example", &securityhub.FindingAggregatorArgs{
LinkingMode: pulumi.String("ALL_REGIONS"),
}, pulumi.DependsOn([]pulumi.Resource{
example,
}))
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.SecurityHub.Account("example");
var exampleFindingAggregator = new Aws.SecurityHub.FindingAggregator("example", new()
{
LinkingMode = "ALL_REGIONS",
}, new CustomResourceOptions
{
DependsOn =
{
example,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.securityhub.Account;
import com.pulumi.aws.securityhub.FindingAggregator;
import com.pulumi.aws.securityhub.FindingAggregatorArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Account("example");
var exampleFindingAggregator = new FindingAggregator("exampleFindingAggregator", FindingAggregatorArgs.builder()
.linkingMode("ALL_REGIONS")
.build(), CustomResourceOptions.builder()
.dependsOn(example)
.build());
}
}
resources:
example:
type: aws:securityhub:Account
exampleFindingAggregator:
type: aws:securityhub:FindingAggregator
name: example
properties:
linkingMode: ALL_REGIONS
options:
dependsOn:
- ${example}
When linkingMode is set to ALL_REGIONS, Security Hub automatically aggregates findings from every region where it’s enabled. The dependsOn relationship ensures the Security Hub Account resource exists before creating the aggregator. Security Hub will automatically include new regions as they become available and you opt into them.
Aggregate findings from specific regions only
Some organizations operate in a subset of AWS regions due to compliance requirements or operational boundaries.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.securityhub.Account("example", {});
const exampleFindingAggregator = new aws.securityhub.FindingAggregator("example", {
linkingMode: "SPECIFIED_REGIONS",
specifiedRegions: [
"eu-west-1",
"eu-west-2",
],
}, {
dependsOn: [example],
});
import pulumi
import pulumi_aws as aws
example = aws.securityhub.Account("example")
example_finding_aggregator = aws.securityhub.FindingAggregator("example",
linking_mode="SPECIFIED_REGIONS",
specified_regions=[
"eu-west-1",
"eu-west-2",
],
opts = pulumi.ResourceOptions(depends_on=[example]))
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/securityhub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := securityhub.NewAccount(ctx, "example", nil)
if err != nil {
return err
}
_, err = securityhub.NewFindingAggregator(ctx, "example", &securityhub.FindingAggregatorArgs{
LinkingMode: pulumi.String("SPECIFIED_REGIONS"),
SpecifiedRegions: pulumi.StringArray{
pulumi.String("eu-west-1"),
pulumi.String("eu-west-2"),
},
}, pulumi.DependsOn([]pulumi.Resource{
example,
}))
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.SecurityHub.Account("example");
var exampleFindingAggregator = new Aws.SecurityHub.FindingAggregator("example", new()
{
LinkingMode = "SPECIFIED_REGIONS",
SpecifiedRegions = new[]
{
"eu-west-1",
"eu-west-2",
},
}, new CustomResourceOptions
{
DependsOn =
{
example,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.securityhub.Account;
import com.pulumi.aws.securityhub.FindingAggregator;
import com.pulumi.aws.securityhub.FindingAggregatorArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Account("example");
var exampleFindingAggregator = new FindingAggregator("exampleFindingAggregator", FindingAggregatorArgs.builder()
.linkingMode("SPECIFIED_REGIONS")
.specifiedRegions(
"eu-west-1",
"eu-west-2")
.build(), CustomResourceOptions.builder()
.dependsOn(example)
.build());
}
}
resources:
example:
type: aws:securityhub:Account
exampleFindingAggregator:
type: aws:securityhub:FindingAggregator
name: example
properties:
linkingMode: SPECIFIED_REGIONS
specifiedRegions:
- eu-west-1
- eu-west-2
options:
dependsOn:
- ${example}
The SPECIFIED_REGIONS linking mode requires the specifiedRegions property, which lists exactly which regions to aggregate from. This gives you explicit control over the aggregation scope, useful when you have data residency requirements or separate security boundaries.
Exclude specific regions from aggregation
Teams that want broad coverage but need to exclude certain regions can aggregate from all regions except those explicitly listed.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.securityhub.Account("example", {});
const exampleFindingAggregator = new aws.securityhub.FindingAggregator("example", {
linkingMode: "ALL_REGIONS_EXCEPT_SPECIFIED",
specifiedRegions: [
"eu-west-1",
"eu-west-2",
],
}, {
dependsOn: [example],
});
import pulumi
import pulumi_aws as aws
example = aws.securityhub.Account("example")
example_finding_aggregator = aws.securityhub.FindingAggregator("example",
linking_mode="ALL_REGIONS_EXCEPT_SPECIFIED",
specified_regions=[
"eu-west-1",
"eu-west-2",
],
opts = pulumi.ResourceOptions(depends_on=[example]))
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/securityhub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := securityhub.NewAccount(ctx, "example", nil)
if err != nil {
return err
}
_, err = securityhub.NewFindingAggregator(ctx, "example", &securityhub.FindingAggregatorArgs{
LinkingMode: pulumi.String("ALL_REGIONS_EXCEPT_SPECIFIED"),
SpecifiedRegions: pulumi.StringArray{
pulumi.String("eu-west-1"),
pulumi.String("eu-west-2"),
},
}, pulumi.DependsOn([]pulumi.Resource{
example,
}))
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.SecurityHub.Account("example");
var exampleFindingAggregator = new Aws.SecurityHub.FindingAggregator("example", new()
{
LinkingMode = "ALL_REGIONS_EXCEPT_SPECIFIED",
SpecifiedRegions = new[]
{
"eu-west-1",
"eu-west-2",
},
}, new CustomResourceOptions
{
DependsOn =
{
example,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.securityhub.Account;
import com.pulumi.aws.securityhub.FindingAggregator;
import com.pulumi.aws.securityhub.FindingAggregatorArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Account("example");
var exampleFindingAggregator = new FindingAggregator("exampleFindingAggregator", FindingAggregatorArgs.builder()
.linkingMode("ALL_REGIONS_EXCEPT_SPECIFIED")
.specifiedRegions(
"eu-west-1",
"eu-west-2")
.build(), CustomResourceOptions.builder()
.dependsOn(example)
.build());
}
}
resources:
example:
type: aws:securityhub:Account
exampleFindingAggregator:
type: aws:securityhub:FindingAggregator
name: example
properties:
linkingMode: ALL_REGIONS_EXCEPT_SPECIFIED
specifiedRegions:
- eu-west-1
- eu-west-2
options:
dependsOn:
- ${example}
The ALL_REGIONS_EXCEPT_SPECIFIED mode inverts the selection logic: it aggregates from all regions except those in specifiedRegions. This is useful when you have a few regions with special requirements (like separate compliance boundaries) but want findings from everywhere else.
Beyond these examples
These snippets focus on specific finding aggregator features: region linking modes and explicit region inclusion and exclusion. They’re intentionally minimal rather than full Security Hub deployments.
The examples assume pre-existing infrastructure such as Security Hub enabled in each region to be aggregated. They focus on configuring the aggregator rather than provisioning Security Hub itself.
To keep things focused, common aggregator patterns are omitted, including:
- Cross-account aggregation (requires Organization configuration)
- Finding filters and suppression rules
- Integration with other AWS services (EventBridge, SNS)
- NO_REGIONS mode (creates aggregator without linking regions)
These omissions are intentional: the goal is to illustrate how each aggregation mode is wired, not provide drop-in security modules. See the Security Hub FindingAggregator resource reference for all available configuration options.
Let's configure AWS Security Hub Finding Aggregators
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Prerequisites & Setup
aws.securityhub.Account resource first and use dependsOn to ensure proper ordering.Linking Modes & Region Selection
There are four linking modes:
- ALL_REGIONS - Aggregates findings from all available regions
- ALL_REGIONS_EXCEPT_SPECIFIED - Aggregates from all regions except those in
specifiedRegions - SPECIFIED_REGIONS - Aggregates only from regions listed in
specifiedRegions - NO_REGIONS - Enables the aggregator but doesn’t link any regions to the home region
specifiedRegions when linkingMode is set to ALL_REGIONS_EXCEPT_SPECIFIED or SPECIFIED_REGIONS. It’s not needed for ALL_REGIONS or NO_REGIONS modes.Automatic Aggregation
ALL_REGIONS or ALL_REGIONS_EXCEPT_SPECIFIED linking modes. Security Hub automatically aggregates findings from new regions as they become available and you opt into them.