The aws:securityhub/insight:Insight resource, part of the Pulumi AWS provider, defines custom Security Hub insights that filter and group security findings based on specific criteria. This guide focuses on four filtering capabilities: account-based filtering, time-based filtering, network and confidence filtering, and tag-based segmentation.
Insights require Security Hub to be enabled and depend on findings generated by AWS services or third-party integrations. The examples are intentionally small. Combine them with your own filter combinations and grouping strategies.
Group findings by AWS account ID
Multi-account environments need to track which accounts generate the most security findings.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.securityhub.Account("example", {});
const exampleInsight = new aws.securityhub.Insight("example", {
filters: {
awsAccountIds: [
{
comparison: "EQUALS",
value: "1234567890",
},
{
comparison: "EQUALS",
value: "09876543210",
},
],
},
groupByAttribute: "AwsAccountId",
name: "example-insight",
}, {
dependsOn: [example],
});
import pulumi
import pulumi_aws as aws
example = aws.securityhub.Account("example")
example_insight = aws.securityhub.Insight("example",
filters={
"aws_account_ids": [
{
"comparison": "EQUALS",
"value": "1234567890",
},
{
"comparison": "EQUALS",
"value": "09876543210",
},
],
},
group_by_attribute="AwsAccountId",
name="example-insight",
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.NewInsight(ctx, "example", &securityhub.InsightArgs{
Filters: &securityhub.InsightFiltersArgs{
AwsAccountIds: securityhub.InsightFiltersAwsAccountIdArray{
&securityhub.InsightFiltersAwsAccountIdArgs{
Comparison: pulumi.String("EQUALS"),
Value: pulumi.String("1234567890"),
},
&securityhub.InsightFiltersAwsAccountIdArgs{
Comparison: pulumi.String("EQUALS"),
Value: pulumi.String("09876543210"),
},
},
},
GroupByAttribute: pulumi.String("AwsAccountId"),
Name: pulumi.String("example-insight"),
}, 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 exampleInsight = new Aws.SecurityHub.Insight("example", new()
{
Filters = new Aws.SecurityHub.Inputs.InsightFiltersArgs
{
AwsAccountIds = new[]
{
new Aws.SecurityHub.Inputs.InsightFiltersAwsAccountIdArgs
{
Comparison = "EQUALS",
Value = "1234567890",
},
new Aws.SecurityHub.Inputs.InsightFiltersAwsAccountIdArgs
{
Comparison = "EQUALS",
Value = "09876543210",
},
},
},
GroupByAttribute = "AwsAccountId",
Name = "example-insight",
}, 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.Insight;
import com.pulumi.aws.securityhub.InsightArgs;
import com.pulumi.aws.securityhub.inputs.InsightFiltersArgs;
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 exampleInsight = new Insight("exampleInsight", InsightArgs.builder()
.filters(InsightFiltersArgs.builder()
.awsAccountIds(
InsightFiltersAwsAccountIdArgs.builder()
.comparison("EQUALS")
.value("1234567890")
.build(),
InsightFiltersAwsAccountIdArgs.builder()
.comparison("EQUALS")
.value("09876543210")
.build())
.build())
.groupByAttribute("AwsAccountId")
.name("example-insight")
.build(), CustomResourceOptions.builder()
.dependsOn(example)
.build());
}
}
resources:
example:
type: aws:securityhub:Account
exampleInsight:
type: aws:securityhub:Insight
name: example
properties:
filters:
awsAccountIds:
- comparison: EQUALS
value: '1234567890'
- comparison: EQUALS
value: '09876543210'
groupByAttribute: AwsAccountId
name: example-insight
options:
dependsOn:
- ${example}
The filters property defines criteria for including findings in the insight. The awsAccountIds array accepts multiple account IDs, each with a comparison operator. The groupByAttribute property determines how results are organized; here, findings are grouped by account ID to create a ranked view of security posture across accounts.
Track recent findings with time-based filters
Security teams monitoring active threats focus on recent findings rather than historical data.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.securityhub.Account("example", {});
const exampleInsight = new aws.securityhub.Insight("example", {
filters: {
createdAts: [{
dateRange: {
unit: "DAYS",
value: 5,
},
}],
},
groupByAttribute: "CreatedAt",
name: "example-insight",
}, {
dependsOn: [example],
});
import pulumi
import pulumi_aws as aws
example = aws.securityhub.Account("example")
example_insight = aws.securityhub.Insight("example",
filters={
"created_ats": [{
"date_range": {
"unit": "DAYS",
"value": 5,
},
}],
},
group_by_attribute="CreatedAt",
name="example-insight",
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.NewInsight(ctx, "example", &securityhub.InsightArgs{
Filters: &securityhub.InsightFiltersArgs{
CreatedAts: securityhub.InsightFiltersCreatedAtArray{
&securityhub.InsightFiltersCreatedAtArgs{
DateRange: &securityhub.InsightFiltersCreatedAtDateRangeArgs{
Unit: pulumi.String("DAYS"),
Value: pulumi.Int(5),
},
},
},
},
GroupByAttribute: pulumi.String("CreatedAt"),
Name: pulumi.String("example-insight"),
}, 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 exampleInsight = new Aws.SecurityHub.Insight("example", new()
{
Filters = new Aws.SecurityHub.Inputs.InsightFiltersArgs
{
CreatedAts = new[]
{
new Aws.SecurityHub.Inputs.InsightFiltersCreatedAtArgs
{
DateRange = new Aws.SecurityHub.Inputs.InsightFiltersCreatedAtDateRangeArgs
{
Unit = "DAYS",
Value = 5,
},
},
},
},
GroupByAttribute = "CreatedAt",
Name = "example-insight",
}, 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.Insight;
import com.pulumi.aws.securityhub.InsightArgs;
import com.pulumi.aws.securityhub.inputs.InsightFiltersArgs;
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 exampleInsight = new Insight("exampleInsight", InsightArgs.builder()
.filters(InsightFiltersArgs.builder()
.createdAts(InsightFiltersCreatedAtArgs.builder()
.dateRange(InsightFiltersCreatedAtDateRangeArgs.builder()
.unit("DAYS")
.value(5)
.build())
.build())
.build())
.groupByAttribute("CreatedAt")
.name("example-insight")
.build(), CustomResourceOptions.builder()
.dependsOn(example)
.build());
}
}
resources:
example:
type: aws:securityhub:Account
exampleInsight:
type: aws:securityhub:Insight
name: example
properties:
filters:
createdAts:
- dateRange:
unit: DAYS
value: 5
groupByAttribute: CreatedAt
name: example-insight
options:
dependsOn:
- ${example}
The createdAts filter limits insights to findings created within a specified time window. The dateRange property uses unit and value to define the lookback period; this example shows findings from the last 5 days. Grouping by CreatedAt organizes results chronologically.
Monitor network traffic to specific IP ranges
Network security monitoring often focuses on traffic patterns to sensitive infrastructure.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.securityhub.Account("example", {});
const exampleInsight = new aws.securityhub.Insight("example", {
filters: {
networkDestinationIpv4s: [{
cidr: "10.0.0.0/16",
}],
},
groupByAttribute: "NetworkDestinationIpV4",
name: "example-insight",
}, {
dependsOn: [example],
});
import pulumi
import pulumi_aws as aws
example = aws.securityhub.Account("example")
example_insight = aws.securityhub.Insight("example",
filters={
"network_destination_ipv4s": [{
"cidr": "10.0.0.0/16",
}],
},
group_by_attribute="NetworkDestinationIpV4",
name="example-insight",
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.NewInsight(ctx, "example", &securityhub.InsightArgs{
Filters: &securityhub.InsightFiltersArgs{
NetworkDestinationIpv4s: securityhub.InsightFiltersNetworkDestinationIpv4Array{
&securityhub.InsightFiltersNetworkDestinationIpv4Args{
Cidr: pulumi.String("10.0.0.0/16"),
},
},
},
GroupByAttribute: pulumi.String("NetworkDestinationIpV4"),
Name: pulumi.String("example-insight"),
}, 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 exampleInsight = new Aws.SecurityHub.Insight("example", new()
{
Filters = new Aws.SecurityHub.Inputs.InsightFiltersArgs
{
NetworkDestinationIpv4s = new[]
{
new Aws.SecurityHub.Inputs.InsightFiltersNetworkDestinationIpv4Args
{
Cidr = "10.0.0.0/16",
},
},
},
GroupByAttribute = "NetworkDestinationIpV4",
Name = "example-insight",
}, 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.Insight;
import com.pulumi.aws.securityhub.InsightArgs;
import com.pulumi.aws.securityhub.inputs.InsightFiltersArgs;
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 exampleInsight = new Insight("exampleInsight", InsightArgs.builder()
.filters(InsightFiltersArgs.builder()
.networkDestinationIpv4s(InsightFiltersNetworkDestinationIpv4Args.builder()
.cidr("10.0.0.0/16")
.build())
.build())
.groupByAttribute("NetworkDestinationIpV4")
.name("example-insight")
.build(), CustomResourceOptions.builder()
.dependsOn(example)
.build());
}
}
resources:
example:
type: aws:securityhub:Account
exampleInsight:
type: aws:securityhub:Insight
name: example
properties:
filters:
networkDestinationIpv4s:
- cidr: 10.0.0.0/16
groupByAttribute: NetworkDestinationIpV4
name: example-insight
options:
dependsOn:
- ${example}
The networkDestinationIpv4s filter matches findings where network traffic targets specific IP ranges. The cidr property accepts CIDR notation to define the address space. This reveals findings related to specific network segments or external endpoints.
Prioritize high-confidence security findings
Security findings include confidence scores that indicate detection certainty.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.securityhub.Account("example", {});
const exampleInsight = new aws.securityhub.Insight("example", {
filters: {
confidences: [{
gte: "80",
}],
},
groupByAttribute: "Confidence",
name: "example-insight",
}, {
dependsOn: [example],
});
import pulumi
import pulumi_aws as aws
example = aws.securityhub.Account("example")
example_insight = aws.securityhub.Insight("example",
filters={
"confidences": [{
"gte": "80",
}],
},
group_by_attribute="Confidence",
name="example-insight",
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.NewInsight(ctx, "example", &securityhub.InsightArgs{
Filters: &securityhub.InsightFiltersArgs{
Confidences: securityhub.InsightFiltersConfidenceArray{
&securityhub.InsightFiltersConfidenceArgs{
Gte: pulumi.String("80"),
},
},
},
GroupByAttribute: pulumi.String("Confidence"),
Name: pulumi.String("example-insight"),
}, 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 exampleInsight = new Aws.SecurityHub.Insight("example", new()
{
Filters = new Aws.SecurityHub.Inputs.InsightFiltersArgs
{
Confidences = new[]
{
new Aws.SecurityHub.Inputs.InsightFiltersConfidenceArgs
{
Gte = "80",
},
},
},
GroupByAttribute = "Confidence",
Name = "example-insight",
}, 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.Insight;
import com.pulumi.aws.securityhub.InsightArgs;
import com.pulumi.aws.securityhub.inputs.InsightFiltersArgs;
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 exampleInsight = new Insight("exampleInsight", InsightArgs.builder()
.filters(InsightFiltersArgs.builder()
.confidences(InsightFiltersConfidenceArgs.builder()
.gte("80")
.build())
.build())
.groupByAttribute("Confidence")
.name("example-insight")
.build(), CustomResourceOptions.builder()
.dependsOn(example)
.build());
}
}
resources:
example:
type: aws:securityhub:Account
exampleInsight:
type: aws:securityhub:Insight
name: example
properties:
filters:
confidences:
- gte: '80'
groupByAttribute: Confidence
name: example-insight
options:
dependsOn:
- ${example}
The confidences filter uses comparison operators like gte (greater than or equal) to set a threshold. This example includes only findings with 80% or higher confidence, helping teams focus on findings most likely to represent real threats.
Segment findings by environment or workload
Organizations using tags to classify resources can filter findings by those same tags.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.securityhub.Account("example", {});
const exampleInsight = new aws.securityhub.Insight("example", {
filters: {
resourceTags: [{
comparison: "EQUALS",
key: "Environment",
value: "Production",
}],
},
groupByAttribute: "ResourceTags",
name: "example-insight",
}, {
dependsOn: [example],
});
import pulumi
import pulumi_aws as aws
example = aws.securityhub.Account("example")
example_insight = aws.securityhub.Insight("example",
filters={
"resource_tags": [{
"comparison": "EQUALS",
"key": "Environment",
"value": "Production",
}],
},
group_by_attribute="ResourceTags",
name="example-insight",
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.NewInsight(ctx, "example", &securityhub.InsightArgs{
Filters: &securityhub.InsightFiltersArgs{
ResourceTags: securityhub.InsightFiltersResourceTagArray{
&securityhub.InsightFiltersResourceTagArgs{
Comparison: pulumi.String("EQUALS"),
Key: pulumi.String("Environment"),
Value: pulumi.String("Production"),
},
},
},
GroupByAttribute: pulumi.String("ResourceTags"),
Name: pulumi.String("example-insight"),
}, 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 exampleInsight = new Aws.SecurityHub.Insight("example", new()
{
Filters = new Aws.SecurityHub.Inputs.InsightFiltersArgs
{
ResourceTags = new[]
{
new Aws.SecurityHub.Inputs.InsightFiltersResourceTagArgs
{
Comparison = "EQUALS",
Key = "Environment",
Value = "Production",
},
},
},
GroupByAttribute = "ResourceTags",
Name = "example-insight",
}, 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.Insight;
import com.pulumi.aws.securityhub.InsightArgs;
import com.pulumi.aws.securityhub.inputs.InsightFiltersArgs;
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 exampleInsight = new Insight("exampleInsight", InsightArgs.builder()
.filters(InsightFiltersArgs.builder()
.resourceTags(InsightFiltersResourceTagArgs.builder()
.comparison("EQUALS")
.key("Environment")
.value("Production")
.build())
.build())
.groupByAttribute("ResourceTags")
.name("example-insight")
.build(), CustomResourceOptions.builder()
.dependsOn(example)
.build());
}
}
resources:
example:
type: aws:securityhub:Account
exampleInsight:
type: aws:securityhub:Insight
name: example
properties:
filters:
resourceTags:
- comparison: EQUALS
key: Environment
value: Production
groupByAttribute: ResourceTags
name: example-insight
options:
dependsOn:
- ${example}
The resourceTags filter matches findings on resources with specific tag key-value pairs. The comparison operator determines the match type; EQUALS requires exact matches. This creates insights scoped to specific environments, teams, or applications.
Beyond these examples
These snippets focus on specific insight filter types: account and time-based filtering, network and confidence-based filtering, and tag-based segmentation. They’re intentionally minimal rather than full security monitoring solutions.
The examples assume pre-existing infrastructure such as Security Hub enabled in the AWS account, and security findings from AWS services or third-party integrations. They focus on configuring the insight rather than provisioning Security Hub itself.
To keep things focused, common insight patterns are omitted, including:
- Multiple filter combinations (up to 10 distinct attributes)
- Other filter types (severity, compliance status, resource type)
- Custom grouping attributes beyond the examples shown
- Integration with Security Hub actions or automation
These omissions are intentional: the goal is to illustrate how each filter type is wired, not provide drop-in security monitoring modules. See the Security Hub Insight resource reference for all available configuration options.
Let's create AWS Security Hub Custom Insights
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Setup & Dependencies
dependsOn ensures the Account resource is created first.Filtering & Grouping
You can filter by:
- Account IDs -
awsAccountIdswith EQUALS comparison - Date ranges -
createdAtswith unit (DAYS) and value - IP addresses -
networkDestinationIpv4swith CIDR notation - Confidence scores -
confidenceswith gte/lte operators - Resource tags -
resourceTagswith key, value, and comparison
ResourceId produces a list of resource identifiers, while grouping by AwsAccountId organizes findings by account.region property. If not specified, it defaults to the region configured in your provider.