Configure GCP Region Security Policy Rules

The gcp:compute/regionSecurityPolicyRule:RegionSecurityPolicyRule resource, part of the Pulumi GCP provider, defines individual rules within a RegionSecurityPolicy that match traffic patterns and enforce allow, deny, or rate-limiting actions. This guide focuses on four capabilities: IP-based access control, default-deny patterns, WAF exclusion configuration, and packet-level network matching.

Rules belong to a RegionSecurityPolicy and reference its name. Network match rules require advanced DDoS protection and NetworkEdgeSecurityService. The examples are intentionally small. Combine them with your own security policies and network infrastructure.

Allow traffic from specific IP ranges

Most Cloud Armor deployments start by defining rules that allow or deny traffic based on source IP addresses.

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

const _default = new gcp.compute.RegionSecurityPolicy("default", {
    region: "us-west2",
    name: "policyruletest",
    description: "basic region security policy",
    type: "CLOUD_ARMOR",
});
const policyRule = new gcp.compute.RegionSecurityPolicyRule("policy_rule", {
    region: "us-west2",
    securityPolicy: _default.name,
    description: "new rule",
    priority: 100,
    match: {
        versionedExpr: "SRC_IPS_V1",
        config: {
            srcIpRanges: ["10.10.0.0/16"],
        },
    },
    action: "allow",
    preview: true,
});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.RegionSecurityPolicy("default",
    region="us-west2",
    name="policyruletest",
    description="basic region security policy",
    type="CLOUD_ARMOR")
policy_rule = gcp.compute.RegionSecurityPolicyRule("policy_rule",
    region="us-west2",
    security_policy=default.name,
    description="new rule",
    priority=100,
    match={
        "versioned_expr": "SRC_IPS_V1",
        "config": {
            "src_ip_ranges": ["10.10.0.0/16"],
        },
    },
    action="allow",
    preview=True)
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 {
		_default, err := compute.NewRegionSecurityPolicy(ctx, "default", &compute.RegionSecurityPolicyArgs{
			Region:      pulumi.String("us-west2"),
			Name:        pulumi.String("policyruletest"),
			Description: pulumi.String("basic region security policy"),
			Type:        pulumi.String("CLOUD_ARMOR"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewRegionSecurityPolicyRule(ctx, "policy_rule", &compute.RegionSecurityPolicyRuleArgs{
			Region:         pulumi.String("us-west2"),
			SecurityPolicy: _default.Name,
			Description:    pulumi.String("new rule"),
			Priority:       pulumi.Int(100),
			Match: &compute.RegionSecurityPolicyRuleMatchArgs{
				VersionedExpr: pulumi.String("SRC_IPS_V1"),
				Config: &compute.RegionSecurityPolicyRuleMatchConfigArgs{
					SrcIpRanges: pulumi.StringArray{
						pulumi.String("10.10.0.0/16"),
					},
				},
			},
			Action:  pulumi.String("allow"),
			Preview: pulumi.Bool(true),
		})
		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 @default = new Gcp.Compute.RegionSecurityPolicy("default", new()
    {
        Region = "us-west2",
        Name = "policyruletest",
        Description = "basic region security policy",
        Type = "CLOUD_ARMOR",
    });

    var policyRule = new Gcp.Compute.RegionSecurityPolicyRule("policy_rule", new()
    {
        Region = "us-west2",
        SecurityPolicy = @default.Name,
        Description = "new rule",
        Priority = 100,
        Match = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleMatchArgs
        {
            VersionedExpr = "SRC_IPS_V1",
            Config = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleMatchConfigArgs
            {
                SrcIpRanges = new[]
                {
                    "10.10.0.0/16",
                },
            },
        },
        Action = "allow",
        Preview = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.RegionSecurityPolicy;
import com.pulumi.gcp.compute.RegionSecurityPolicyArgs;
import com.pulumi.gcp.compute.RegionSecurityPolicyRule;
import com.pulumi.gcp.compute.RegionSecurityPolicyRuleArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyRuleMatchArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyRuleMatchConfigArgs;
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 default_ = new RegionSecurityPolicy("default", RegionSecurityPolicyArgs.builder()
            .region("us-west2")
            .name("policyruletest")
            .description("basic region security policy")
            .type("CLOUD_ARMOR")
            .build());

        var policyRule = new RegionSecurityPolicyRule("policyRule", RegionSecurityPolicyRuleArgs.builder()
            .region("us-west2")
            .securityPolicy(default_.name())
            .description("new rule")
            .priority(100)
            .match(RegionSecurityPolicyRuleMatchArgs.builder()
                .versionedExpr("SRC_IPS_V1")
                .config(RegionSecurityPolicyRuleMatchConfigArgs.builder()
                    .srcIpRanges("10.10.0.0/16")
                    .build())
                .build())
            .action("allow")
            .preview(true)
            .build());

    }
}
resources:
  default:
    type: gcp:compute:RegionSecurityPolicy
    properties:
      region: us-west2
      name: policyruletest
      description: basic region security policy
      type: CLOUD_ARMOR
  policyRule:
    type: gcp:compute:RegionSecurityPolicyRule
    name: policy_rule
    properties:
      region: us-west2
      securityPolicy: ${default.name}
      description: new rule
      priority: 100
      match:
        versionedExpr: SRC_IPS_V1
        config:
          srcIpRanges:
            - 10.10.0.0/16
      action: allow
      preview: true

When a request arrives, Cloud Armor evaluates it against the match condition. The versionedExpr field specifies the match type (SRC_IPS_V1 for IP-based matching), and srcIpRanges lists the CIDR blocks to match. The priority determines evaluation order: lower numbers are evaluated first. The action specifies what happens when the rule matches (allow or deny).

Configure a default deny rule with exceptions

Security policies often use a default-deny approach where all traffic is blocked unless explicitly allowed by higher-priority rules.

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

const _default = new gcp.compute.RegionSecurityPolicy("default", {
    region: "us-west2",
    name: "policywithdefaultrule",
    description: "basic region security policy",
    type: "CLOUD_ARMOR",
});
const defaultRule = new gcp.compute.RegionSecurityPolicyRule("default_rule", {
    region: "us-west2",
    securityPolicy: _default.name,
    description: "new rule",
    action: "deny",
    priority: 2147483647,
    match: {
        versionedExpr: "SRC_IPS_V1",
        config: {
            srcIpRanges: ["*"],
        },
    },
});
const policyRule = new gcp.compute.RegionSecurityPolicyRule("policy_rule", {
    region: "us-west2",
    securityPolicy: _default.name,
    description: "new rule",
    priority: 100,
    match: {
        versionedExpr: "SRC_IPS_V1",
        config: {
            srcIpRanges: ["10.10.0.0/16"],
        },
    },
    action: "allow",
    preview: true,
});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.RegionSecurityPolicy("default",
    region="us-west2",
    name="policywithdefaultrule",
    description="basic region security policy",
    type="CLOUD_ARMOR")
default_rule = gcp.compute.RegionSecurityPolicyRule("default_rule",
    region="us-west2",
    security_policy=default.name,
    description="new rule",
    action="deny",
    priority=2147483647,
    match={
        "versioned_expr": "SRC_IPS_V1",
        "config": {
            "src_ip_ranges": ["*"],
        },
    })
policy_rule = gcp.compute.RegionSecurityPolicyRule("policy_rule",
    region="us-west2",
    security_policy=default.name,
    description="new rule",
    priority=100,
    match={
        "versioned_expr": "SRC_IPS_V1",
        "config": {
            "src_ip_ranges": ["10.10.0.0/16"],
        },
    },
    action="allow",
    preview=True)
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 {
		_default, err := compute.NewRegionSecurityPolicy(ctx, "default", &compute.RegionSecurityPolicyArgs{
			Region:      pulumi.String("us-west2"),
			Name:        pulumi.String("policywithdefaultrule"),
			Description: pulumi.String("basic region security policy"),
			Type:        pulumi.String("CLOUD_ARMOR"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewRegionSecurityPolicyRule(ctx, "default_rule", &compute.RegionSecurityPolicyRuleArgs{
			Region:         pulumi.String("us-west2"),
			SecurityPolicy: _default.Name,
			Description:    pulumi.String("new rule"),
			Action:         pulumi.String("deny"),
			Priority:       pulumi.Int(2147483647),
			Match: &compute.RegionSecurityPolicyRuleMatchArgs{
				VersionedExpr: pulumi.String("SRC_IPS_V1"),
				Config: &compute.RegionSecurityPolicyRuleMatchConfigArgs{
					SrcIpRanges: pulumi.StringArray{
						pulumi.String("*"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = compute.NewRegionSecurityPolicyRule(ctx, "policy_rule", &compute.RegionSecurityPolicyRuleArgs{
			Region:         pulumi.String("us-west2"),
			SecurityPolicy: _default.Name,
			Description:    pulumi.String("new rule"),
			Priority:       pulumi.Int(100),
			Match: &compute.RegionSecurityPolicyRuleMatchArgs{
				VersionedExpr: pulumi.String("SRC_IPS_V1"),
				Config: &compute.RegionSecurityPolicyRuleMatchConfigArgs{
					SrcIpRanges: pulumi.StringArray{
						pulumi.String("10.10.0.0/16"),
					},
				},
			},
			Action:  pulumi.String("allow"),
			Preview: pulumi.Bool(true),
		})
		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 @default = new Gcp.Compute.RegionSecurityPolicy("default", new()
    {
        Region = "us-west2",
        Name = "policywithdefaultrule",
        Description = "basic region security policy",
        Type = "CLOUD_ARMOR",
    });

    var defaultRule = new Gcp.Compute.RegionSecurityPolicyRule("default_rule", new()
    {
        Region = "us-west2",
        SecurityPolicy = @default.Name,
        Description = "new rule",
        Action = "deny",
        Priority = 2147483647,
        Match = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleMatchArgs
        {
            VersionedExpr = "SRC_IPS_V1",
            Config = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleMatchConfigArgs
            {
                SrcIpRanges = new[]
                {
                    "*",
                },
            },
        },
    });

    var policyRule = new Gcp.Compute.RegionSecurityPolicyRule("policy_rule", new()
    {
        Region = "us-west2",
        SecurityPolicy = @default.Name,
        Description = "new rule",
        Priority = 100,
        Match = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleMatchArgs
        {
            VersionedExpr = "SRC_IPS_V1",
            Config = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleMatchConfigArgs
            {
                SrcIpRanges = new[]
                {
                    "10.10.0.0/16",
                },
            },
        },
        Action = "allow",
        Preview = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.RegionSecurityPolicy;
import com.pulumi.gcp.compute.RegionSecurityPolicyArgs;
import com.pulumi.gcp.compute.RegionSecurityPolicyRule;
import com.pulumi.gcp.compute.RegionSecurityPolicyRuleArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyRuleMatchArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyRuleMatchConfigArgs;
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 default_ = new RegionSecurityPolicy("default", RegionSecurityPolicyArgs.builder()
            .region("us-west2")
            .name("policywithdefaultrule")
            .description("basic region security policy")
            .type("CLOUD_ARMOR")
            .build());

        var defaultRule = new RegionSecurityPolicyRule("defaultRule", RegionSecurityPolicyRuleArgs.builder()
            .region("us-west2")
            .securityPolicy(default_.name())
            .description("new rule")
            .action("deny")
            .priority(2147483647)
            .match(RegionSecurityPolicyRuleMatchArgs.builder()
                .versionedExpr("SRC_IPS_V1")
                .config(RegionSecurityPolicyRuleMatchConfigArgs.builder()
                    .srcIpRanges("*")
                    .build())
                .build())
            .build());

        var policyRule = new RegionSecurityPolicyRule("policyRule", RegionSecurityPolicyRuleArgs.builder()
            .region("us-west2")
            .securityPolicy(default_.name())
            .description("new rule")
            .priority(100)
            .match(RegionSecurityPolicyRuleMatchArgs.builder()
                .versionedExpr("SRC_IPS_V1")
                .config(RegionSecurityPolicyRuleMatchConfigArgs.builder()
                    .srcIpRanges("10.10.0.0/16")
                    .build())
                .build())
            .action("allow")
            .preview(true)
            .build());

    }
}
resources:
  default:
    type: gcp:compute:RegionSecurityPolicy
    properties:
      region: us-west2
      name: policywithdefaultrule
      description: basic region security policy
      type: CLOUD_ARMOR
  defaultRule:
    type: gcp:compute:RegionSecurityPolicyRule
    name: default_rule
    properties:
      region: us-west2
      securityPolicy: ${default.name}
      description: new rule
      action: deny
      priority: '2147483647'
      match:
        versionedExpr: SRC_IPS_V1
        config:
          srcIpRanges:
            - '*'
  policyRule:
    type: gcp:compute:RegionSecurityPolicyRule
    name: policy_rule
    properties:
      region: us-west2
      securityPolicy: ${default.name}
      description: new rule
      priority: 100
      match:
        versionedExpr: SRC_IPS_V1
        config:
          srcIpRanges:
            - 10.10.0.0/16
      action: allow
      preview: true

The default rule uses priority 2147483647 (the lowest possible value) to catch everything not matched earlier. The srcIpRanges value “*” matches all traffic. Higher-priority rules (lower numbers like 100) are evaluated first, so allowed IPs pass through before reaching the default deny.

Exclude paths and parameters from WAF inspection

Web applications often have admin endpoints or form fields that trigger false positives in WAF rule sets.

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

const _default = new gcp.compute.RegionSecurityPolicy("default", {
    region: "asia-southeast1",
    name: "policyruletest",
    description: "basic region security policy",
    type: "CLOUD_ARMOR",
});
const policyRule = new gcp.compute.RegionSecurityPolicyRule("policy_rule", {
    region: "asia-southeast1",
    securityPolicy: _default.name,
    description: "new rule",
    priority: 100,
    match: {
        versionedExpr: "SRC_IPS_V1",
        config: {
            srcIpRanges: ["10.10.0.0/16"],
        },
    },
    preconfiguredWafConfig: {
        exclusions: [
            {
                requestUris: [{
                    operator: "STARTS_WITH",
                    value: "/admin",
                }],
                targetRuleSet: "rce-stable",
            },
            {
                requestQueryParams: [
                    {
                        operator: "CONTAINS",
                        value: "password",
                    },
                    {
                        operator: "STARTS_WITH",
                        value: "freeform",
                    },
                    {
                        operator: "EQUALS",
                        value: "description",
                    },
                ],
                targetRuleSet: "xss-stable",
                targetRuleIds: [
                    "owasp-crs-v030001-id941330-xss",
                    "owasp-crs-v030001-id941340-xss",
                ],
            },
        ],
    },
    action: "allow",
    preview: true,
});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.RegionSecurityPolicy("default",
    region="asia-southeast1",
    name="policyruletest",
    description="basic region security policy",
    type="CLOUD_ARMOR")
policy_rule = gcp.compute.RegionSecurityPolicyRule("policy_rule",
    region="asia-southeast1",
    security_policy=default.name,
    description="new rule",
    priority=100,
    match={
        "versioned_expr": "SRC_IPS_V1",
        "config": {
            "src_ip_ranges": ["10.10.0.0/16"],
        },
    },
    preconfigured_waf_config={
        "exclusions": [
            {
                "request_uris": [{
                    "operator": "STARTS_WITH",
                    "value": "/admin",
                }],
                "target_rule_set": "rce-stable",
            },
            {
                "request_query_params": [
                    {
                        "operator": "CONTAINS",
                        "value": "password",
                    },
                    {
                        "operator": "STARTS_WITH",
                        "value": "freeform",
                    },
                    {
                        "operator": "EQUALS",
                        "value": "description",
                    },
                ],
                "target_rule_set": "xss-stable",
                "target_rule_ids": [
                    "owasp-crs-v030001-id941330-xss",
                    "owasp-crs-v030001-id941340-xss",
                ],
            },
        ],
    },
    action="allow",
    preview=True)
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 {
		_default, err := compute.NewRegionSecurityPolicy(ctx, "default", &compute.RegionSecurityPolicyArgs{
			Region:      pulumi.String("asia-southeast1"),
			Name:        pulumi.String("policyruletest"),
			Description: pulumi.String("basic region security policy"),
			Type:        pulumi.String("CLOUD_ARMOR"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewRegionSecurityPolicyRule(ctx, "policy_rule", &compute.RegionSecurityPolicyRuleArgs{
			Region:         pulumi.String("asia-southeast1"),
			SecurityPolicy: _default.Name,
			Description:    pulumi.String("new rule"),
			Priority:       pulumi.Int(100),
			Match: &compute.RegionSecurityPolicyRuleMatchArgs{
				VersionedExpr: pulumi.String("SRC_IPS_V1"),
				Config: &compute.RegionSecurityPolicyRuleMatchConfigArgs{
					SrcIpRanges: pulumi.StringArray{
						pulumi.String("10.10.0.0/16"),
					},
				},
			},
			PreconfiguredWafConfig: &compute.RegionSecurityPolicyRulePreconfiguredWafConfigArgs{
				Exclusions: compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionArray{
					&compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionArgs{
						RequestUris: compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestUriArray{
							&compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestUriArgs{
								Operator: pulumi.String("STARTS_WITH"),
								Value:    pulumi.String("/admin"),
							},
						},
						TargetRuleSet: pulumi.String("rce-stable"),
					},
					&compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionArgs{
						RequestQueryParams: compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArray{
							&compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs{
								Operator: pulumi.String("CONTAINS"),
								Value:    pulumi.String("password"),
							},
							&compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs{
								Operator: pulumi.String("STARTS_WITH"),
								Value:    pulumi.String("freeform"),
							},
							&compute.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs{
								Operator: pulumi.String("EQUALS"),
								Value:    pulumi.String("description"),
							},
						},
						TargetRuleSet: pulumi.String("xss-stable"),
						TargetRuleIds: pulumi.StringArray{
							pulumi.String("owasp-crs-v030001-id941330-xss"),
							pulumi.String("owasp-crs-v030001-id941340-xss"),
						},
					},
				},
			},
			Action:  pulumi.String("allow"),
			Preview: pulumi.Bool(true),
		})
		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 @default = new Gcp.Compute.RegionSecurityPolicy("default", new()
    {
        Region = "asia-southeast1",
        Name = "policyruletest",
        Description = "basic region security policy",
        Type = "CLOUD_ARMOR",
    });

    var policyRule = new Gcp.Compute.RegionSecurityPolicyRule("policy_rule", new()
    {
        Region = "asia-southeast1",
        SecurityPolicy = @default.Name,
        Description = "new rule",
        Priority = 100,
        Match = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleMatchArgs
        {
            VersionedExpr = "SRC_IPS_V1",
            Config = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleMatchConfigArgs
            {
                SrcIpRanges = new[]
                {
                    "10.10.0.0/16",
                },
            },
        },
        PreconfiguredWafConfig = new Gcp.Compute.Inputs.RegionSecurityPolicyRulePreconfiguredWafConfigArgs
        {
            Exclusions = new[]
            {
                new Gcp.Compute.Inputs.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionArgs
                {
                    RequestUris = new[]
                    {
                        new Gcp.Compute.Inputs.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestUriArgs
                        {
                            Operator = "STARTS_WITH",
                            Value = "/admin",
                        },
                    },
                    TargetRuleSet = "rce-stable",
                },
                new Gcp.Compute.Inputs.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionArgs
                {
                    RequestQueryParams = new[]
                    {
                        new Gcp.Compute.Inputs.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs
                        {
                            Operator = "CONTAINS",
                            Value = "password",
                        },
                        new Gcp.Compute.Inputs.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs
                        {
                            Operator = "STARTS_WITH",
                            Value = "freeform",
                        },
                        new Gcp.Compute.Inputs.RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs
                        {
                            Operator = "EQUALS",
                            Value = "description",
                        },
                    },
                    TargetRuleSet = "xss-stable",
                    TargetRuleIds = new[]
                    {
                        "owasp-crs-v030001-id941330-xss",
                        "owasp-crs-v030001-id941340-xss",
                    },
                },
            },
        },
        Action = "allow",
        Preview = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.RegionSecurityPolicy;
import com.pulumi.gcp.compute.RegionSecurityPolicyArgs;
import com.pulumi.gcp.compute.RegionSecurityPolicyRule;
import com.pulumi.gcp.compute.RegionSecurityPolicyRuleArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyRuleMatchArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyRuleMatchConfigArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyRulePreconfiguredWafConfigArgs;
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 default_ = new RegionSecurityPolicy("default", RegionSecurityPolicyArgs.builder()
            .region("asia-southeast1")
            .name("policyruletest")
            .description("basic region security policy")
            .type("CLOUD_ARMOR")
            .build());

        var policyRule = new RegionSecurityPolicyRule("policyRule", RegionSecurityPolicyRuleArgs.builder()
            .region("asia-southeast1")
            .securityPolicy(default_.name())
            .description("new rule")
            .priority(100)
            .match(RegionSecurityPolicyRuleMatchArgs.builder()
                .versionedExpr("SRC_IPS_V1")
                .config(RegionSecurityPolicyRuleMatchConfigArgs.builder()
                    .srcIpRanges("10.10.0.0/16")
                    .build())
                .build())
            .preconfiguredWafConfig(RegionSecurityPolicyRulePreconfiguredWafConfigArgs.builder()
                .exclusions(                
                    RegionSecurityPolicyRulePreconfiguredWafConfigExclusionArgs.builder()
                        .requestUris(RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestUriArgs.builder()
                            .operator("STARTS_WITH")
                            .value("/admin")
                            .build())
                        .targetRuleSet("rce-stable")
                        .build(),
                    RegionSecurityPolicyRulePreconfiguredWafConfigExclusionArgs.builder()
                        .requestQueryParams(                        
                            RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs.builder()
                                .operator("CONTAINS")
                                .value("password")
                                .build(),
                            RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs.builder()
                                .operator("STARTS_WITH")
                                .value("freeform")
                                .build(),
                            RegionSecurityPolicyRulePreconfiguredWafConfigExclusionRequestQueryParamArgs.builder()
                                .operator("EQUALS")
                                .value("description")
                                .build())
                        .targetRuleSet("xss-stable")
                        .targetRuleIds(                        
                            "owasp-crs-v030001-id941330-xss",
                            "owasp-crs-v030001-id941340-xss")
                        .build())
                .build())
            .action("allow")
            .preview(true)
            .build());

    }
}
resources:
  default:
    type: gcp:compute:RegionSecurityPolicy
    properties:
      region: asia-southeast1
      name: policyruletest
      description: basic region security policy
      type: CLOUD_ARMOR
  policyRule:
    type: gcp:compute:RegionSecurityPolicyRule
    name: policy_rule
    properties:
      region: asia-southeast1
      securityPolicy: ${default.name}
      description: new rule
      priority: 100
      match:
        versionedExpr: SRC_IPS_V1
        config:
          srcIpRanges:
            - 10.10.0.0/16
      preconfiguredWafConfig:
        exclusions:
          - requestUris:
              - operator: STARTS_WITH
                value: /admin
            targetRuleSet: rce-stable
          - requestQueryParams:
              - operator: CONTAINS
                value: password
              - operator: STARTS_WITH
                value: freeform
              - operator: EQUALS
                value: description
            targetRuleSet: xss-stable
            targetRuleIds:
              - owasp-crs-v030001-id941330-xss
              - owasp-crs-v030001-id941340-xss
      action: allow
      preview: true

The preconfiguredWafConfig property defines exclusions that bypass specific WAF rules for certain request patterns. Each exclusion targets a rule set (like “rce-stable” or “xss-stable”) and specifies which request components to skip: URIs, query parameters, headers, or cookies. The operator field controls matching behavior (STARTS_WITH, CONTAINS, EQUALS). You can exclude entire rule sets or specific rule IDs within a set.

Match packets using custom header fields

Advanced DDoS protection scenarios require matching on packet-level details beyond source IPs, such as TCP flags or custom protocol fields.

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

// First activate advanced network DDoS protection for the desired region
const policyddosprotection = new gcp.compute.RegionSecurityPolicy("policyddosprotection", {
    region: "us-west2",
    name: "policyddosprotection",
    description: "policy for activating network DDoS protection for the desired region",
    type: "CLOUD_ARMOR_NETWORK",
    ddosProtectionConfig: {
        ddosProtection: "ADVANCED_PREVIEW",
    },
});
const edgeSecService = new gcp.compute.NetworkEdgeSecurityService("edge_sec_service", {
    region: "us-west2",
    name: "edgesecservice",
    description: "linking policy to edge security service",
    securityPolicy: policyddosprotection.selfLink,
});
// Add the desired policy and custom rule.
const policynetworkmatch = new gcp.compute.RegionSecurityPolicy("policynetworkmatch", {
    region: "us-west2",
    name: "policyfornetworkmatch",
    description: "region security policy for network match",
    type: "CLOUD_ARMOR_NETWORK",
    userDefinedFields: [{
        name: "SIG1_AT_0",
        base: "TCP",
        offset: 8,
        size: 2,
        mask: "0x8F00",
    }],
}, {
    dependsOn: [edgeSecService],
});
const policyRuleNetworkMatch = new gcp.compute.RegionSecurityPolicyRule("policy_rule_network_match", {
    region: "us-west2",
    securityPolicy: policynetworkmatch.name,
    description: "custom rule for network match",
    priority: 100,
    networkMatch: {
        srcIpRanges: ["10.10.0.0/16"],
        userDefinedFields: [{
            name: "SIG1_AT_0",
            values: ["0x8F00"],
        }],
    },
    action: "allow",
    preview: true,
});
import pulumi
import pulumi_gcp as gcp

# First activate advanced network DDoS protection for the desired region
policyddosprotection = gcp.compute.RegionSecurityPolicy("policyddosprotection",
    region="us-west2",
    name="policyddosprotection",
    description="policy for activating network DDoS protection for the desired region",
    type="CLOUD_ARMOR_NETWORK",
    ddos_protection_config={
        "ddos_protection": "ADVANCED_PREVIEW",
    })
edge_sec_service = gcp.compute.NetworkEdgeSecurityService("edge_sec_service",
    region="us-west2",
    name="edgesecservice",
    description="linking policy to edge security service",
    security_policy=policyddosprotection.self_link)
# Add the desired policy and custom rule.
policynetworkmatch = gcp.compute.RegionSecurityPolicy("policynetworkmatch",
    region="us-west2",
    name="policyfornetworkmatch",
    description="region security policy for network match",
    type="CLOUD_ARMOR_NETWORK",
    user_defined_fields=[{
        "name": "SIG1_AT_0",
        "base": "TCP",
        "offset": 8,
        "size": 2,
        "mask": "0x8F00",
    }],
    opts = pulumi.ResourceOptions(depends_on=[edge_sec_service]))
policy_rule_network_match = gcp.compute.RegionSecurityPolicyRule("policy_rule_network_match",
    region="us-west2",
    security_policy=policynetworkmatch.name,
    description="custom rule for network match",
    priority=100,
    network_match={
        "src_ip_ranges": ["10.10.0.0/16"],
        "user_defined_fields": [{
            "name": "SIG1_AT_0",
            "values": ["0x8F00"],
        }],
    },
    action="allow",
    preview=True)
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 {
		// First activate advanced network DDoS protection for the desired region
		policyddosprotection, err := compute.NewRegionSecurityPolicy(ctx, "policyddosprotection", &compute.RegionSecurityPolicyArgs{
			Region:      pulumi.String("us-west2"),
			Name:        pulumi.String("policyddosprotection"),
			Description: pulumi.String("policy for activating network DDoS protection for the desired region"),
			Type:        pulumi.String("CLOUD_ARMOR_NETWORK"),
			DdosProtectionConfig: &compute.RegionSecurityPolicyDdosProtectionConfigArgs{
				DdosProtection: pulumi.String("ADVANCED_PREVIEW"),
			},
		})
		if err != nil {
			return err
		}
		edgeSecService, err := compute.NewNetworkEdgeSecurityService(ctx, "edge_sec_service", &compute.NetworkEdgeSecurityServiceArgs{
			Region:         pulumi.String("us-west2"),
			Name:           pulumi.String("edgesecservice"),
			Description:    pulumi.String("linking policy to edge security service"),
			SecurityPolicy: policyddosprotection.SelfLink,
		})
		if err != nil {
			return err
		}
		// Add the desired policy and custom rule.
		policynetworkmatch, err := compute.NewRegionSecurityPolicy(ctx, "policynetworkmatch", &compute.RegionSecurityPolicyArgs{
			Region:      pulumi.String("us-west2"),
			Name:        pulumi.String("policyfornetworkmatch"),
			Description: pulumi.String("region security policy for network match"),
			Type:        pulumi.String("CLOUD_ARMOR_NETWORK"),
			UserDefinedFields: compute.RegionSecurityPolicyUserDefinedFieldArray{
				&compute.RegionSecurityPolicyUserDefinedFieldArgs{
					Name:   pulumi.String("SIG1_AT_0"),
					Base:   pulumi.String("TCP"),
					Offset: pulumi.Int(8),
					Size:   pulumi.Int(2),
					Mask:   pulumi.String("0x8F00"),
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			edgeSecService,
		}))
		if err != nil {
			return err
		}
		_, err = compute.NewRegionSecurityPolicyRule(ctx, "policy_rule_network_match", &compute.RegionSecurityPolicyRuleArgs{
			Region:         pulumi.String("us-west2"),
			SecurityPolicy: policynetworkmatch.Name,
			Description:    pulumi.String("custom rule for network match"),
			Priority:       pulumi.Int(100),
			NetworkMatch: &compute.RegionSecurityPolicyRuleNetworkMatchArgs{
				SrcIpRanges: pulumi.StringArray{
					pulumi.String("10.10.0.0/16"),
				},
				UserDefinedFields: compute.RegionSecurityPolicyRuleNetworkMatchUserDefinedFieldArray{
					&compute.RegionSecurityPolicyRuleNetworkMatchUserDefinedFieldArgs{
						Name: pulumi.String("SIG1_AT_0"),
						Values: pulumi.StringArray{
							pulumi.String("0x8F00"),
						},
					},
				},
			},
			Action:  pulumi.String("allow"),
			Preview: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    // First activate advanced network DDoS protection for the desired region
    var policyddosprotection = new Gcp.Compute.RegionSecurityPolicy("policyddosprotection", new()
    {
        Region = "us-west2",
        Name = "policyddosprotection",
        Description = "policy for activating network DDoS protection for the desired region",
        Type = "CLOUD_ARMOR_NETWORK",
        DdosProtectionConfig = new Gcp.Compute.Inputs.RegionSecurityPolicyDdosProtectionConfigArgs
        {
            DdosProtection = "ADVANCED_PREVIEW",
        },
    });

    var edgeSecService = new Gcp.Compute.NetworkEdgeSecurityService("edge_sec_service", new()
    {
        Region = "us-west2",
        Name = "edgesecservice",
        Description = "linking policy to edge security service",
        SecurityPolicy = policyddosprotection.SelfLink,
    });

    // Add the desired policy and custom rule.
    var policynetworkmatch = new Gcp.Compute.RegionSecurityPolicy("policynetworkmatch", new()
    {
        Region = "us-west2",
        Name = "policyfornetworkmatch",
        Description = "region security policy for network match",
        Type = "CLOUD_ARMOR_NETWORK",
        UserDefinedFields = new[]
        {
            new Gcp.Compute.Inputs.RegionSecurityPolicyUserDefinedFieldArgs
            {
                Name = "SIG1_AT_0",
                Base = "TCP",
                Offset = 8,
                Size = 2,
                Mask = "0x8F00",
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            edgeSecService,
        },
    });

    var policyRuleNetworkMatch = new Gcp.Compute.RegionSecurityPolicyRule("policy_rule_network_match", new()
    {
        Region = "us-west2",
        SecurityPolicy = policynetworkmatch.Name,
        Description = "custom rule for network match",
        Priority = 100,
        NetworkMatch = new Gcp.Compute.Inputs.RegionSecurityPolicyRuleNetworkMatchArgs
        {
            SrcIpRanges = new[]
            {
                "10.10.0.0/16",
            },
            UserDefinedFields = new[]
            {
                new Gcp.Compute.Inputs.RegionSecurityPolicyRuleNetworkMatchUserDefinedFieldArgs
                {
                    Name = "SIG1_AT_0",
                    Values = new[]
                    {
                        "0x8F00",
                    },
                },
            },
        },
        Action = "allow",
        Preview = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.RegionSecurityPolicy;
import com.pulumi.gcp.compute.RegionSecurityPolicyArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyDdosProtectionConfigArgs;
import com.pulumi.gcp.compute.NetworkEdgeSecurityService;
import com.pulumi.gcp.compute.NetworkEdgeSecurityServiceArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyUserDefinedFieldArgs;
import com.pulumi.gcp.compute.RegionSecurityPolicyRule;
import com.pulumi.gcp.compute.RegionSecurityPolicyRuleArgs;
import com.pulumi.gcp.compute.inputs.RegionSecurityPolicyRuleNetworkMatchArgs;
import com.pulumi.resources.CustomResourceOptions;
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) {
        // First activate advanced network DDoS protection for the desired region
        var policyddosprotection = new RegionSecurityPolicy("policyddosprotection", RegionSecurityPolicyArgs.builder()
            .region("us-west2")
            .name("policyddosprotection")
            .description("policy for activating network DDoS protection for the desired region")
            .type("CLOUD_ARMOR_NETWORK")
            .ddosProtectionConfig(RegionSecurityPolicyDdosProtectionConfigArgs.builder()
                .ddosProtection("ADVANCED_PREVIEW")
                .build())
            .build());

        var edgeSecService = new NetworkEdgeSecurityService("edgeSecService", NetworkEdgeSecurityServiceArgs.builder()
            .region("us-west2")
            .name("edgesecservice")
            .description("linking policy to edge security service")
            .securityPolicy(policyddosprotection.selfLink())
            .build());

        // Add the desired policy and custom rule.
        var policynetworkmatch = new RegionSecurityPolicy("policynetworkmatch", RegionSecurityPolicyArgs.builder()
            .region("us-west2")
            .name("policyfornetworkmatch")
            .description("region security policy for network match")
            .type("CLOUD_ARMOR_NETWORK")
            .userDefinedFields(RegionSecurityPolicyUserDefinedFieldArgs.builder()
                .name("SIG1_AT_0")
                .base("TCP")
                .offset(8)
                .size(2)
                .mask("0x8F00")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(edgeSecService)
                .build());

        var policyRuleNetworkMatch = new RegionSecurityPolicyRule("policyRuleNetworkMatch", RegionSecurityPolicyRuleArgs.builder()
            .region("us-west2")
            .securityPolicy(policynetworkmatch.name())
            .description("custom rule for network match")
            .priority(100)
            .networkMatch(RegionSecurityPolicyRuleNetworkMatchArgs.builder()
                .srcIpRanges("10.10.0.0/16")
                .userDefinedFields(RegionSecurityPolicyRuleNetworkMatchUserDefinedFieldArgs.builder()
                    .name("SIG1_AT_0")
                    .values("0x8F00")
                    .build())
                .build())
            .action("allow")
            .preview(true)
            .build());

    }
}
resources:
  # First activate advanced network DDoS protection for the desired region
  policyddosprotection:
    type: gcp:compute:RegionSecurityPolicy
    properties:
      region: us-west2
      name: policyddosprotection
      description: policy for activating network DDoS protection for the desired region
      type: CLOUD_ARMOR_NETWORK
      ddosProtectionConfig:
        ddosProtection: ADVANCED_PREVIEW
  edgeSecService:
    type: gcp:compute:NetworkEdgeSecurityService
    name: edge_sec_service
    properties:
      region: us-west2
      name: edgesecservice
      description: linking policy to edge security service
      securityPolicy: ${policyddosprotection.selfLink}
  # Add the desired policy and custom rule.
  policynetworkmatch:
    type: gcp:compute:RegionSecurityPolicy
    properties:
      region: us-west2
      name: policyfornetworkmatch
      description: region security policy for network match
      type: CLOUD_ARMOR_NETWORK
      userDefinedFields:
        - name: SIG1_AT_0
          base: TCP
          offset: 8
          size: 2
          mask: 0x8F00
    options:
      dependsOn:
        - ${edgeSecService}
  policyRuleNetworkMatch:
    type: gcp:compute:RegionSecurityPolicyRule
    name: policy_rule_network_match
    properties:
      region: us-west2
      securityPolicy: ${policynetworkmatch.name}
      description: custom rule for network match
      priority: 100
      networkMatch:
        srcIpRanges:
          - 10.10.0.0/16
        userDefinedFields:
          - name: SIG1_AT_0
            values:
              - 0x8F00
      action: allow
      preview: true

Network match rules operate at the packet level for CLOUD_ARMOR_NETWORK policies. The networkMatch property replaces the standard match property and supports userDefinedFields that extract values from packet headers. The security policy must define these fields (name, base protocol, offset, size, mask) before rules can reference them. This example matches packets from specific IP ranges with a custom TCP header field value.

Beyond these examples

These snippets focus on specific rule-level features: IP-based access control and default-deny patterns, WAF exclusions for false positive handling, and packet-level matching with custom header fields. They’re intentionally minimal rather than full security configurations.

The examples reference pre-existing infrastructure such as RegionSecurityPolicy resources, NetworkEdgeSecurityService (for network match rules), and advanced DDoS protection activation (for CLOUD_ARMOR_NETWORK). They focus on configuring individual rules rather than provisioning the entire security stack.

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

  • Rate limiting and ban actions (rateLimitOptions)
  • Geographic restrictions (srcRegionCodes)
  • Expression-based matching beyond IP ranges
  • Redirect actions and reCAPTCHA integration

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

Let's configure GCP Region Security 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 & Priorities
What properties can't be changed after creating a rule?
The properties priority, project, region, and securityPolicy are immutable. Changing any of these requires recreating the rule.
How does rule priority work?
Priority ranges from 0 to 2147483647, where 0 is the highest priority and 2147483647 is the lowest. Rules are evaluated from highest to lowest priority, so lower numbers are processed first.
How do I create a default deny-all rule?
Set priority to 2147483647 (lowest priority), action to “deny”, and srcIpRanges to ["*"] in your match configuration. This catches all traffic not matched by higher-priority rules.
How do I add multiple rules to the same security policy?
Create separate RegionSecurityPolicyRule resources with different priorities, all referencing the same securityPolicy name. Each rule needs a unique priority value.
Actions & Rate Limiting
What actions can I configure for a security policy rule?
You can use: allow (permit traffic), deny(STATUS) (block with HTTP status 403/404/502), rate_based_ban (rate limit and ban), redirect (reCAPTCHA or external URL), or throttle (rate limit only).
When do I need to configure rateLimitOptions?
You must specify rateLimitOptions when using rate_based_ban or throttle actions. You cannot use rateLimitOptions with any other action types.
What's the difference between preview mode and the allow action?
Setting preview: true tests the rule without enforcing any action, while action: "allow" actively permits matching traffic when the rule is enforced.
Match Conditions & Filtering
What's the difference between match and networkMatch?
Use match for standard CLOUD_ARMOR policies with IP-based filtering. Use networkMatch for CLOUD_ARMOR_NETWORK policies that support user-defined packet fields and advanced network filtering.
How do I match traffic from specific IP ranges?
Configure the match block with versionedExpr: "SRC_IPS_V1" and specify IP ranges in config.srcIpRanges, such as [“10.10.0.0/16”].
Can I configure WAF exclusions for specific request paths?
Yes, use preconfiguredWafConfig.exclusions to specify request URIs, query parameters, or headers that should bypass WAF rules. You can target specific rule sets and rule IDs.

Using a different cloud?

Explore security guides for other cloud providers: