The aws:networkfirewall/ruleGroup:RuleGroup resource, part of the Pulumi AWS provider, defines Network Firewall rule groups that inspect and filter network traffic based on stateful or stateless rules. This guide focuses on three capabilities: domain blocking and IP-based filtering, Suricata rule import from files and S3, and stateless inspection with custom actions.
Rule groups are standalone resources that define inspection logic. They’re attached to firewall policies separately, which then associate with Network Firewall instances. The examples are intentionally small. Combine them with your own firewall policies and network configuration.
Block access to specific domains
Network security teams often need to prevent traffic to known malicious or restricted domains by evaluating HTTP Host headers.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.networkfirewall.RuleGroup("example", {
capacity: 100,
name: "example",
type: "STATEFUL",
ruleGroup: {
rulesSource: {
rulesSourceList: {
generatedRulesType: "DENYLIST",
targetTypes: ["HTTP_HOST"],
targets: ["test.example.com"],
},
},
},
tags: {
Tag1: "Value1",
Tag2: "Value2",
},
});
import pulumi
import pulumi_aws as aws
example = aws.networkfirewall.RuleGroup("example",
capacity=100,
name="example",
type="STATEFUL",
rule_group={
"rules_source": {
"rules_source_list": {
"generated_rules_type": "DENYLIST",
"target_types": ["HTTP_HOST"],
"targets": ["test.example.com"],
},
},
},
tags={
"Tag1": "Value1",
"Tag2": "Value2",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkfirewall"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := networkfirewall.NewRuleGroup(ctx, "example", &networkfirewall.RuleGroupArgs{
Capacity: pulumi.Int(100),
Name: pulumi.String("example"),
Type: pulumi.String("STATEFUL"),
RuleGroup: &networkfirewall.RuleGroupRuleGroupArgs{
RulesSource: &networkfirewall.RuleGroupRuleGroupRulesSourceArgs{
RulesSourceList: &networkfirewall.RuleGroupRuleGroupRulesSourceRulesSourceListArgs{
GeneratedRulesType: pulumi.String("DENYLIST"),
TargetTypes: pulumi.StringArray{
pulumi.String("HTTP_HOST"),
},
Targets: pulumi.StringArray{
pulumi.String("test.example.com"),
},
},
},
},
Tags: pulumi.StringMap{
"Tag1": pulumi.String("Value1"),
"Tag2": pulumi.String("Value2"),
},
})
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.NetworkFirewall.RuleGroup("example", new()
{
Capacity = 100,
Name = "example",
Type = "STATEFUL",
RuleGroupConfiguration = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupArgs
{
RulesSource = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceArgs
{
RulesSourceList = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceRulesSourceListArgs
{
GeneratedRulesType = "DENYLIST",
TargetTypes = new[]
{
"HTTP_HOST",
},
Targets = new[]
{
"test.example.com",
},
},
},
},
Tags =
{
{ "Tag1", "Value1" },
{ "Tag2", "Value2" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkfirewall.RuleGroup;
import com.pulumi.aws.networkfirewall.RuleGroupArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupRulesSourceArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupRulesSourceRulesSourceListArgs;
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 RuleGroup("example", RuleGroupArgs.builder()
.capacity(100)
.name("example")
.type("STATEFUL")
.ruleGroup(RuleGroupRuleGroupArgs.builder()
.rulesSource(RuleGroupRuleGroupRulesSourceArgs.builder()
.rulesSourceList(RuleGroupRuleGroupRulesSourceRulesSourceListArgs.builder()
.generatedRulesType("DENYLIST")
.targetTypes("HTTP_HOST")
.targets("test.example.com")
.build())
.build())
.build())
.tags(Map.ofEntries(
Map.entry("Tag1", "Value1"),
Map.entry("Tag2", "Value2")
))
.build());
}
}
resources:
example:
type: aws:networkfirewall:RuleGroup
properties:
capacity: 100
name: example
type: STATEFUL
ruleGroup:
rulesSource:
rulesSourceList:
generatedRulesType: DENYLIST
targetTypes:
- HTTP_HOST
targets:
- test.example.com
tags:
Tag1: Value1
Tag2: Value2
When traffic matches a domain in the targets list, Network Firewall blocks the connection. The generatedRulesType property controls whether this is a DENYLIST or ALLOWLIST. The targetTypes property specifies what to inspect (HTTP_HOST, TLS_SNI, or both). The capacity property sets the maximum operating resources; for stateful rules, this must be at least the number of rules.
Allow HTTP traffic from specific source IPs
Applications receiving traffic from known partners need to permit connections from specific source addresses.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const ips = [
"1.1.1.1/32",
"1.0.0.1/32",
];
const example = new aws.networkfirewall.RuleGroup("example", {
capacity: 50,
description: "Permits http traffic from source",
name: "example",
type: "STATEFUL",
ruleGroup: {
rulesSource: {
statefulRules: ips.map((v, k) => ({key: k, value: v})).map(entry => ({
action: "PASS",
header: {
destination: "ANY",
destinationPort: "ANY",
protocol: "HTTP",
direction: "ANY",
sourcePort: "ANY",
source: entry.value,
},
ruleOptions: [{
keyword: "sid",
settings: ["1"],
}],
})),
},
},
tags: {
Name: "permit HTTP from source",
},
});
import pulumi
import pulumi_aws as aws
ips = [
"1.1.1.1/32",
"1.0.0.1/32",
]
example = aws.networkfirewall.RuleGroup("example",
capacity=50,
description="Permits http traffic from source",
name="example",
type="STATEFUL",
rule_group={
"rules_source": {
"stateful_rules": [{
"action": "PASS",
"header": {
"destination": "ANY",
"destination_port": "ANY",
"protocol": "HTTP",
"direction": "ANY",
"source_port": "ANY",
"source": entry["value"],
},
"rule_options": [{
"keyword": "sid",
"settings": ["1"],
}],
} for entry in [{"key": k, "value": v} for k, v in ips.items()]],
},
},
tags={
"Name": "permit HTTP from source",
})
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var ips = new[]
{
"1.1.1.1/32",
"1.0.0.1/32",
};
var example = new Aws.NetworkFirewall.RuleGroup("example", new()
{
Capacity = 50,
Description = "Permits http traffic from source",
Name = "example",
Type = "STATEFUL",
RuleGroupConfiguration = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupArgs
{
RulesSource = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceArgs
{
StatefulRules = ips.Select((v, k) => new { Key = k, Value = v }).Select(entry =>
{
return new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatefulRuleArgs
{
Action = "PASS",
Header = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatefulRuleHeaderArgs
{
Destination = "ANY",
DestinationPort = "ANY",
Protocol = "HTTP",
Direction = "ANY",
SourcePort = "ANY",
Source = entry.Value,
},
RuleOptions = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatefulRuleRuleOptionArgs
{
Keyword = "sid",
Settings = new[]
{
"1",
},
},
},
};
}).ToList(),
},
},
Tags =
{
{ "Name", "permit HTTP from source" },
},
});
});
Each statefulRule defines a 5-tuple match (source, destination, ports, protocol, direction) and an action (PASS, DROP, or ALERT). The header block specifies what traffic to match. The ruleOptions array includes a sid (signature ID) that uniquely identifies each rule. Here, the code iterates over an IP list to create one rule per source address.
Import existing Suricata rules from a file
Teams migrating from other network security tools can preserve their existing Suricata-format rules.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";
const example = new aws.networkfirewall.RuleGroup("example", {
capacity: 100,
name: "example",
type: "STATEFUL",
rules: std.file({
input: "example.rules",
}).then(invoke => invoke.result),
tags: {
Tag1: "Value1",
Tag2: "Value2",
},
});
import pulumi
import pulumi_aws as aws
import pulumi_std as std
example = aws.networkfirewall.RuleGroup("example",
capacity=100,
name="example",
type="STATEFUL",
rules=std.file(input="example.rules").result,
tags={
"Tag1": "Value1",
"Tag2": "Value2",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkfirewall"
"github.com/pulumi/pulumi-std/sdk/go/std"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
invokeFile, err := std.File(ctx, &std.FileArgs{
Input: "example.rules",
}, nil)
if err != nil {
return err
}
_, err = networkfirewall.NewRuleGroup(ctx, "example", &networkfirewall.RuleGroupArgs{
Capacity: pulumi.Int(100),
Name: pulumi.String("example"),
Type: pulumi.String("STATEFUL"),
Rules: pulumi.String(invokeFile.Result),
Tags: pulumi.StringMap{
"Tag1": pulumi.String("Value1"),
"Tag2": pulumi.String("Value2"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var example = new Aws.NetworkFirewall.RuleGroup("example", new()
{
Capacity = 100,
Name = "example",
Type = "STATEFUL",
Rules = Std.File.Invoke(new()
{
Input = "example.rules",
}).Apply(invoke => invoke.Result),
Tags =
{
{ "Tag1", "Value1" },
{ "Tag2", "Value2" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkfirewall.RuleGroup;
import com.pulumi.aws.networkfirewall.RuleGroupArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.FileArgs;
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 RuleGroup("example", RuleGroupArgs.builder()
.capacity(100)
.name("example")
.type("STATEFUL")
.rules(StdFunctions.file(FileArgs.builder()
.input("example.rules")
.build()).result())
.tags(Map.ofEntries(
Map.entry("Tag1", "Value1"),
Map.entry("Tag2", "Value2")
))
.build());
}
}
resources:
example:
type: aws:networkfirewall:RuleGroup
properties:
capacity: 100
name: example
type: STATEFUL
rules:
fn::invoke:
function: std:file
arguments:
input: example.rules
return: result
tags:
Tag1: Value1
Tag2: Value2
The rules property accepts Suricata rule strings directly, with one rule per line. This is an alternative to defining rules inline via ruleGroup. Use this when you have existing Suricata rules you want to import without rewriting them into the structured format.
Define reusable variables for Suricata rules
Complex rule sets benefit from variables that define IP ranges and port sets once, then reference them throughout the rules.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";
const example = new aws.networkfirewall.RuleGroup("example", {
capacity: 100,
name: "example",
type: "STATEFUL",
ruleGroup: {
ruleVariables: {
ipSets: [
{
key: "WEBSERVERS_HOSTS",
ipSet: {
definitions: [
"10.0.0.0/16",
"10.0.1.0/24",
"192.168.0.0/16",
],
},
},
{
key: "EXTERNAL_HOST",
ipSet: {
definitions: ["1.2.3.4/32"],
},
},
],
portSets: [{
key: "HTTP_PORTS",
portSet: {
definitions: [
"443",
"80",
],
},
}],
},
rulesSource: {
rulesString: std.file({
input: "suricata_rules_file",
}).then(invoke => invoke.result),
},
},
tags: {
Tag1: "Value1",
Tag2: "Value2",
},
});
import pulumi
import pulumi_aws as aws
import pulumi_std as std
example = aws.networkfirewall.RuleGroup("example",
capacity=100,
name="example",
type="STATEFUL",
rule_group={
"rule_variables": {
"ip_sets": [
{
"key": "WEBSERVERS_HOSTS",
"ip_set": {
"definitions": [
"10.0.0.0/16",
"10.0.1.0/24",
"192.168.0.0/16",
],
},
},
{
"key": "EXTERNAL_HOST",
"ip_set": {
"definitions": ["1.2.3.4/32"],
},
},
],
"port_sets": [{
"key": "HTTP_PORTS",
"port_set": {
"definitions": [
"443",
"80",
],
},
}],
},
"rules_source": {
"rules_string": std.file(input="suricata_rules_file").result,
},
},
tags={
"Tag1": "Value1",
"Tag2": "Value2",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkfirewall"
"github.com/pulumi/pulumi-std/sdk/go/std"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
invokeFile, err := std.File(ctx, &std.FileArgs{
Input: "suricata_rules_file",
}, nil)
if err != nil {
return err
}
_, err = networkfirewall.NewRuleGroup(ctx, "example", &networkfirewall.RuleGroupArgs{
Capacity: pulumi.Int(100),
Name: pulumi.String("example"),
Type: pulumi.String("STATEFUL"),
RuleGroup: &networkfirewall.RuleGroupRuleGroupArgs{
RuleVariables: &networkfirewall.RuleGroupRuleGroupRuleVariablesArgs{
IpSets: networkfirewall.RuleGroupRuleGroupRuleVariablesIpSetArray{
&networkfirewall.RuleGroupRuleGroupRuleVariablesIpSetArgs{
Key: pulumi.String("WEBSERVERS_HOSTS"),
IpSet: &networkfirewall.RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs{
Definitions: pulumi.StringArray{
pulumi.String("10.0.0.0/16"),
pulumi.String("10.0.1.0/24"),
pulumi.String("192.168.0.0/16"),
},
},
},
&networkfirewall.RuleGroupRuleGroupRuleVariablesIpSetArgs{
Key: pulumi.String("EXTERNAL_HOST"),
IpSet: &networkfirewall.RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs{
Definitions: pulumi.StringArray{
pulumi.String("1.2.3.4/32"),
},
},
},
},
PortSets: networkfirewall.RuleGroupRuleGroupRuleVariablesPortSetArray{
&networkfirewall.RuleGroupRuleGroupRuleVariablesPortSetArgs{
Key: pulumi.String("HTTP_PORTS"),
PortSet: &networkfirewall.RuleGroupRuleGroupRuleVariablesPortSetPortSetArgs{
Definitions: pulumi.StringArray{
pulumi.String("443"),
pulumi.String("80"),
},
},
},
},
},
RulesSource: &networkfirewall.RuleGroupRuleGroupRulesSourceArgs{
RulesString: pulumi.String(invokeFile.Result),
},
},
Tags: pulumi.StringMap{
"Tag1": pulumi.String("Value1"),
"Tag2": pulumi.String("Value2"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var example = new Aws.NetworkFirewall.RuleGroup("example", new()
{
Capacity = 100,
Name = "example",
Type = "STATEFUL",
RuleGroupConfiguration = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupArgs
{
RuleVariables = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesArgs
{
IpSets = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesIpSetArgs
{
Key = "WEBSERVERS_HOSTS",
IpSet = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs
{
Definitions = new[]
{
"10.0.0.0/16",
"10.0.1.0/24",
"192.168.0.0/16",
},
},
},
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesIpSetArgs
{
Key = "EXTERNAL_HOST",
IpSet = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs
{
Definitions = new[]
{
"1.2.3.4/32",
},
},
},
},
PortSets = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesPortSetArgs
{
Key = "HTTP_PORTS",
PortSet = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesPortSetPortSetArgs
{
Definitions = new[]
{
"443",
"80",
},
},
},
},
},
RulesSource = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceArgs
{
RulesString = Std.File.Invoke(new()
{
Input = "suricata_rules_file",
}).Apply(invoke => invoke.Result),
},
},
Tags =
{
{ "Tag1", "Value1" },
{ "Tag2", "Value2" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkfirewall.RuleGroup;
import com.pulumi.aws.networkfirewall.RuleGroupArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupRuleVariablesArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupRulesSourceArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.FileArgs;
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 RuleGroup("example", RuleGroupArgs.builder()
.capacity(100)
.name("example")
.type("STATEFUL")
.ruleGroup(RuleGroupRuleGroupArgs.builder()
.ruleVariables(RuleGroupRuleGroupRuleVariablesArgs.builder()
.ipSets(
RuleGroupRuleGroupRuleVariablesIpSetArgs.builder()
.key("WEBSERVERS_HOSTS")
.ipSet(RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs.builder()
.definitions(
"10.0.0.0/16",
"10.0.1.0/24",
"192.168.0.0/16")
.build())
.build(),
RuleGroupRuleGroupRuleVariablesIpSetArgs.builder()
.key("EXTERNAL_HOST")
.ipSet(RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs.builder()
.definitions("1.2.3.4/32")
.build())
.build())
.portSets(RuleGroupRuleGroupRuleVariablesPortSetArgs.builder()
.key("HTTP_PORTS")
.portSet(RuleGroupRuleGroupRuleVariablesPortSetPortSetArgs.builder()
.definitions(
"443",
"80")
.build())
.build())
.build())
.rulesSource(RuleGroupRuleGroupRulesSourceArgs.builder()
.rulesString(StdFunctions.file(FileArgs.builder()
.input("suricata_rules_file")
.build()).result())
.build())
.build())
.tags(Map.ofEntries(
Map.entry("Tag1", "Value1"),
Map.entry("Tag2", "Value2")
))
.build());
}
}
resources:
example:
type: aws:networkfirewall:RuleGroup
properties:
capacity: 100
name: example
type: STATEFUL
ruleGroup:
ruleVariables:
ipSets:
- key: WEBSERVERS_HOSTS
ipSet:
definitions:
- 10.0.0.0/16
- 10.0.1.0/24
- 192.168.0.0/16
- key: EXTERNAL_HOST
ipSet:
definitions:
- 1.2.3.4/32
portSets:
- key: HTTP_PORTS
portSet:
definitions:
- '443'
- '80'
rulesSource:
rulesString:
fn::invoke:
function: std:file
arguments:
input: suricata_rules_file
return: result
tags:
Tag1: Value1
Tag2: Value2
The ruleVariables block defines ipSets and portSets that your Suricata rules can reference by key (e.g., $HOME_NET, $HTTP_PORTS). The rulesString property contains the actual Suricata rules that use these variables. This extends the file-based approach by adding variable definitions, reducing duplication when the same IPs or ports appear in multiple rules.
Publish metrics from stateless rules
Stateless inspection evaluates packets individually without tracking connection state, enabling fast filtering and custom metric publishing.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.networkfirewall.RuleGroup("example", {
description: "Stateless Rate Limiting Rule",
capacity: 100,
name: "example",
type: "STATELESS",
ruleGroup: {
rulesSource: {
statelessRulesAndCustomActions: {
customActions: [{
actionDefinition: {
publishMetricAction: {
dimensions: [{
value: "2",
}],
},
},
actionName: "ExampleMetricsAction",
}],
statelessRules: [{
priority: 1,
ruleDefinition: {
actions: [
"aws:pass",
"ExampleMetricsAction",
],
matchAttributes: {
sources: [{
addressDefinition: "1.2.3.4/32",
}],
sourcePorts: [{
fromPort: 443,
toPort: 443,
}],
destinations: [{
addressDefinition: "124.1.1.5/32",
}],
destinationPorts: [{
fromPort: 443,
toPort: 443,
}],
protocols: [6],
tcpFlags: [{
flags: ["SYN"],
masks: [
"SYN",
"ACK",
],
}],
},
},
}],
},
},
},
tags: {
Tag1: "Value1",
Tag2: "Value2",
},
});
import pulumi
import pulumi_aws as aws
example = aws.networkfirewall.RuleGroup("example",
description="Stateless Rate Limiting Rule",
capacity=100,
name="example",
type="STATELESS",
rule_group={
"rules_source": {
"stateless_rules_and_custom_actions": {
"custom_actions": [{
"action_definition": {
"publish_metric_action": {
"dimensions": [{
"value": "2",
}],
},
},
"action_name": "ExampleMetricsAction",
}],
"stateless_rules": [{
"priority": 1,
"rule_definition": {
"actions": [
"aws:pass",
"ExampleMetricsAction",
],
"match_attributes": {
"sources": [{
"address_definition": "1.2.3.4/32",
}],
"source_ports": [{
"from_port": 443,
"to_port": 443,
}],
"destinations": [{
"address_definition": "124.1.1.5/32",
}],
"destination_ports": [{
"from_port": 443,
"to_port": 443,
}],
"protocols": [6],
"tcp_flags": [{
"flags": ["SYN"],
"masks": [
"SYN",
"ACK",
],
}],
},
},
}],
},
},
},
tags={
"Tag1": "Value1",
"Tag2": "Value2",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkfirewall"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := networkfirewall.NewRuleGroup(ctx, "example", &networkfirewall.RuleGroupArgs{
Description: pulumi.String("Stateless Rate Limiting Rule"),
Capacity: pulumi.Int(100),
Name: pulumi.String("example"),
Type: pulumi.String("STATELESS"),
RuleGroup: &networkfirewall.RuleGroupRuleGroupArgs{
RulesSource: &networkfirewall.RuleGroupRuleGroupRulesSourceArgs{
StatelessRulesAndCustomActions: &networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsArgs{
CustomActions: networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionArray{
&networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionArgs{
ActionDefinition: &networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionArgs{
PublishMetricAction: &networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionPublishMetricActionArgs{
Dimensions: networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionPublishMetricActionDimensionArray{
&networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionPublishMetricActionDimensionArgs{
Value: pulumi.String("2"),
},
},
},
},
ActionName: pulumi.String("ExampleMetricsAction"),
},
},
StatelessRules: networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleArray{
&networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleArgs{
Priority: pulumi.Int(1),
RuleDefinition: &networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionArgs{
Actions: pulumi.StringArray{
pulumi.String("aws:pass"),
pulumi.String("ExampleMetricsAction"),
},
MatchAttributes: &networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesArgs{
Sources: networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesSourceArray{
&networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesSourceArgs{
AddressDefinition: pulumi.String("1.2.3.4/32"),
},
},
SourcePorts: networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesSourcePortArray{
&networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesSourcePortArgs{
FromPort: pulumi.Int(443),
ToPort: pulumi.Int(443),
},
},
Destinations: networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesDestinationArray{
&networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesDestinationArgs{
AddressDefinition: pulumi.String("124.1.1.5/32"),
},
},
DestinationPorts: networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesDestinationPortArray{
&networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesDestinationPortArgs{
FromPort: pulumi.Int(443),
ToPort: pulumi.Int(443),
},
},
Protocols: pulumi.IntArray{
pulumi.Int(6),
},
TcpFlags: networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesTcpFlagArray{
&networkfirewall.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesTcpFlagArgs{
Flags: pulumi.StringArray{
pulumi.String("SYN"),
},
Masks: pulumi.StringArray{
pulumi.String("SYN"),
pulumi.String("ACK"),
},
},
},
},
},
},
},
},
},
},
Tags: pulumi.StringMap{
"Tag1": pulumi.String("Value1"),
"Tag2": pulumi.String("Value2"),
},
})
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.NetworkFirewall.RuleGroup("example", new()
{
Description = "Stateless Rate Limiting Rule",
Capacity = 100,
Name = "example",
Type = "STATELESS",
RuleGroupConfiguration = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupArgs
{
RulesSource = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceArgs
{
StatelessRulesAndCustomActions = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsArgs
{
CustomActions = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionArgs
{
ActionDefinition = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionArgs
{
PublishMetricAction = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionPublishMetricActionArgs
{
Dimensions = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionPublishMetricActionDimensionArgs
{
Value = "2",
},
},
},
},
ActionName = "ExampleMetricsAction",
},
},
StatelessRules = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleArgs
{
Priority = 1,
RuleDefinition = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionArgs
{
Actions = new[]
{
"aws:pass",
"ExampleMetricsAction",
},
MatchAttributes = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesArgs
{
Sources = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesSourceArgs
{
AddressDefinition = "1.2.3.4/32",
},
},
SourcePorts = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesSourcePortArgs
{
FromPort = 443,
ToPort = 443,
},
},
Destinations = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesDestinationArgs
{
AddressDefinition = "124.1.1.5/32",
},
},
DestinationPorts = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesDestinationPortArgs
{
FromPort = 443,
ToPort = 443,
},
},
Protocols = new[]
{
6,
},
TcpFlags = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesTcpFlagArgs
{
Flags = new[]
{
"SYN",
},
Masks = new[]
{
"SYN",
"ACK",
},
},
},
},
},
},
},
},
},
},
Tags =
{
{ "Tag1", "Value1" },
{ "Tag2", "Value2" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkfirewall.RuleGroup;
import com.pulumi.aws.networkfirewall.RuleGroupArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupRulesSourceArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsArgs;
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 RuleGroup("example", RuleGroupArgs.builder()
.description("Stateless Rate Limiting Rule")
.capacity(100)
.name("example")
.type("STATELESS")
.ruleGroup(RuleGroupRuleGroupArgs.builder()
.rulesSource(RuleGroupRuleGroupRulesSourceArgs.builder()
.statelessRulesAndCustomActions(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsArgs.builder()
.customActions(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionArgs.builder()
.actionDefinition(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionArgs.builder()
.publishMetricAction(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionPublishMetricActionArgs.builder()
.dimensions(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsCustomActionActionDefinitionPublishMetricActionDimensionArgs.builder()
.value("2")
.build())
.build())
.build())
.actionName("ExampleMetricsAction")
.build())
.statelessRules(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleArgs.builder()
.priority(1)
.ruleDefinition(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionArgs.builder()
.actions(
"aws:pass",
"ExampleMetricsAction")
.matchAttributes(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesArgs.builder()
.sources(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesSourceArgs.builder()
.addressDefinition("1.2.3.4/32")
.build())
.sourcePorts(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesSourcePortArgs.builder()
.fromPort(443)
.toPort(443)
.build())
.destinations(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesDestinationArgs.builder()
.addressDefinition("124.1.1.5/32")
.build())
.destinationPorts(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesDestinationPortArgs.builder()
.fromPort(443)
.toPort(443)
.build())
.protocols(6)
.tcpFlags(RuleGroupRuleGroupRulesSourceStatelessRulesAndCustomActionsStatelessRuleRuleDefinitionMatchAttributesTcpFlagArgs.builder()
.flags("SYN")
.masks(
"SYN",
"ACK")
.build())
.build())
.build())
.build())
.build())
.build())
.build())
.tags(Map.ofEntries(
Map.entry("Tag1", "Value1"),
Map.entry("Tag2", "Value2")
))
.build());
}
}
resources:
example:
type: aws:networkfirewall:RuleGroup
properties:
description: Stateless Rate Limiting Rule
capacity: 100
name: example
type: STATELESS
ruleGroup:
rulesSource:
statelessRulesAndCustomActions:
customActions:
- actionDefinition:
publishMetricAction:
dimensions:
- value: '2'
actionName: ExampleMetricsAction
statelessRules:
- priority: 1
ruleDefinition:
actions:
- aws:pass
- ExampleMetricsAction
matchAttributes:
sources:
- addressDefinition: 1.2.3.4/32
sourcePorts:
- fromPort: 443
toPort: 443
destinations:
- addressDefinition: 124.1.1.5/32
destinationPorts:
- fromPort: 443
toPort: 443
protocols:
- 6
tcpFlags:
- flags:
- SYN
masks:
- SYN
- ACK
tags:
Tag1: Value1
Tag2: Value2
Stateless rules match on packet attributes (source/destination IPs, ports, protocols, TCP flags) and execute actions immediately. The customActions block defines a publishMetricAction that sends dimensions to CloudWatch when the rule matches. The statelessRules array assigns priorities (lower numbers evaluated first) and combines standard actions (aws:pass, aws:drop, aws:forward_to_sfe) with custom actions. The matchAttributes block specifies the 5-tuple and TCP flags to inspect.
Load Suricata rules from S3
Centralized rule management often stores Suricata rules in S3, allowing multiple rule groups to reference the same source.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const suricataRules = aws.s3.getObject({
bucket: suricataRulesAwsS3Bucket.id,
key: "rules/custom.rules",
});
const s3RulesExample = new aws.networkfirewall.RuleGroup("s3_rules_example", {
capacity: 1000,
name: "my-terraform-s3-rules",
type: "STATEFUL",
ruleGroup: {
ruleVariables: {
ipSets: [{
key: "HOME_NET",
ipSet: {
definitions: [
"10.0.0.0/16",
"192.168.0.0/16",
"172.16.0.0/12",
],
},
}],
portSets: [{
key: "HTTP_PORTS",
portSet: {
definitions: [
"443",
"80",
],
},
}],
},
rulesSource: {
rulesString: suricataRules.then(suricataRules => suricataRules.body),
},
},
tags: {
ManagedBy: "terraform",
},
});
import pulumi
import pulumi_aws as aws
suricata_rules = aws.s3.get_object(bucket=suricata_rules_aws_s3_bucket["id"],
key="rules/custom.rules")
s3_rules_example = aws.networkfirewall.RuleGroup("s3_rules_example",
capacity=1000,
name="my-terraform-s3-rules",
type="STATEFUL",
rule_group={
"rule_variables": {
"ip_sets": [{
"key": "HOME_NET",
"ip_set": {
"definitions": [
"10.0.0.0/16",
"192.168.0.0/16",
"172.16.0.0/12",
],
},
}],
"port_sets": [{
"key": "HTTP_PORTS",
"port_set": {
"definitions": [
"443",
"80",
],
},
}],
},
"rules_source": {
"rules_string": suricata_rules.body,
},
},
tags={
"ManagedBy": "terraform",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkfirewall"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
suricataRules, err := s3.GetObject(ctx, &s3.GetObjectArgs{
Bucket: suricataRulesAwsS3Bucket.Id,
Key: "rules/custom.rules",
}, nil)
if err != nil {
return err
}
_, err = networkfirewall.NewRuleGroup(ctx, "s3_rules_example", &networkfirewall.RuleGroupArgs{
Capacity: pulumi.Int(1000),
Name: pulumi.String("my-terraform-s3-rules"),
Type: pulumi.String("STATEFUL"),
RuleGroup: &networkfirewall.RuleGroupRuleGroupArgs{
RuleVariables: &networkfirewall.RuleGroupRuleGroupRuleVariablesArgs{
IpSets: networkfirewall.RuleGroupRuleGroupRuleVariablesIpSetArray{
&networkfirewall.RuleGroupRuleGroupRuleVariablesIpSetArgs{
Key: pulumi.String("HOME_NET"),
IpSet: &networkfirewall.RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs{
Definitions: pulumi.StringArray{
pulumi.String("10.0.0.0/16"),
pulumi.String("192.168.0.0/16"),
pulumi.String("172.16.0.0/12"),
},
},
},
},
PortSets: networkfirewall.RuleGroupRuleGroupRuleVariablesPortSetArray{
&networkfirewall.RuleGroupRuleGroupRuleVariablesPortSetArgs{
Key: pulumi.String("HTTP_PORTS"),
PortSet: &networkfirewall.RuleGroupRuleGroupRuleVariablesPortSetPortSetArgs{
Definitions: pulumi.StringArray{
pulumi.String("443"),
pulumi.String("80"),
},
},
},
},
},
RulesSource: &networkfirewall.RuleGroupRuleGroupRulesSourceArgs{
RulesString: pulumi.String(suricataRules.Body),
},
},
Tags: pulumi.StringMap{
"ManagedBy": pulumi.String("terraform"),
},
})
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 suricataRules = Aws.S3.GetObject.Invoke(new()
{
Bucket = suricataRulesAwsS3Bucket.Id,
Key = "rules/custom.rules",
});
var s3RulesExample = new Aws.NetworkFirewall.RuleGroup("s3_rules_example", new()
{
Capacity = 1000,
Name = "my-terraform-s3-rules",
Type = "STATEFUL",
RuleGroupConfiguration = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupArgs
{
RuleVariables = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesArgs
{
IpSets = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesIpSetArgs
{
Key = "HOME_NET",
IpSet = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs
{
Definitions = new[]
{
"10.0.0.0/16",
"192.168.0.0/16",
"172.16.0.0/12",
},
},
},
},
PortSets = new[]
{
new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesPortSetArgs
{
Key = "HTTP_PORTS",
PortSet = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRuleVariablesPortSetPortSetArgs
{
Definitions = new[]
{
"443",
"80",
},
},
},
},
},
RulesSource = new Aws.NetworkFirewall.Inputs.RuleGroupRuleGroupRulesSourceArgs
{
RulesString = suricataRules.Apply(getObjectResult => getObjectResult.Body),
},
},
Tags =
{
{ "ManagedBy", "terraform" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.s3.S3Functions;
import com.pulumi.aws.s3.inputs.GetObjectArgs;
import com.pulumi.aws.networkfirewall.RuleGroup;
import com.pulumi.aws.networkfirewall.RuleGroupArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupRuleVariablesArgs;
import com.pulumi.aws.networkfirewall.inputs.RuleGroupRuleGroupRulesSourceArgs;
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) {
final var suricataRules = S3Functions.getObject(GetObjectArgs.builder()
.bucket(suricataRulesAwsS3Bucket.id())
.key("rules/custom.rules")
.build());
var s3RulesExample = new RuleGroup("s3RulesExample", RuleGroupArgs.builder()
.capacity(1000)
.name("my-terraform-s3-rules")
.type("STATEFUL")
.ruleGroup(RuleGroupRuleGroupArgs.builder()
.ruleVariables(RuleGroupRuleGroupRuleVariablesArgs.builder()
.ipSets(RuleGroupRuleGroupRuleVariablesIpSetArgs.builder()
.key("HOME_NET")
.ipSet(RuleGroupRuleGroupRuleVariablesIpSetIpSetArgs.builder()
.definitions(
"10.0.0.0/16",
"192.168.0.0/16",
"172.16.0.0/12")
.build())
.build())
.portSets(RuleGroupRuleGroupRuleVariablesPortSetArgs.builder()
.key("HTTP_PORTS")
.portSet(RuleGroupRuleGroupRuleVariablesPortSetPortSetArgs.builder()
.definitions(
"443",
"80")
.build())
.build())
.build())
.rulesSource(RuleGroupRuleGroupRulesSourceArgs.builder()
.rulesString(suricataRules.body())
.build())
.build())
.tags(Map.of("ManagedBy", "terraform"))
.build());
}
}
resources:
s3RulesExample:
type: aws:networkfirewall:RuleGroup
name: s3_rules_example
properties:
capacity: 1000
name: my-terraform-s3-rules
type: STATEFUL
ruleGroup:
ruleVariables:
ipSets:
- key: HOME_NET
ipSet:
definitions:
- 10.0.0.0/16
- 192.168.0.0/16
- 172.16.0.0/12
portSets:
- key: HTTP_PORTS
portSet:
definitions:
- '443'
- '80'
rulesSource:
rulesString: ${suricataRules.body}
tags:
ManagedBy: terraform
variables:
suricataRules:
fn::invoke:
function: aws:s3:getObject
arguments:
bucket: ${suricataRulesAwsS3Bucket.id}
key: rules/custom.rules
The getObject function retrieves the rule file from S3, and the body property provides the content as a string. This is an alternative to the file-based approach, useful when rules are managed centrally or updated frequently. The ruleVariables block works the same way as in the file-based example, defining reusable IP and port sets.
Beyond these examples
These snippets focus on specific rule group features: stateful domain blocking and IP-based filtering, Suricata rule import (file and S3), and stateless inspection with custom metrics. They’re intentionally minimal rather than full network security policies.
The examples may reference pre-existing infrastructure such as S3 buckets for centralized rule storage and IAM permissions for S3 access. They focus on defining rule groups rather than provisioning the surrounding firewall infrastructure.
To keep things focused, common rule group patterns are omitted, including:
- Encryption configuration (encryptionConfiguration)
- IP set references for dynamic IP lists (referenceSets)
- Stateful rule options (flow control, protocol detection)
- TCP flag matching and protocol-specific inspection
These omissions are intentional: the goal is to illustrate how each rule group feature is wired, not provide drop-in security policies. See the Network Firewall RuleGroup resource reference for all available configuration options.
Let's configure AWS Network Firewall Rule Groups
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Rule Group Basics
type property with values STATEFUL or STATELESS.capacity and name are immutable. Changing either property after creation will force replacement of the entire rule group.Rule Definition Methods
ruleGroup for structured rule definitions, or rules for Suricata flat format (one rule per line). You must specify one, but not both.You have two options:
- Simple format - Use the
rulesproperty with a file reference - With variables - Use
ruleGroup.rulesSource.rulesStringwith file content, allowing you to defineruleVariables
aws.s3.getObject to fetch the rules file from S3, then pass the body to ruleGroup.rulesSource.rulesString.ipSets and portSets) define reusable IP addresses and ports that can be referenced in Suricata rules. Use them when you have common IP ranges or ports referenced across multiple rules.Common Use Cases
rulesSource.rulesSourceList, setting generatedRulesType to DENYLIST, targetTypes to ["HTTP_HOST"], and targets to your domain list.rulesSource.statefulRules with action set to PASS, specifying the source IPs in the header.source field. Set other header fields like destination, protocol, and ports as needed.rulesSource.statefulRules with action set to DROP, specifying the destination IP in header.destination and other matching criteria like ports and protocol.customActions in statelessRulesAndCustomActions with an actionDefinition (such as publishMetricAction), then reference the actionName in your rule’s actions array alongside standard actions like aws:pass.ruleGroup.referenceSets.ipSetReferences to reference IP sets by their ARN, allowing you to share IP set definitions across rule groups.