Configure AWS Network Firewall Policies

The aws:networkfirewall/firewallPolicy:FirewallPolicy resource, part of the Pulumi AWS provider, defines a Network Firewall policy that controls traffic inspection behavior: default actions, rule group references, and evaluation order. This guide focuses on four capabilities: default action configuration, policy variables and custom actions, AWS-managed threat detection, and rule evaluation ordering.

Firewall policies reference existing rule groups (stateless and stateful) and optionally TLS inspection configurations. The examples are intentionally small. Combine them with your own rule groups and network infrastructure.

Define default actions and attach rule groups

Network Firewall 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 (
	"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: {}

When traffic doesn’t match any rule, Network Firewall applies the default action. The statelessDefaultActions property handles complete packets; statelessFragmentDefaultActions handles fragments. The statelessRuleGroupReferences array attaches rule groups with priority values that control evaluation order. The tlsInspectionConfigurationArn enables TLS decryption for encrypted traffic inspection.

Override HOME_NET with custom IP ranges

Rule groups often reference the HOME_NET variable to distinguish internal from external traffic. Policies override this variable to match your network 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 variables that rule groups can reference. The ruleVariables array sets HOME_NET to your internal IP ranges. Rule groups use this variable to identify traffic originating from or destined to your network.

Publish metrics with custom stateless actions

Beyond AWS’s built-in actions (pass, drop, forward), 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 actions you can reference in default actions or rule groups. Each action has an actionName and an actionDefinition. The publishMetricAction sends custom dimensions to CloudWatch when the action executes. 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 enable deep threat inspection on these rule groups for enhanced security.

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 (
	"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. Set deepThreatInspection to “true” to enable enhanced threat detection. AWS-managed rule groups like AttackInfrastructureActionOrder provide continuously updated threat intelligence without manual rule maintenance.

Control rule evaluation order with strict ordering

By default, Network Firewall evaluates stateful rules in action order (pass rules first, then drop/alert). Strict order mode evaluates rules by explicit 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 (
	"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 controls how Network Firewall evaluates stateful rules. Set ruleOrder to “STRICT_ORDER” to evaluate rules by priority value instead of action type. Each rule group reference must include a priority property. Lower priority values evaluate first. This extends the threat detection pattern from the previous example by adding explicit control over evaluation sequence.

Beyond these examples

These snippets focus on specific policy-level features: default actions and rule group attachment, policy variables 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:

  • Stateful rule group references without threat detection
  • KMS encryption configuration (encryptionConfiguration)
  • Multiple rule group priorities and ordering
  • Custom action definitions beyond metrics

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
What happens if I change the firewall policy name?
The name property is immutable, so changing it forces replacement of the entire firewall policy resource.
What actions are required when creating a firewall policy?
You must specify statelessDefaultActions (e.g., aws:pass) and statelessFragmentDefaultActions (e.g., aws:drop) for stateless traffic inspection.
Rule Groups & Ordering
What's the difference between ACTION_ORDER and STRICT_ORDER for stateful rules?
ACTION_ORDER (default) evaluates rules by action priority without requiring explicit priority values. STRICT_ORDER requires you to set a priority for each stateful rule group reference.
When do I need to specify priority for stateful rule groups?
Priority is required when using STRICT_ORDER in statefulEngineOptions.ruleOrder. With ACTION_ORDER, priority is not used.
Advanced Features
How do I override HOME_NET in my firewall policy?
Configure policyVariables.ruleVariables with key: "HOME_NET" and provide IP definitions in ipSet.definitions (e.g., ["10.0.0.0/16", "10.1.0.0/24"]).
How do I create custom actions for stateless inspection?
Define statelessCustomActions with an actionDefinition (such as publishMetricAction) and reference the actionName in your statelessDefaultActions array.
How do I enable deep threat inspection?
Set deepThreatInspection: "true" in statefulRuleGroupReferences and use AWS-managed rule groups like AttackInfrastructureActionOrder or AttackInfrastructureStrictOrder.
How do I enable TLS inspection for my firewall policy?
Specify tlsInspectionConfigurationArn in the firewallPolicy block, pointing to your TLS inspection configuration ARN.
Can I use both stateless and stateful rule groups in the same policy?
Yes, configure statelessRuleGroupReferences for stateless rules and statefulRuleGroupReferences for stateful rules within the same firewallPolicy block.

Using a different cloud?

Explore security guides for other cloud providers: