Configure GCP Network Firewall Policy Rules

The gcp:compute/networkFirewallPolicyRule:NetworkFirewallPolicyRule resource, part of the Pulumi GCP provider, defines individual firewall rules within a network firewall policy: their match conditions, actions, and traffic direction. This guide focuses on three capabilities: source and destination matching with address groups and threat intelligence, network scope filtering for VPC-based traffic control, and ingress and egress rule configuration.

Firewall rules belong to a NetworkFirewallPolicy and may reference AddressGroups, VPC networks, secure tags, and service accounts that must exist separately. The examples are intentionally small. Combine them with your own policy infrastructure and network topology.

Match traffic using address groups and threat intelligence

Security teams often centralize threat intelligence and IP management by filtering traffic based on multiple criteria: known malicious IPs, geographic regions, and organizational address groups.

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

The match block defines what traffic this rule evaluates. When traffic arrives, GCP checks it against srcAddressGroups (centrally managed IP lists), srcThreatIntelligences (Google’s threat feeds like “iplist-known-malicious-ips”), srcRegionCodes (geographic origin), and srcSecureTags (instance tags). The targetServiceAccounts property limits the rule to instances running under specific service accounts. The action property determines whether matching traffic is allowed or denied.

Control egress to internet destinations

Applications that need to restrict outbound traffic use egress rules with network scope filtering to prevent data exfiltration or enforce compliance boundaries.

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

Setting direction to “EGRESS” makes this rule evaluate outbound traffic. The destNetworkScope property set to “INTERNET” matches traffic leaving your VPC for public destinations. Combined with destIpRanges, you can allow or deny specific internet endpoints. The layer4Configs block with ipProtocol “all” applies the rule to all protocols and ports.

Filter ingress from specific VPC networks

Multi-VPC architectures often control which VPCs can send traffic to shared services by identifying traffic origin through 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 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 set to “VPC_NETWORKS” combined with srcNetworks filters traffic by VPC membership. Only traffic originating from the specified network IDs matches this rule. This extends the egress pattern by showing how to restrict which VPCs can reach your resources.

Beyond these examples

These snippets focus on specific rule-level features: source and destination matching, network scope and context filtering, and ingress and egress rule direction. They’re intentionally minimal rather than complete firewall policies.

The examples rely on pre-existing infrastructure such as NetworkFirewallPolicy (the parent policy), AddressGroup resources, TagKey/TagValue for secure tags, and VPC networks and service accounts. They focus on configuring individual rules rather than provisioning the entire policy hierarchy.

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

  • Security profile groups (securityProfileGroup, tlsInspect)
  • Protocol-specific filtering (layer4Configs with specific ports)
  • Rule priority ordering and conflict resolution
  • Logging configuration and export destinations

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 actions are available for firewall policy rules?
Four actions are supported: allow, deny, goto_next, and apply_security_profile_group.
What properties can't I change after creating a rule?
Three properties are immutable: firewallPolicy, priority, and project. You must recreate the rule to change these.
How does rule priority work?
Priority ranges from 0 (highest) to 2147483647 (lowest). Rules are evaluated from highest to lowest priority.
Traffic Matching & Filtering
What match conditions can I use to filter traffic?
Match conditions include srcIpRanges, destIpRanges, srcFqdns, srcThreatIntelligences, srcAddressGroups, layer4Configs, srcNetworkScope, destNetworkScope, srcNetworkContext, destNetworkContext, and srcNetworks.
What's the difference between networkScope and networkContext in match conditions?
Both are used for network-based matching. Examples show srcNetworkScope and destNetworkScope with values like VPC_NETWORKS or INTERNET, and separate examples show srcNetworkContext and destNetworkContext with the same values. Both can be used with srcNetworks or destNetworks for VPC-specific matching.
Targeting & Scope
Can I use targetSecureTags and targetServiceAccounts together?
No, targetSecureTags and targetServiceAccounts are mutually exclusive. You must choose one or the other.
Why isn't my rule being enforced even though I configured it correctly?
If all secure tags in targetSecureTags are in INEFFECTIVE state, the rule will be ignored. Ensure at least one secure tag is EFFECTIVE.
How many secure tags can I specify in targetSecureTags?
You can specify a maximum of 256 secure tags in targetSecureTags.
Logging & Security Profiles
Can I enable logging on goto_next rules?
No, logging cannot be enabled on rules with action set to goto_next.
When can I use securityProfileGroup and tlsInspect?
Both securityProfileGroup and tlsInspect can only be set when action is apply_security_profile_group. They cannot be used with other actions.

Using a different cloud?

Explore networking guides for other cloud providers: