Configure GCP Network Firewall Policy Rules

The gcp:compute/networkFirewallPolicyRule:NetworkFirewallPolicyRule resource, part of the Pulumi GCP provider, defines individual firewall rules within a NetworkFirewallPolicy: their match conditions, actions (allow or deny), and target scope. This guide focuses on three capabilities: egress filtering with network scope, ingress filtering from VPC networks, and multi-criteria source matching.

Firewall rules belong to a NetworkFirewallPolicy and may reference VPC networks, AddressGroups, or TagValues that must exist separately. The examples are intentionally small. Combine them with your own policies, networks, and security infrastructure.

Allow outbound traffic to the internet

Organizations often need to control which instances can reach external destinations based on network scope.

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

const basicNetworkFirewallPolicy = new gcp.compute.NetworkFirewallPolicy("basic_network_firewall_policy", {
    name: "fw-policy",
    description: "Sample global network firewall policy",
    project: "my-project-name",
});
const primary = new gcp.compute.NetworkFirewallPolicyRule("primary", {
    action: "allow",
    description: "This is a simple rule description",
    direction: "EGRESS",
    disabled: false,
    enableLogging: true,
    firewallPolicy: basicNetworkFirewallPolicy.name,
    priority: 1000,
    ruleName: "test-rule",
    match: {
        destIpRanges: ["10.100.0.1/32"],
        destNetworkScope: "INTERNET",
        layer4Configs: [{
            ipProtocol: "all",
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

basic_network_firewall_policy = gcp.compute.NetworkFirewallPolicy("basic_network_firewall_policy",
    name="fw-policy",
    description="Sample global network firewall policy",
    project="my-project-name")
primary = gcp.compute.NetworkFirewallPolicyRule("primary",
    action="allow",
    description="This is a simple rule description",
    direction="EGRESS",
    disabled=False,
    enable_logging=True,
    firewall_policy=basic_network_firewall_policy.name,
    priority=1000,
    rule_name="test-rule",
    match={
        "dest_ip_ranges": ["10.100.0.1/32"],
        "dest_network_scope": "INTERNET",
        "layer4_configs": [{
            "ip_protocol": "all",
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		basicNetworkFirewallPolicy, err := compute.NewNetworkFirewallPolicy(ctx, "basic_network_firewall_policy", &compute.NetworkFirewallPolicyArgs{
			Name:        pulumi.String("fw-policy"),
			Description: pulumi.String("Sample global network firewall policy"),
			Project:     pulumi.String("my-project-name"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewNetworkFirewallPolicyRule(ctx, "primary", &compute.NetworkFirewallPolicyRuleArgs{
			Action:         pulumi.String("allow"),
			Description:    pulumi.String("This is a simple rule description"),
			Direction:      pulumi.String("EGRESS"),
			Disabled:       pulumi.Bool(false),
			EnableLogging:  pulumi.Bool(true),
			FirewallPolicy: basicNetworkFirewallPolicy.Name,
			Priority:       pulumi.Int(1000),
			RuleName:       pulumi.String("test-rule"),
			Match: &compute.NetworkFirewallPolicyRuleMatchArgs{
				DestIpRanges: pulumi.StringArray{
					pulumi.String("10.100.0.1/32"),
				},
				DestNetworkScope: pulumi.String("INTERNET"),
				Layer4Configs: compute.NetworkFirewallPolicyRuleMatchLayer4ConfigArray{
					&compute.NetworkFirewallPolicyRuleMatchLayer4ConfigArgs{
						IpProtocol: pulumi.String("all"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var basicNetworkFirewallPolicy = new Gcp.Compute.NetworkFirewallPolicy("basic_network_firewall_policy", new()
    {
        Name = "fw-policy",
        Description = "Sample global network firewall policy",
        Project = "my-project-name",
    });

    var primary = new Gcp.Compute.NetworkFirewallPolicyRule("primary", new()
    {
        Action = "allow",
        Description = "This is a simple rule description",
        Direction = "EGRESS",
        Disabled = false,
        EnableLogging = true,
        FirewallPolicy = basicNetworkFirewallPolicy.Name,
        Priority = 1000,
        RuleName = "test-rule",
        Match = new Gcp.Compute.Inputs.NetworkFirewallPolicyRuleMatchArgs
        {
            DestIpRanges = new[]
            {
                "10.100.0.1/32",
            },
            DestNetworkScope = "INTERNET",
            Layer4Configs = new[]
            {
                new Gcp.Compute.Inputs.NetworkFirewallPolicyRuleMatchLayer4ConfigArgs
                {
                    IpProtocol = "all",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.NetworkFirewallPolicy;
import com.pulumi.gcp.compute.NetworkFirewallPolicyArgs;
import com.pulumi.gcp.compute.NetworkFirewallPolicyRule;
import com.pulumi.gcp.compute.NetworkFirewallPolicyRuleArgs;
import com.pulumi.gcp.compute.inputs.NetworkFirewallPolicyRuleMatchArgs;
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 basicNetworkFirewallPolicy = new NetworkFirewallPolicy("basicNetworkFirewallPolicy", NetworkFirewallPolicyArgs.builder()
            .name("fw-policy")
            .description("Sample global network firewall policy")
            .project("my-project-name")
            .build());

        var primary = new NetworkFirewallPolicyRule("primary", NetworkFirewallPolicyRuleArgs.builder()
            .action("allow")
            .description("This is a simple rule description")
            .direction("EGRESS")
            .disabled(false)
            .enableLogging(true)
            .firewallPolicy(basicNetworkFirewallPolicy.name())
            .priority(1000)
            .ruleName("test-rule")
            .match(NetworkFirewallPolicyRuleMatchArgs.builder()
                .destIpRanges("10.100.0.1/32")
                .destNetworkScope("INTERNET")
                .layer4Configs(NetworkFirewallPolicyRuleMatchLayer4ConfigArgs.builder()
                    .ipProtocol("all")
                    .build())
                .build())
            .build());

    }
}
resources:
  basicNetworkFirewallPolicy:
    type: gcp:compute:NetworkFirewallPolicy
    name: basic_network_firewall_policy
    properties:
      name: fw-policy
      description: Sample global network firewall policy
      project: my-project-name
  primary:
    type: gcp:compute:NetworkFirewallPolicyRule
    properties:
      action: allow
      description: This is a simple rule description
      direction: EGRESS
      disabled: false
      enableLogging: true
      firewallPolicy: ${basicNetworkFirewallPolicy.name}
      priority: 1000
      ruleName: test-rule
      match:
        destIpRanges:
          - 10.100.0.1/32
        destNetworkScope: INTERNET
        layer4Configs:
          - ipProtocol: all

When direction is EGRESS, the rule evaluates outbound traffic. The destNetworkScope property filters by destination type: INTERNET permits external destinations, while VPC_NETWORKS would restrict to private networks. The destIpRanges property further narrows the match to specific CIDR blocks. The layer4Configs block specifies which protocols to allow; “all” permits any IP protocol.

Accept traffic from specific VPC networks

Multi-VPC architectures require rules that permit traffic from trusted networks while blocking external sources.

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

const basicNetworkFirewallPolicy = new gcp.compute.NetworkFirewallPolicy("basic_network_firewall_policy", {
    name: "fw-policy",
    description: "Sample global network firewall policy",
    project: "my-project-name",
});
const network = new gcp.compute.Network("network", {name: "network"});
const primary = new gcp.compute.NetworkFirewallPolicyRule("primary", {
    action: "allow",
    description: "This is a simple rule description",
    direction: "INGRESS",
    disabled: false,
    enableLogging: true,
    firewallPolicy: basicNetworkFirewallPolicy.name,
    priority: 1000,
    ruleName: "test-rule",
    match: {
        srcIpRanges: ["11.100.0.1/32"],
        srcNetworkScope: "VPC_NETWORKS",
        srcNetworks: [network.id],
        layer4Configs: [{
            ipProtocol: "all",
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

basic_network_firewall_policy = gcp.compute.NetworkFirewallPolicy("basic_network_firewall_policy",
    name="fw-policy",
    description="Sample global network firewall policy",
    project="my-project-name")
network = gcp.compute.Network("network", name="network")
primary = gcp.compute.NetworkFirewallPolicyRule("primary",
    action="allow",
    description="This is a simple rule description",
    direction="INGRESS",
    disabled=False,
    enable_logging=True,
    firewall_policy=basic_network_firewall_policy.name,
    priority=1000,
    rule_name="test-rule",
    match={
        "src_ip_ranges": ["11.100.0.1/32"],
        "src_network_scope": "VPC_NETWORKS",
        "src_networks": [network.id],
        "layer4_configs": [{
            "ip_protocol": "all",
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		basicNetworkFirewallPolicy, err := compute.NewNetworkFirewallPolicy(ctx, "basic_network_firewall_policy", &compute.NetworkFirewallPolicyArgs{
			Name:        pulumi.String("fw-policy"),
			Description: pulumi.String("Sample global network firewall policy"),
			Project:     pulumi.String("my-project-name"),
		})
		if err != nil {
			return err
		}
		network, err := compute.NewNetwork(ctx, "network", &compute.NetworkArgs{
			Name: pulumi.String("network"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewNetworkFirewallPolicyRule(ctx, "primary", &compute.NetworkFirewallPolicyRuleArgs{
			Action:         pulumi.String("allow"),
			Description:    pulumi.String("This is a simple rule description"),
			Direction:      pulumi.String("INGRESS"),
			Disabled:       pulumi.Bool(false),
			EnableLogging:  pulumi.Bool(true),
			FirewallPolicy: basicNetworkFirewallPolicy.Name,
			Priority:       pulumi.Int(1000),
			RuleName:       pulumi.String("test-rule"),
			Match: &compute.NetworkFirewallPolicyRuleMatchArgs{
				SrcIpRanges: pulumi.StringArray{
					pulumi.String("11.100.0.1/32"),
				},
				SrcNetworkScope: pulumi.String("VPC_NETWORKS"),
				SrcNetworks: pulumi.StringArray{
					network.ID(),
				},
				Layer4Configs: compute.NetworkFirewallPolicyRuleMatchLayer4ConfigArray{
					&compute.NetworkFirewallPolicyRuleMatchLayer4ConfigArgs{
						IpProtocol: pulumi.String("all"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var basicNetworkFirewallPolicy = new Gcp.Compute.NetworkFirewallPolicy("basic_network_firewall_policy", new()
    {
        Name = "fw-policy",
        Description = "Sample global network firewall policy",
        Project = "my-project-name",
    });

    var network = new Gcp.Compute.Network("network", new()
    {
        Name = "network",
    });

    var primary = new Gcp.Compute.NetworkFirewallPolicyRule("primary", new()
    {
        Action = "allow",
        Description = "This is a simple rule description",
        Direction = "INGRESS",
        Disabled = false,
        EnableLogging = true,
        FirewallPolicy = basicNetworkFirewallPolicy.Name,
        Priority = 1000,
        RuleName = "test-rule",
        Match = new Gcp.Compute.Inputs.NetworkFirewallPolicyRuleMatchArgs
        {
            SrcIpRanges = new[]
            {
                "11.100.0.1/32",
            },
            SrcNetworkScope = "VPC_NETWORKS",
            SrcNetworks = new[]
            {
                network.Id,
            },
            Layer4Configs = new[]
            {
                new Gcp.Compute.Inputs.NetworkFirewallPolicyRuleMatchLayer4ConfigArgs
                {
                    IpProtocol = "all",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.NetworkFirewallPolicy;
import com.pulumi.gcp.compute.NetworkFirewallPolicyArgs;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.NetworkFirewallPolicyRule;
import com.pulumi.gcp.compute.NetworkFirewallPolicyRuleArgs;
import com.pulumi.gcp.compute.inputs.NetworkFirewallPolicyRuleMatchArgs;
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 basicNetworkFirewallPolicy = new NetworkFirewallPolicy("basicNetworkFirewallPolicy", NetworkFirewallPolicyArgs.builder()
            .name("fw-policy")
            .description("Sample global network firewall policy")
            .project("my-project-name")
            .build());

        var network = new Network("network", NetworkArgs.builder()
            .name("network")
            .build());

        var primary = new NetworkFirewallPolicyRule("primary", NetworkFirewallPolicyRuleArgs.builder()
            .action("allow")
            .description("This is a simple rule description")
            .direction("INGRESS")
            .disabled(false)
            .enableLogging(true)
            .firewallPolicy(basicNetworkFirewallPolicy.name())
            .priority(1000)
            .ruleName("test-rule")
            .match(NetworkFirewallPolicyRuleMatchArgs.builder()
                .srcIpRanges("11.100.0.1/32")
                .srcNetworkScope("VPC_NETWORKS")
                .srcNetworks(network.id())
                .layer4Configs(NetworkFirewallPolicyRuleMatchLayer4ConfigArgs.builder()
                    .ipProtocol("all")
                    .build())
                .build())
            .build());

    }
}
resources:
  basicNetworkFirewallPolicy:
    type: gcp:compute:NetworkFirewallPolicy
    name: basic_network_firewall_policy
    properties:
      name: fw-policy
      description: Sample global network firewall policy
      project: my-project-name
  primary:
    type: gcp:compute:NetworkFirewallPolicyRule
    properties:
      action: allow
      description: This is a simple rule description
      direction: INGRESS
      disabled: false
      enableLogging: true
      firewallPolicy: ${basicNetworkFirewallPolicy.name}
      priority: 1000
      ruleName: test-rule
      match:
        srcIpRanges:
          - 11.100.0.1/32
        srcNetworkScope: VPC_NETWORKS
        srcNetworks:
          - ${network.id}
        layer4Configs:
          - ipProtocol: all
  network:
    type: gcp:compute:Network
    properties:
      name: network

For INGRESS rules, srcNetworkScope and srcNetworks work together to filter by source VPC. Setting srcNetworkScope to VPC_NETWORKS restricts matches to traffic originating from VPCs, and srcNetworks lists the specific network IDs to allow. The srcIpRanges property adds an additional IP-based filter within those networks.

Filter ingress with address groups and threat intelligence

Security teams often combine multiple source filters to create defense-in-depth rules, layering address groups, FQDNs, region codes, and threat intelligence feeds.

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

const basicGlobalNetworksecurityAddressGroup = new gcp.networksecurity.AddressGroup("basic_global_networksecurity_address_group", {
    name: "address-group",
    parent: "projects/my-project-name",
    description: "Sample global networksecurity_address_group",
    location: "global",
    items: ["208.80.154.224/32"],
    type: "IPV4",
    capacity: 100,
});
const basicNetworkFirewallPolicy = new gcp.compute.NetworkFirewallPolicy("basic_network_firewall_policy", {
    name: "fw-policy",
    description: "Sample global network firewall policy",
    project: "my-project-name",
});
const basicNetwork = new gcp.compute.Network("basic_network", {name: "network"});
const basicKey = new gcp.tags.TagKey("basic_key", {
    description: "For keyname resources.",
    parent: "organizations/123456789",
    purpose: "GCE_FIREWALL",
    shortName: "tag-key",
    purposeData: {
        network: pulumi.interpolate`my-project-name/${basicNetwork.name}`,
    },
});
const basicValue = new gcp.tags.TagValue("basic_value", {
    description: "For valuename resources.",
    parent: basicKey.id,
    shortName: "tag-value",
});
const primary = new gcp.compute.NetworkFirewallPolicyRule("primary", {
    action: "allow",
    description: "This is a simple rule description",
    direction: "INGRESS",
    disabled: false,
    enableLogging: true,
    firewallPolicy: basicNetworkFirewallPolicy.name,
    priority: 1000,
    ruleName: "test-rule",
    targetServiceAccounts: ["my@service-account.com"],
    match: {
        srcAddressGroups: [basicGlobalNetworksecurityAddressGroup.id],
        srcIpRanges: ["10.100.0.1/32"],
        srcFqdns: ["google.com"],
        srcRegionCodes: ["US"],
        srcThreatIntelligences: ["iplist-known-malicious-ips"],
        srcSecureTags: [{
            name: basicValue.id,
        }],
        layer4Configs: [{
            ipProtocol: "all",
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

basic_global_networksecurity_address_group = gcp.networksecurity.AddressGroup("basic_global_networksecurity_address_group",
    name="address-group",
    parent="projects/my-project-name",
    description="Sample global networksecurity_address_group",
    location="global",
    items=["208.80.154.224/32"],
    type="IPV4",
    capacity=100)
basic_network_firewall_policy = gcp.compute.NetworkFirewallPolicy("basic_network_firewall_policy",
    name="fw-policy",
    description="Sample global network firewall policy",
    project="my-project-name")
basic_network = gcp.compute.Network("basic_network", name="network")
basic_key = gcp.tags.TagKey("basic_key",
    description="For keyname resources.",
    parent="organizations/123456789",
    purpose="GCE_FIREWALL",
    short_name="tag-key",
    purpose_data={
        "network": basic_network.name.apply(lambda name: f"my-project-name/{name}"),
    })
basic_value = gcp.tags.TagValue("basic_value",
    description="For valuename resources.",
    parent=basic_key.id,
    short_name="tag-value")
primary = gcp.compute.NetworkFirewallPolicyRule("primary",
    action="allow",
    description="This is a simple rule description",
    direction="INGRESS",
    disabled=False,
    enable_logging=True,
    firewall_policy=basic_network_firewall_policy.name,
    priority=1000,
    rule_name="test-rule",
    target_service_accounts=["my@service-account.com"],
    match={
        "src_address_groups": [basic_global_networksecurity_address_group.id],
        "src_ip_ranges": ["10.100.0.1/32"],
        "src_fqdns": ["google.com"],
        "src_region_codes": ["US"],
        "src_threat_intelligences": ["iplist-known-malicious-ips"],
        "src_secure_tags": [{
            "name": basic_value.id,
        }],
        "layer4_configs": [{
            "ip_protocol": "all",
        }],
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networksecurity"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/tags"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		basicGlobalNetworksecurityAddressGroup, err := networksecurity.NewAddressGroup(ctx, "basic_global_networksecurity_address_group", &networksecurity.AddressGroupArgs{
			Name:        pulumi.String("address-group"),
			Parent:      pulumi.String("projects/my-project-name"),
			Description: pulumi.String("Sample global networksecurity_address_group"),
			Location:    pulumi.String("global"),
			Items: pulumi.StringArray{
				pulumi.String("208.80.154.224/32"),
			},
			Type:     pulumi.String("IPV4"),
			Capacity: pulumi.Int(100),
		})
		if err != nil {
			return err
		}
		basicNetworkFirewallPolicy, err := compute.NewNetworkFirewallPolicy(ctx, "basic_network_firewall_policy", &compute.NetworkFirewallPolicyArgs{
			Name:        pulumi.String("fw-policy"),
			Description: pulumi.String("Sample global network firewall policy"),
			Project:     pulumi.String("my-project-name"),
		})
		if err != nil {
			return err
		}
		basicNetwork, err := compute.NewNetwork(ctx, "basic_network", &compute.NetworkArgs{
			Name: pulumi.String("network"),
		})
		if err != nil {
			return err
		}
		basicKey, err := tags.NewTagKey(ctx, "basic_key", &tags.TagKeyArgs{
			Description: pulumi.String("For keyname resources."),
			Parent:      pulumi.String("organizations/123456789"),
			Purpose:     pulumi.String("GCE_FIREWALL"),
			ShortName:   pulumi.String("tag-key"),
			PurposeData: pulumi.StringMap{
				"network": basicNetwork.Name.ApplyT(func(name string) (string, error) {
					return fmt.Sprintf("my-project-name/%v", name), nil
				}).(pulumi.StringOutput),
			},
		})
		if err != nil {
			return err
		}
		basicValue, err := tags.NewTagValue(ctx, "basic_value", &tags.TagValueArgs{
			Description: pulumi.String("For valuename resources."),
			Parent:      basicKey.ID(),
			ShortName:   pulumi.String("tag-value"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewNetworkFirewallPolicyRule(ctx, "primary", &compute.NetworkFirewallPolicyRuleArgs{
			Action:         pulumi.String("allow"),
			Description:    pulumi.String("This is a simple rule description"),
			Direction:      pulumi.String("INGRESS"),
			Disabled:       pulumi.Bool(false),
			EnableLogging:  pulumi.Bool(true),
			FirewallPolicy: basicNetworkFirewallPolicy.Name,
			Priority:       pulumi.Int(1000),
			RuleName:       pulumi.String("test-rule"),
			TargetServiceAccounts: pulumi.StringArray{
				pulumi.String("my@service-account.com"),
			},
			Match: &compute.NetworkFirewallPolicyRuleMatchArgs{
				SrcAddressGroups: pulumi.StringArray{
					basicGlobalNetworksecurityAddressGroup.ID(),
				},
				SrcIpRanges: pulumi.StringArray{
					pulumi.String("10.100.0.1/32"),
				},
				SrcFqdns: pulumi.StringArray{
					pulumi.String("google.com"),
				},
				SrcRegionCodes: pulumi.StringArray{
					pulumi.String("US"),
				},
				SrcThreatIntelligences: pulumi.StringArray{
					pulumi.String("iplist-known-malicious-ips"),
				},
				SrcSecureTags: compute.NetworkFirewallPolicyRuleMatchSrcSecureTagArray{
					&compute.NetworkFirewallPolicyRuleMatchSrcSecureTagArgs{
						Name: basicValue.ID(),
					},
				},
				Layer4Configs: compute.NetworkFirewallPolicyRuleMatchLayer4ConfigArray{
					&compute.NetworkFirewallPolicyRuleMatchLayer4ConfigArgs{
						IpProtocol: pulumi.String("all"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var basicGlobalNetworksecurityAddressGroup = new Gcp.NetworkSecurity.AddressGroup("basic_global_networksecurity_address_group", new()
    {
        Name = "address-group",
        Parent = "projects/my-project-name",
        Description = "Sample global networksecurity_address_group",
        Location = "global",
        Items = new[]
        {
            "208.80.154.224/32",
        },
        Type = "IPV4",
        Capacity = 100,
    });

    var basicNetworkFirewallPolicy = new Gcp.Compute.NetworkFirewallPolicy("basic_network_firewall_policy", new()
    {
        Name = "fw-policy",
        Description = "Sample global network firewall policy",
        Project = "my-project-name",
    });

    var basicNetwork = new Gcp.Compute.Network("basic_network", new()
    {
        Name = "network",
    });

    var basicKey = new Gcp.Tags.TagKey("basic_key", new()
    {
        Description = "For keyname resources.",
        Parent = "organizations/123456789",
        Purpose = "GCE_FIREWALL",
        ShortName = "tag-key",
        PurposeData = 
        {
            { "network", basicNetwork.Name.Apply(name => $"my-project-name/{name}") },
        },
    });

    var basicValue = new Gcp.Tags.TagValue("basic_value", new()
    {
        Description = "For valuename resources.",
        Parent = basicKey.Id,
        ShortName = "tag-value",
    });

    var primary = new Gcp.Compute.NetworkFirewallPolicyRule("primary", new()
    {
        Action = "allow",
        Description = "This is a simple rule description",
        Direction = "INGRESS",
        Disabled = false,
        EnableLogging = true,
        FirewallPolicy = basicNetworkFirewallPolicy.Name,
        Priority = 1000,
        RuleName = "test-rule",
        TargetServiceAccounts = new[]
        {
            "my@service-account.com",
        },
        Match = new Gcp.Compute.Inputs.NetworkFirewallPolicyRuleMatchArgs
        {
            SrcAddressGroups = new[]
            {
                basicGlobalNetworksecurityAddressGroup.Id,
            },
            SrcIpRanges = new[]
            {
                "10.100.0.1/32",
            },
            SrcFqdns = new[]
            {
                "google.com",
            },
            SrcRegionCodes = new[]
            {
                "US",
            },
            SrcThreatIntelligences = new[]
            {
                "iplist-known-malicious-ips",
            },
            SrcSecureTags = new[]
            {
                new Gcp.Compute.Inputs.NetworkFirewallPolicyRuleMatchSrcSecureTagArgs
                {
                    Name = basicValue.Id,
                },
            },
            Layer4Configs = new[]
            {
                new Gcp.Compute.Inputs.NetworkFirewallPolicyRuleMatchLayer4ConfigArgs
                {
                    IpProtocol = "all",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networksecurity.AddressGroup;
import com.pulumi.gcp.networksecurity.AddressGroupArgs;
import com.pulumi.gcp.compute.NetworkFirewallPolicy;
import com.pulumi.gcp.compute.NetworkFirewallPolicyArgs;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.tags.TagKey;
import com.pulumi.gcp.tags.TagKeyArgs;
import com.pulumi.gcp.tags.TagValue;
import com.pulumi.gcp.tags.TagValueArgs;
import com.pulumi.gcp.compute.NetworkFirewallPolicyRule;
import com.pulumi.gcp.compute.NetworkFirewallPolicyRuleArgs;
import com.pulumi.gcp.compute.inputs.NetworkFirewallPolicyRuleMatchArgs;
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 basicGlobalNetworksecurityAddressGroup = new AddressGroup("basicGlobalNetworksecurityAddressGroup", AddressGroupArgs.builder()
            .name("address-group")
            .parent("projects/my-project-name")
            .description("Sample global networksecurity_address_group")
            .location("global")
            .items("208.80.154.224/32")
            .type("IPV4")
            .capacity(100)
            .build());

        var basicNetworkFirewallPolicy = new NetworkFirewallPolicy("basicNetworkFirewallPolicy", NetworkFirewallPolicyArgs.builder()
            .name("fw-policy")
            .description("Sample global network firewall policy")
            .project("my-project-name")
            .build());

        var basicNetwork = new Network("basicNetwork", NetworkArgs.builder()
            .name("network")
            .build());

        var basicKey = new TagKey("basicKey", TagKeyArgs.builder()
            .description("For keyname resources.")
            .parent("organizations/123456789")
            .purpose("GCE_FIREWALL")
            .shortName("tag-key")
            .purposeData(Map.of("network", basicNetwork.name().applyValue(_name -> String.format("my-project-name/%s", _name))))
            .build());

        var basicValue = new TagValue("basicValue", TagValueArgs.builder()
            .description("For valuename resources.")
            .parent(basicKey.id())
            .shortName("tag-value")
            .build());

        var primary = new NetworkFirewallPolicyRule("primary", NetworkFirewallPolicyRuleArgs.builder()
            .action("allow")
            .description("This is a simple rule description")
            .direction("INGRESS")
            .disabled(false)
            .enableLogging(true)
            .firewallPolicy(basicNetworkFirewallPolicy.name())
            .priority(1000)
            .ruleName("test-rule")
            .targetServiceAccounts("my@service-account.com")
            .match(NetworkFirewallPolicyRuleMatchArgs.builder()
                .srcAddressGroups(basicGlobalNetworksecurityAddressGroup.id())
                .srcIpRanges("10.100.0.1/32")
                .srcFqdns("google.com")
                .srcRegionCodes("US")
                .srcThreatIntelligences("iplist-known-malicious-ips")
                .srcSecureTags(NetworkFirewallPolicyRuleMatchSrcSecureTagArgs.builder()
                    .name(basicValue.id())
                    .build())
                .layer4Configs(NetworkFirewallPolicyRuleMatchLayer4ConfigArgs.builder()
                    .ipProtocol("all")
                    .build())
                .build())
            .build());

    }
}
resources:
  basicGlobalNetworksecurityAddressGroup:
    type: gcp:networksecurity:AddressGroup
    name: basic_global_networksecurity_address_group
    properties:
      name: address-group
      parent: projects/my-project-name
      description: Sample global networksecurity_address_group
      location: global
      items:
        - 208.80.154.224/32
      type: IPV4
      capacity: 100
  basicNetworkFirewallPolicy:
    type: gcp:compute:NetworkFirewallPolicy
    name: basic_network_firewall_policy
    properties:
      name: fw-policy
      description: Sample global network firewall policy
      project: my-project-name
  primary:
    type: gcp:compute:NetworkFirewallPolicyRule
    properties:
      action: allow
      description: This is a simple rule description
      direction: INGRESS
      disabled: false
      enableLogging: true
      firewallPolicy: ${basicNetworkFirewallPolicy.name}
      priority: 1000
      ruleName: test-rule
      targetServiceAccounts:
        - my@service-account.com
      match:
        srcAddressGroups:
          - ${basicGlobalNetworksecurityAddressGroup.id}
        srcIpRanges:
          - 10.100.0.1/32
        srcFqdns:
          - google.com
        srcRegionCodes:
          - US
        srcThreatIntelligences:
          - iplist-known-malicious-ips
        srcSecureTags:
          - name: ${basicValue.id}
        layer4Configs:
          - ipProtocol: all
  basicNetwork:
    type: gcp:compute:Network
    name: basic_network
    properties:
      name: network
  basicKey:
    type: gcp:tags:TagKey
    name: basic_key
    properties:
      description: For keyname resources.
      parent: organizations/123456789
      purpose: GCE_FIREWALL
      shortName: tag-key
      purposeData:
        network: my-project-name/${basicNetwork.name}
  basicValue:
    type: gcp:tags:TagValue
    name: basic_value
    properties:
      description: For valuename resources.
      parent: ${basicKey.id}
      shortName: tag-value

This configuration demonstrates advanced source matching. The srcAddressGroups property references a NetworkSecurity AddressGroup containing IP ranges. The srcFqdns property filters by domain name, srcRegionCodes restricts by geographic origin, and srcThreatIntelligences blocks known malicious IPs. The srcSecureTags property applies the rule only to instances with specific secure tags. The targetServiceAccounts property further narrows the rule to specific service accounts. All these conditions combine to create a layered ingress filter.

Beyond these examples

These snippets focus on specific rule-level features: ingress and egress direction control, network scope filtering, and source criteria including address groups and threat intelligence. They’re intentionally minimal rather than full firewall policies.

The examples reference pre-existing infrastructure such as NetworkFirewallPolicy resources, VPC networks for network scope filtering, and NetworkSecurity AddressGroups and TagValues. They focus on configuring individual rules rather than provisioning the surrounding policy and network infrastructure.

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

  • Security profile groups and TLS inspection (securityProfileGroup, tlsInspect)
  • Rule chaining with goto_next action
  • Destination filtering for ingress rules
  • Layer 4 protocol-specific configuration (TCP/UDP ports)

These omissions are intentional: the goal is to illustrate how each rule feature is wired, not provide drop-in firewall modules. See the NetworkFirewallPolicyRule resource reference for all available configuration options.

Let's configure GCP Network Firewall Policy Rules

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Rule Configuration & Actions
What are the available actions and their constraints?
Four actions are available: allow, deny, goto_next, and apply_security_profile_group. The apply_security_profile_group action requires securityProfileGroup to be specified and is the only action that supports tlsInspect. The goto_next action cannot have logging enabled.
How does rule priority work?
Priority is a required integer between 0 and 2147483647, where 0 is the highest priority and 2147483647 is the lowest. Rules are evaluated from highest to lowest priority.
What properties are immutable after creation?
Three properties cannot be changed after creation: firewallPolicy, priority, and project.
Targeting & Scope
Can I use both targetServiceAccounts and targetSecureTags on the same rule?
No, targetServiceAccounts and targetSecureTags are mutually exclusive. You must choose one targeting method or neither (which applies the rule to all instances).
What happens if all my targetSecureTags are in INEFFECTIVE state?
The rule will be ignored if all specified secure tags are INEFFECTIVE. At least one tag must be in EFFECTIVE state for the rule to apply.
How many secure tags can I specify in targetSecureTags?
You can specify a maximum of 256 secure tags in targetSecureTags.
How do I match ingress traffic from specific VPC networks?
Set direction to INGRESS and configure match.srcNetworkScope to VPC_NETWORKS, then specify the network IDs in match.srcNetworks.
Match Conditions & Traffic Filtering
What source match conditions are available for ingress rules?
You can match on srcIpRanges, srcAddressGroups, srcFqdns, srcRegionCodes, srcThreatIntelligences, srcSecureTags, srcNetworkScope, and srcNetworks. All are configured within the match object.
How do I filter egress traffic destined for the internet?
Set direction to EGRESS and configure match.destNetworkScope to INTERNET along with match.destIpRanges to specify destination IP ranges.
Logging & Limitations
When can I enable logging on a firewall rule?
You can enable logging on allow, deny, and apply_security_profile_group actions. Logging cannot be enabled on goto_next rules.
What is the difference between INGRESS and EGRESS direction?
INGRESS rules apply to incoming traffic to your instances, while EGRESS rules apply to outgoing traffic from your instances. The direction determines which match conditions are available (source conditions for INGRESS, destination conditions for EGRESS).
Can I import an existing firewall policy rule?
Yes, you can import using the format projects/{{project}}/global/firewallPolicies/{{firewall_policy}}/rules/{{priority}}, or the shorter formats {{project}}/{{firewall_policy}}/{{priority}} or {{firewall_policy}}/{{priority}}.

Using a different cloud?

Explore networking guides for other cloud providers: