Configure AWS Network Firewall Policies

The aws:networkfirewall/firewallPolicy:FirewallPolicy resource, part of the Pulumi AWS provider, defines a Network Firewall policy that specifies default traffic actions, attaches rule groups, and configures inspection behavior. This guide focuses on four capabilities: default action configuration, rule group attachment and ordering, variable overrides and custom actions, and threat detection modes.

Firewall policies reference existing Network Firewall rule groups and may reference TLS inspection configurations. The examples are intentionally small. Combine them with your own rule groups and network topology.

Define default actions and attach rule groups

Most policies start by defining how to handle traffic that doesn’t match any rules, then attach rule groups for inspection.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const current = aws.getRegion({});
const currentGetPartition = aws.getPartition({});
const currentGetCallerIdentity = aws.getCallerIdentity({});
const example = new aws.networkfirewall.FirewallPolicy("example", {
    name: "example",
    firewallPolicy: {
        statelessDefaultActions: ["aws:pass"],
        statelessFragmentDefaultActions: ["aws:drop"],
        statelessRuleGroupReferences: [{
            priority: 1,
            resourceArn: exampleAwsNetworkfirewallRuleGroup.arn,
        }],
        tlsInspectionConfigurationArn: Promise.all([currentGetPartition, current, currentGetCallerIdentity]).then(([currentGetPartition, current, currentGetCallerIdentity]) => `arn:${currentGetPartition.partition}:network-firewall:${current.region}:${currentGetCallerIdentity.accountId}:tls-configuration/example`),
    },
    tags: {
        Tag1: "Value1",
        Tag2: "Value2",
    },
});
import pulumi
import pulumi_aws as aws

current = aws.get_region()
current_get_partition = aws.get_partition()
current_get_caller_identity = aws.get_caller_identity()
example = aws.networkfirewall.FirewallPolicy("example",
    name="example",
    firewall_policy={
        "stateless_default_actions": ["aws:pass"],
        "stateless_fragment_default_actions": ["aws:drop"],
        "stateless_rule_group_references": [{
            "priority": 1,
            "resource_arn": example_aws_networkfirewall_rule_group["arn"],
        }],
        "tls_inspection_configuration_arn": f"arn:{current_get_partition.partition}:network-firewall:{current.region}:{current_get_caller_identity.account_id}:tls-configuration/example",
    },
    tags={
        "Tag1": "Value1",
        "Tag2": "Value2",
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"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 {
		current, err := aws.GetRegion(ctx, &aws.GetRegionArgs{}, nil)
		if err != nil {
			return err
		}
		currentGetPartition, err := aws.GetPartition(ctx, &aws.GetPartitionArgs{}, nil)
		if err != nil {
			return err
		}
		currentGetCallerIdentity, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		_, err = networkfirewall.NewFirewallPolicy(ctx, "example", &networkfirewall.FirewallPolicyArgs{
			Name: pulumi.String("example"),
			FirewallPolicy: &networkfirewall.FirewallPolicyFirewallPolicyArgs{
				StatelessDefaultActions: pulumi.StringArray{
					pulumi.String("aws:pass"),
				},
				StatelessFragmentDefaultActions: pulumi.StringArray{
					pulumi.String("aws:drop"),
				},
				StatelessRuleGroupReferences: networkfirewall.FirewallPolicyFirewallPolicyStatelessRuleGroupReferenceArray{
					&networkfirewall.FirewallPolicyFirewallPolicyStatelessRuleGroupReferenceArgs{
						Priority:    pulumi.Int(1),
						ResourceArn: pulumi.Any(exampleAwsNetworkfirewallRuleGroup.Arn),
					},
				},
				TlsInspectionConfigurationArn: pulumi.Sprintf("arn:%v:network-firewall:%v:%v:tls-configuration/example", currentGetPartition.Partition, current.Region, currentGetCallerIdentity.AccountId),
			},
			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 current = Aws.GetRegion.Invoke();

    var currentGetPartition = Aws.GetPartition.Invoke();

    var currentGetCallerIdentity = Aws.GetCallerIdentity.Invoke();

    var example = new Aws.NetworkFirewall.FirewallPolicy("example", new()
    {
        Name = "example",
        FirewallPolicyConfiguration = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyArgs
        {
            StatelessDefaultActions = new[]
            {
                "aws:pass",
            },
            StatelessFragmentDefaultActions = new[]
            {
                "aws:drop",
            },
            StatelessRuleGroupReferences = new[]
            {
                new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatelessRuleGroupReferenceArgs
                {
                    Priority = 1,
                    ResourceArn = exampleAwsNetworkfirewallRuleGroup.Arn,
                },
            },
            TlsInspectionConfigurationArn = Output.Tuple(currentGetPartition, current, currentGetCallerIdentity).Apply(values =>
            {
                var currentGetPartition = values.Item1;
                var current = values.Item2;
                var currentGetCallerIdentity = values.Item3;
                return $"arn:{currentGetPartition.Apply(getPartitionResult => getPartitionResult.Partition)}:network-firewall:{current.Apply(getRegionResult => getRegionResult.Region)}:{currentGetCallerIdentity.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:tls-configuration/example";
            }),
        },
        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.AwsFunctions;
import com.pulumi.aws.inputs.GetRegionArgs;
import com.pulumi.aws.inputs.GetPartitionArgs;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.networkfirewall.FirewallPolicy;
import com.pulumi.aws.networkfirewall.FirewallPolicyArgs;
import com.pulumi.aws.networkfirewall.inputs.FirewallPolicyFirewallPolicyArgs;
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 current = AwsFunctions.getRegion(GetRegionArgs.builder()
            .build());

        final var currentGetPartition = AwsFunctions.getPartition(GetPartitionArgs.builder()
            .build());

        final var currentGetCallerIdentity = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        var example = new FirewallPolicy("example", FirewallPolicyArgs.builder()
            .name("example")
            .firewallPolicy(FirewallPolicyFirewallPolicyArgs.builder()
                .statelessDefaultActions("aws:pass")
                .statelessFragmentDefaultActions("aws:drop")
                .statelessRuleGroupReferences(FirewallPolicyFirewallPolicyStatelessRuleGroupReferenceArgs.builder()
                    .priority(1)
                    .resourceArn(exampleAwsNetworkfirewallRuleGroup.arn())
                    .build())
                .tlsInspectionConfigurationArn(String.format("arn:%s:network-firewall:%s:%s:tls-configuration/example", currentGetPartition.partition(),current.region(),currentGetCallerIdentity.accountId()))
                .build())
            .tags(Map.ofEntries(
                Map.entry("Tag1", "Value1"),
                Map.entry("Tag2", "Value2")
            ))
            .build());

    }
}
resources:
  example:
    type: aws:networkfirewall:FirewallPolicy
    properties:
      name: example
      firewallPolicy:
        statelessDefaultActions:
          - aws:pass
        statelessFragmentDefaultActions:
          - aws:drop
        statelessRuleGroupReferences:
          - priority: 1
            resourceArn: ${exampleAwsNetworkfirewallRuleGroup.arn}
        tlsInspectionConfigurationArn: arn:${currentGetPartition.partition}:network-firewall:${current.region}:${currentGetCallerIdentity.accountId}:tls-configuration/example
      tags:
        Tag1: Value1
        Tag2: Value2
variables:
  current:
    fn::invoke:
      function: aws:getRegion
      arguments: {}
  currentGetPartition:
    fn::invoke:
      function: aws:getPartition
      arguments: {}
  currentGetCallerIdentity:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}

The statelessDefaultActions property sets what happens to packets that don’t match stateless rules (here, “aws:pass” allows them through). The statelessFragmentDefaultActions property handles fragmented packets separately. The statelessRuleGroupReferences array attaches rule groups with priority values that control evaluation order.

Override HOME_NET variable for custom networks

Rule groups often reference the HOME_NET variable to identify internal networks. Policies can override this to match your topology.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.networkfirewall.FirewallPolicy("example", {
    name: "example",
    firewallPolicy: {
        policyVariables: {
            ruleVariables: [{
                key: "HOME_NET",
                ipSet: {
                    definitions: [
                        "10.0.0.0/16",
                        "10.1.0.0/24",
                    ],
                },
            }],
        },
        statelessDefaultActions: ["aws:pass"],
        statelessFragmentDefaultActions: ["aws:drop"],
        statelessRuleGroupReferences: [{
            priority: 1,
            resourceArn: exampleAwsNetworkfirewallRuleGroup.arn,
        }],
    },
    tags: {
        Tag1: "Value1",
        Tag2: "Value2",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.networkfirewall.FirewallPolicy("example",
    name="example",
    firewall_policy={
        "policy_variables": {
            "rule_variables": [{
                "key": "HOME_NET",
                "ip_set": {
                    "definitions": [
                        "10.0.0.0/16",
                        "10.1.0.0/24",
                    ],
                },
            }],
        },
        "stateless_default_actions": ["aws:pass"],
        "stateless_fragment_default_actions": ["aws:drop"],
        "stateless_rule_group_references": [{
            "priority": 1,
            "resource_arn": example_aws_networkfirewall_rule_group["arn"],
        }],
    },
    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.NewFirewallPolicy(ctx, "example", &networkfirewall.FirewallPolicyArgs{
			Name: pulumi.String("example"),
			FirewallPolicy: &networkfirewall.FirewallPolicyFirewallPolicyArgs{
				PolicyVariables: &networkfirewall.FirewallPolicyFirewallPolicyPolicyVariablesArgs{
					RuleVariables: networkfirewall.FirewallPolicyFirewallPolicyPolicyVariablesRuleVariableArray{
						&networkfirewall.FirewallPolicyFirewallPolicyPolicyVariablesRuleVariableArgs{
							Key: pulumi.String("HOME_NET"),
							IpSet: &networkfirewall.FirewallPolicyFirewallPolicyPolicyVariablesRuleVariableIpSetArgs{
								Definitions: pulumi.StringArray{
									pulumi.String("10.0.0.0/16"),
									pulumi.String("10.1.0.0/24"),
								},
							},
						},
					},
				},
				StatelessDefaultActions: pulumi.StringArray{
					pulumi.String("aws:pass"),
				},
				StatelessFragmentDefaultActions: pulumi.StringArray{
					pulumi.String("aws:drop"),
				},
				StatelessRuleGroupReferences: networkfirewall.FirewallPolicyFirewallPolicyStatelessRuleGroupReferenceArray{
					&networkfirewall.FirewallPolicyFirewallPolicyStatelessRuleGroupReferenceArgs{
						Priority:    pulumi.Int(1),
						ResourceArn: pulumi.Any(exampleAwsNetworkfirewallRuleGroup.Arn),
					},
				},
			},
			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.FirewallPolicy("example", new()
    {
        Name = "example",
        FirewallPolicyConfiguration = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyArgs
        {
            PolicyVariables = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyPolicyVariablesArgs
            {
                RuleVariables = new[]
                {
                    new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyPolicyVariablesRuleVariableArgs
                    {
                        Key = "HOME_NET",
                        IpSet = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyPolicyVariablesRuleVariableIpSetArgs
                        {
                            Definitions = new[]
                            {
                                "10.0.0.0/16",
                                "10.1.0.0/24",
                            },
                        },
                    },
                },
            },
            StatelessDefaultActions = new[]
            {
                "aws:pass",
            },
            StatelessFragmentDefaultActions = new[]
            {
                "aws:drop",
            },
            StatelessRuleGroupReferences = new[]
            {
                new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatelessRuleGroupReferenceArgs
                {
                    Priority = 1,
                    ResourceArn = exampleAwsNetworkfirewallRuleGroup.Arn,
                },
            },
        },
        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.FirewallPolicy;
import com.pulumi.aws.networkfirewall.FirewallPolicyArgs;
import com.pulumi.aws.networkfirewall.inputs.FirewallPolicyFirewallPolicyArgs;
import com.pulumi.aws.networkfirewall.inputs.FirewallPolicyFirewallPolicyPolicyVariablesArgs;
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 FirewallPolicy("example", FirewallPolicyArgs.builder()
            .name("example")
            .firewallPolicy(FirewallPolicyFirewallPolicyArgs.builder()
                .policyVariables(FirewallPolicyFirewallPolicyPolicyVariablesArgs.builder()
                    .ruleVariables(FirewallPolicyFirewallPolicyPolicyVariablesRuleVariableArgs.builder()
                        .key("HOME_NET")
                        .ipSet(FirewallPolicyFirewallPolicyPolicyVariablesRuleVariableIpSetArgs.builder()
                            .definitions(                            
                                "10.0.0.0/16",
                                "10.1.0.0/24")
                            .build())
                        .build())
                    .build())
                .statelessDefaultActions("aws:pass")
                .statelessFragmentDefaultActions("aws:drop")
                .statelessRuleGroupReferences(FirewallPolicyFirewallPolicyStatelessRuleGroupReferenceArgs.builder()
                    .priority(1)
                    .resourceArn(exampleAwsNetworkfirewallRuleGroup.arn())
                    .build())
                .build())
            .tags(Map.ofEntries(
                Map.entry("Tag1", "Value1"),
                Map.entry("Tag2", "Value2")
            ))
            .build());

    }
}
resources:
  example:
    type: aws:networkfirewall:FirewallPolicy
    properties:
      name: example
      firewallPolicy:
        policyVariables:
          ruleVariables:
            - key: HOME_NET
              ipSet:
                definitions:
                  - 10.0.0.0/16
                  - 10.1.0.0/24
        statelessDefaultActions:
          - aws:pass
        statelessFragmentDefaultActions:
          - aws:drop
        statelessRuleGroupReferences:
          - priority: 1
            resourceArn: ${exampleAwsNetworkfirewallRuleGroup.arn}
      tags:
        Tag1: Value1
        Tag2: Value2

The policyVariables block defines variable overrides. The ruleVariables array sets HOME_NET to your internal CIDR ranges. Rule groups that reference HOME_NET will use these definitions instead of defaults.

Publish metrics with custom stateless actions

Beyond built-in pass, drop, and forward actions, policies can define custom actions that publish CloudWatch metrics.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.networkfirewall.FirewallPolicy("example", {
    name: "example",
    firewallPolicy: {
        statelessDefaultActions: [
            "aws:pass",
            "ExampleCustomAction",
        ],
        statelessFragmentDefaultActions: ["aws:drop"],
        statelessCustomActions: [{
            actionDefinition: {
                publishMetricAction: {
                    dimensions: [{
                        value: "1",
                    }],
                },
            },
            actionName: "ExampleCustomAction",
        }],
    },
});
import pulumi
import pulumi_aws as aws

example = aws.networkfirewall.FirewallPolicy("example",
    name="example",
    firewall_policy={
        "stateless_default_actions": [
            "aws:pass",
            "ExampleCustomAction",
        ],
        "stateless_fragment_default_actions": ["aws:drop"],
        "stateless_custom_actions": [{
            "action_definition": {
                "publish_metric_action": {
                    "dimensions": [{
                        "value": "1",
                    }],
                },
            },
            "action_name": "ExampleCustomAction",
        }],
    })
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.NewFirewallPolicy(ctx, "example", &networkfirewall.FirewallPolicyArgs{
			Name: pulumi.String("example"),
			FirewallPolicy: &networkfirewall.FirewallPolicyFirewallPolicyArgs{
				StatelessDefaultActions: pulumi.StringArray{
					pulumi.String("aws:pass"),
					pulumi.String("ExampleCustomAction"),
				},
				StatelessFragmentDefaultActions: pulumi.StringArray{
					pulumi.String("aws:drop"),
				},
				StatelessCustomActions: networkfirewall.FirewallPolicyFirewallPolicyStatelessCustomActionArray{
					&networkfirewall.FirewallPolicyFirewallPolicyStatelessCustomActionArgs{
						ActionDefinition: &networkfirewall.FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionArgs{
							PublishMetricAction: &networkfirewall.FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionPublishMetricActionArgs{
								Dimensions: networkfirewall.FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionPublishMetricActionDimensionArray{
									&networkfirewall.FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionPublishMetricActionDimensionArgs{
										Value: pulumi.String("1"),
									},
								},
							},
						},
						ActionName: pulumi.String("ExampleCustomAction"),
					},
				},
			},
		})
		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.FirewallPolicy("example", new()
    {
        Name = "example",
        FirewallPolicyConfiguration = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyArgs
        {
            StatelessDefaultActions = new[]
            {
                "aws:pass",
                "ExampleCustomAction",
            },
            StatelessFragmentDefaultActions = new[]
            {
                "aws:drop",
            },
            StatelessCustomActions = new[]
            {
                new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatelessCustomActionArgs
                {
                    ActionDefinition = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionArgs
                    {
                        PublishMetricAction = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionPublishMetricActionArgs
                        {
                            Dimensions = new[]
                            {
                                new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionPublishMetricActionDimensionArgs
                                {
                                    Value = "1",
                                },
                            },
                        },
                    },
                    ActionName = "ExampleCustomAction",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkfirewall.FirewallPolicy;
import com.pulumi.aws.networkfirewall.FirewallPolicyArgs;
import com.pulumi.aws.networkfirewall.inputs.FirewallPolicyFirewallPolicyArgs;
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 FirewallPolicy("example", FirewallPolicyArgs.builder()
            .name("example")
            .firewallPolicy(FirewallPolicyFirewallPolicyArgs.builder()
                .statelessDefaultActions(                
                    "aws:pass",
                    "ExampleCustomAction")
                .statelessFragmentDefaultActions("aws:drop")
                .statelessCustomActions(FirewallPolicyFirewallPolicyStatelessCustomActionArgs.builder()
                    .actionDefinition(FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionArgs.builder()
                        .publishMetricAction(FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionPublishMetricActionArgs.builder()
                            .dimensions(FirewallPolicyFirewallPolicyStatelessCustomActionActionDefinitionPublishMetricActionDimensionArgs.builder()
                                .value("1")
                                .build())
                            .build())
                        .build())
                    .actionName("ExampleCustomAction")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:networkfirewall:FirewallPolicy
    properties:
      name: example
      firewallPolicy:
        statelessDefaultActions:
          - aws:pass
          - ExampleCustomAction
        statelessFragmentDefaultActions:
          - aws:drop
        statelessCustomActions:
          - actionDefinition:
              publishMetricAction:
                dimensions:
                  - value: '1'
            actionName: ExampleCustomAction

The statelessCustomActions array defines named actions. The publishMetricAction block sends metrics to CloudWatch with custom dimensions. Reference the action name in statelessDefaultActions to invoke it.

Enable deep threat inspection with AWS-managed rules

AWS provides managed stateful rule groups that detect known attack patterns. Policies can enable deep inspection on these groups.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const current = aws.getRegion({});
const currentGetPartition = aws.getPartition({});
const example = new aws.networkfirewall.FirewallPolicy("example", {
    name: "example",
    firewallPolicy: {
        statelessFragmentDefaultActions: ["aws:drop"],
        statelessDefaultActions: ["aws:pass"],
        statefulRuleGroupReferences: [{
            deepThreatInspection: "true",
            resourceArn: Promise.all([currentGetPartition, current]).then(([currentGetPartition, current]) => `arn:${currentGetPartition.partition}:network-firewall:${current.region}:aws-managed:stateful-rulegroup/AttackInfrastructureActionOrder`),
        }],
    },
});
import pulumi
import pulumi_aws as aws

current = aws.get_region()
current_get_partition = aws.get_partition()
example = aws.networkfirewall.FirewallPolicy("example",
    name="example",
    firewall_policy={
        "stateless_fragment_default_actions": ["aws:drop"],
        "stateless_default_actions": ["aws:pass"],
        "stateful_rule_group_references": [{
            "deep_threat_inspection": "true",
            "resource_arn": f"arn:{current_get_partition.partition}:network-firewall:{current.region}:aws-managed:stateful-rulegroup/AttackInfrastructureActionOrder",
        }],
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"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 {
		current, err := aws.GetRegion(ctx, &aws.GetRegionArgs{}, nil)
		if err != nil {
			return err
		}
		currentGetPartition, err := aws.GetPartition(ctx, &aws.GetPartitionArgs{}, nil)
		if err != nil {
			return err
		}
		_, err = networkfirewall.NewFirewallPolicy(ctx, "example", &networkfirewall.FirewallPolicyArgs{
			Name: pulumi.String("example"),
			FirewallPolicy: &networkfirewall.FirewallPolicyFirewallPolicyArgs{
				StatelessFragmentDefaultActions: pulumi.StringArray{
					pulumi.String("aws:drop"),
				},
				StatelessDefaultActions: pulumi.StringArray{
					pulumi.String("aws:pass"),
				},
				StatefulRuleGroupReferences: networkfirewall.FirewallPolicyFirewallPolicyStatefulRuleGroupReferenceArray{
					&networkfirewall.FirewallPolicyFirewallPolicyStatefulRuleGroupReferenceArgs{
						DeepThreatInspection: pulumi.String("true"),
						ResourceArn:          pulumi.Sprintf("arn:%v:network-firewall:%v:aws-managed:stateful-rulegroup/AttackInfrastructureActionOrder", currentGetPartition.Partition, current.Region),
					},
				},
			},
		})
		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 current = Aws.GetRegion.Invoke();

    var currentGetPartition = Aws.GetPartition.Invoke();

    var example = new Aws.NetworkFirewall.FirewallPolicy("example", new()
    {
        Name = "example",
        FirewallPolicyConfiguration = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyArgs
        {
            StatelessFragmentDefaultActions = new[]
            {
                "aws:drop",
            },
            StatelessDefaultActions = new[]
            {
                "aws:pass",
            },
            StatefulRuleGroupReferences = new[]
            {
                new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatefulRuleGroupReferenceArgs
                {
                    DeepThreatInspection = "true",
                    ResourceArn = Output.Tuple(currentGetPartition, current).Apply(values =>
                    {
                        var currentGetPartition = values.Item1;
                        var current = values.Item2;
                        return $"arn:{currentGetPartition.Apply(getPartitionResult => getPartitionResult.Partition)}:network-firewall:{current.Apply(getRegionResult => getRegionResult.Region)}:aws-managed:stateful-rulegroup/AttackInfrastructureActionOrder";
                    }),
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetRegionArgs;
import com.pulumi.aws.inputs.GetPartitionArgs;
import com.pulumi.aws.networkfirewall.FirewallPolicy;
import com.pulumi.aws.networkfirewall.FirewallPolicyArgs;
import com.pulumi.aws.networkfirewall.inputs.FirewallPolicyFirewallPolicyArgs;
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 current = AwsFunctions.getRegion(GetRegionArgs.builder()
            .build());

        final var currentGetPartition = AwsFunctions.getPartition(GetPartitionArgs.builder()
            .build());

        var example = new FirewallPolicy("example", FirewallPolicyArgs.builder()
            .name("example")
            .firewallPolicy(FirewallPolicyFirewallPolicyArgs.builder()
                .statelessFragmentDefaultActions("aws:drop")
                .statelessDefaultActions("aws:pass")
                .statefulRuleGroupReferences(FirewallPolicyFirewallPolicyStatefulRuleGroupReferenceArgs.builder()
                    .deepThreatInspection("true")
                    .resourceArn(String.format("arn:%s:network-firewall:%s:aws-managed:stateful-rulegroup/AttackInfrastructureActionOrder", currentGetPartition.partition(),current.region()))
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:networkfirewall:FirewallPolicy
    properties:
      name: example
      firewallPolicy:
        statelessFragmentDefaultActions:
          - aws:drop
        statelessDefaultActions:
          - aws:pass
        statefulRuleGroupReferences:
          - deepThreatInspection: true
            resourceArn: arn:${currentGetPartition.partition}:network-firewall:${current.region}:aws-managed:stateful-rulegroup/AttackInfrastructureActionOrder
variables:
  current:
    fn::invoke:
      function: aws:getRegion
      arguments: {}
  currentGetPartition:
    fn::invoke:
      function: aws:getPartition
      arguments: {}

The statefulRuleGroupReferences array attaches stateful rule groups. Setting deepThreatInspection to “true” enables enhanced detection. The resourceArn points to an AWS-managed rule group that contains attack signatures.

Control rule evaluation order with strict ordering

By default, Network Firewall evaluates stateful rules in action order (pass, drop, alert). Strict ordering evaluates rules by priority.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const current = aws.getRegion({});
const currentGetPartition = aws.getPartition({});
const example = new aws.networkfirewall.FirewallPolicy("example", {
    name: "example",
    firewallPolicy: {
        statelessFragmentDefaultActions: ["aws:drop"],
        statelessDefaultActions: ["aws:pass"],
        statefulEngineOptions: {
            ruleOrder: "STRICT_ORDER",
        },
        statefulRuleGroupReferences: [{
            deepThreatInspection: "false",
            priority: 1,
            resourceArn: Promise.all([currentGetPartition, current]).then(([currentGetPartition, current]) => `arn:${currentGetPartition.partition}:network-firewall:${current.region}:aws-managed:stateful-rulegroup/AttackInfrastructureStrictOrder`),
        }],
    },
});
import pulumi
import pulumi_aws as aws

current = aws.get_region()
current_get_partition = aws.get_partition()
example = aws.networkfirewall.FirewallPolicy("example",
    name="example",
    firewall_policy={
        "stateless_fragment_default_actions": ["aws:drop"],
        "stateless_default_actions": ["aws:pass"],
        "stateful_engine_options": {
            "rule_order": "STRICT_ORDER",
        },
        "stateful_rule_group_references": [{
            "deep_threat_inspection": "false",
            "priority": 1,
            "resource_arn": f"arn:{current_get_partition.partition}:network-firewall:{current.region}:aws-managed:stateful-rulegroup/AttackInfrastructureStrictOrder",
        }],
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"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 {
		current, err := aws.GetRegion(ctx, &aws.GetRegionArgs{}, nil)
		if err != nil {
			return err
		}
		currentGetPartition, err := aws.GetPartition(ctx, &aws.GetPartitionArgs{}, nil)
		if err != nil {
			return err
		}
		_, err = networkfirewall.NewFirewallPolicy(ctx, "example", &networkfirewall.FirewallPolicyArgs{
			Name: pulumi.String("example"),
			FirewallPolicy: &networkfirewall.FirewallPolicyFirewallPolicyArgs{
				StatelessFragmentDefaultActions: pulumi.StringArray{
					pulumi.String("aws:drop"),
				},
				StatelessDefaultActions: pulumi.StringArray{
					pulumi.String("aws:pass"),
				},
				StatefulEngineOptions: &networkfirewall.FirewallPolicyFirewallPolicyStatefulEngineOptionsArgs{
					RuleOrder: pulumi.String("STRICT_ORDER"),
				},
				StatefulRuleGroupReferences: networkfirewall.FirewallPolicyFirewallPolicyStatefulRuleGroupReferenceArray{
					&networkfirewall.FirewallPolicyFirewallPolicyStatefulRuleGroupReferenceArgs{
						DeepThreatInspection: pulumi.String("false"),
						Priority:             pulumi.Int(1),
						ResourceArn:          pulumi.Sprintf("arn:%v:network-firewall:%v:aws-managed:stateful-rulegroup/AttackInfrastructureStrictOrder", currentGetPartition.Partition, current.Region),
					},
				},
			},
		})
		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 current = Aws.GetRegion.Invoke();

    var currentGetPartition = Aws.GetPartition.Invoke();

    var example = new Aws.NetworkFirewall.FirewallPolicy("example", new()
    {
        Name = "example",
        FirewallPolicyConfiguration = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyArgs
        {
            StatelessFragmentDefaultActions = new[]
            {
                "aws:drop",
            },
            StatelessDefaultActions = new[]
            {
                "aws:pass",
            },
            StatefulEngineOptions = new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatefulEngineOptionsArgs
            {
                RuleOrder = "STRICT_ORDER",
            },
            StatefulRuleGroupReferences = new[]
            {
                new Aws.NetworkFirewall.Inputs.FirewallPolicyFirewallPolicyStatefulRuleGroupReferenceArgs
                {
                    DeepThreatInspection = "false",
                    Priority = 1,
                    ResourceArn = Output.Tuple(currentGetPartition, current).Apply(values =>
                    {
                        var currentGetPartition = values.Item1;
                        var current = values.Item2;
                        return $"arn:{currentGetPartition.Apply(getPartitionResult => getPartitionResult.Partition)}:network-firewall:{current.Apply(getRegionResult => getRegionResult.Region)}:aws-managed:stateful-rulegroup/AttackInfrastructureStrictOrder";
                    }),
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetRegionArgs;
import com.pulumi.aws.inputs.GetPartitionArgs;
import com.pulumi.aws.networkfirewall.FirewallPolicy;
import com.pulumi.aws.networkfirewall.FirewallPolicyArgs;
import com.pulumi.aws.networkfirewall.inputs.FirewallPolicyFirewallPolicyArgs;
import com.pulumi.aws.networkfirewall.inputs.FirewallPolicyFirewallPolicyStatefulEngineOptionsArgs;
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 current = AwsFunctions.getRegion(GetRegionArgs.builder()
            .build());

        final var currentGetPartition = AwsFunctions.getPartition(GetPartitionArgs.builder()
            .build());

        var example = new FirewallPolicy("example", FirewallPolicyArgs.builder()
            .name("example")
            .firewallPolicy(FirewallPolicyFirewallPolicyArgs.builder()
                .statelessFragmentDefaultActions("aws:drop")
                .statelessDefaultActions("aws:pass")
                .statefulEngineOptions(FirewallPolicyFirewallPolicyStatefulEngineOptionsArgs.builder()
                    .ruleOrder("STRICT_ORDER")
                    .build())
                .statefulRuleGroupReferences(FirewallPolicyFirewallPolicyStatefulRuleGroupReferenceArgs.builder()
                    .deepThreatInspection("false")
                    .priority(1)
                    .resourceArn(String.format("arn:%s:network-firewall:%s:aws-managed:stateful-rulegroup/AttackInfrastructureStrictOrder", currentGetPartition.partition(),current.region()))
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:networkfirewall:FirewallPolicy
    properties:
      name: example
      firewallPolicy:
        statelessFragmentDefaultActions:
          - aws:drop
        statelessDefaultActions:
          - aws:pass
        statefulEngineOptions:
          ruleOrder: STRICT_ORDER
        statefulRuleGroupReferences:
          - deepThreatInspection: false
            priority: 1
            resourceArn: arn:${currentGetPartition.partition}:network-firewall:${current.region}:aws-managed:stateful-rulegroup/AttackInfrastructureStrictOrder
variables:
  current:
    fn::invoke:
      function: aws:getRegion
      arguments: {}
  currentGetPartition:
    fn::invoke:
      function: aws:getPartition
      arguments: {}

The statefulEngineOptions block sets ruleOrder to “STRICT_ORDER”. In this mode, you must assign priority values to each rule group. Rules evaluate in ascending priority order regardless of their action type.

Beyond these examples

These snippets focus on specific firewall policy features: default actions and rule group attachment, variable overrides and custom actions, and threat detection and rule ordering. They’re intentionally minimal rather than full network security configurations.

The examples reference pre-existing infrastructure such as Network Firewall rule groups (stateless and stateful) and TLS inspection configurations. They focus on policy configuration rather than provisioning rule groups or firewall resources.

To keep things focused, common policy patterns are omitted, including:

  • Encryption configuration (encryptionConfiguration)
  • Stateful rule group priority in action order mode
  • Multiple custom actions and complex metric dimensions
  • Combining stateless and stateful rule groups in one policy

These omissions are intentional: the goal is to illustrate how each policy feature is wired, not provide drop-in security modules. See the Network Firewall Policy resource reference for all available configuration options.

Let's configure AWS Network Firewall Policies

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Immutability
Can I rename a firewall policy after creation?
No, the name property is immutable and cannot be changed after the policy is created. You’ll need to create a new policy with the desired name.
What are the required configuration fields for a firewall policy?
You must provide name, statelessDefaultActions (e.g., ["aws:pass"]), and statelessFragmentDefaultActions (e.g., ["aws:drop"]).
How do I override the HOME_NET variable?
Use policyVariables.ruleVariables with key "HOME_NET" and an ipSet containing your custom CIDR definitions like ["10.0.0.0/16", "10.1.0.0/24"].
Rule Ordering & Evaluation
What's the difference between action order and strict order rule evaluation?
Action order (default) evaluates rules based on their action type. Strict order evaluates rules by explicit priority. Set statefulEngineOptions.ruleOrder to "STRICT_ORDER" to use priority-based evaluation.
When do I need to set priority on rule group references?
Priority is required on statefulRuleGroupReferences only when using statefulEngineOptions.ruleOrder = "STRICT_ORDER". In default action order mode, priority is not needed.
Can I use AWS-managed rule groups for threat defense?
Yes, reference AWS-managed rule groups like AttackInfrastructureActionOrder or AttackInfrastructureStrictOrder in statefulRuleGroupReferences with the appropriate ARN format.
Custom Actions & Metrics
How do I create a custom action for stateless inspection?
Define the action in statelessCustomActions with an actionName and actionDefinition, then reference that actionName in statelessDefaultActions to activate it.
What does the deepThreatInspection setting do?
Set deepThreatInspection to "true" or "false" (as a string) on statefulRuleGroupReferences to enable or disable deep packet inspection for AWS-managed threat defense rule groups.

Using a different cloud?

Explore security guides for other cloud providers: