Configure GCP Network Security Profiles

The gcp:networksecurity/securityProfile:SecurityProfile resource, part of the Pulumi GCP provider, defines security profiles that control threat prevention, URL filtering, traffic mirroring, or interception behavior at the organization level. This guide focuses on three capabilities: threat prevention with custom overrides, URL filtering rules, and traffic mirroring and interception.

Security profiles belong to organizations and reference VPC networks, deployment groups, and endpoint groups that must exist separately. The examples are intentionally small. Combine them with your own firewall policies and network infrastructure.

Create a threat prevention profile with labels

Organizations deploying Cloud Firewall start by creating security profiles that define threat prevention behavior at the organization level.

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

const _default = new gcp.networksecurity.SecurityProfile("default", {
    name: "my-security-profile",
    parent: "organizations/123456789",
    description: "my description",
    type: "THREAT_PREVENTION",
    labels: {
        foo: "bar",
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.networksecurity.SecurityProfile("default",
    name="my-security-profile",
    parent="organizations/123456789",
    description="my description",
    type="THREAT_PREVENTION",
    labels={
        "foo": "bar",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networksecurity.NewSecurityProfile(ctx, "default", &networksecurity.SecurityProfileArgs{
			Name:        pulumi.String("my-security-profile"),
			Parent:      pulumi.String("organizations/123456789"),
			Description: pulumi.String("my description"),
			Type:        pulumi.String("THREAT_PREVENTION"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
		})
		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.NetworkSecurity.SecurityProfile("default", new()
    {
        Name = "my-security-profile",
        Parent = "organizations/123456789",
        Description = "my description",
        Type = "THREAT_PREVENTION",
        Labels = 
        {
            { "foo", "bar" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networksecurity.SecurityProfile;
import com.pulumi.gcp.networksecurity.SecurityProfileArgs;
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 SecurityProfile("default", SecurityProfileArgs.builder()
            .name("my-security-profile")
            .parent("organizations/123456789")
            .description("my description")
            .type("THREAT_PREVENTION")
            .labels(Map.of("foo", "bar"))
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:SecurityProfile
    properties:
      name: my-security-profile
      parent: organizations/123456789
      description: my description
      type: THREAT_PREVENTION
      labels:
        foo: bar

The type property determines the profile’s behavior; THREAT_PREVENTION enables Google’s threat intelligence. The parent property scopes the profile to an organization. Labels help organize profiles across teams and environments.

Override threat severity and antivirus actions

Security teams often need to tune threat prevention by adjusting actions for specific severity levels, threat IDs, or protocols.

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

const _default = new gcp.networksecurity.SecurityProfile("default", {
    name: "my-security-profile",
    parent: "organizations/123456789",
    description: "my description",
    type: "THREAT_PREVENTION",
    threatPreventionProfile: {
        severityOverrides: [
            {
                action: "ALLOW",
                severity: "INFORMATIONAL",
            },
            {
                action: "DENY",
                severity: "HIGH",
            },
        ],
        threatOverrides: [{
            action: "ALLOW",
            threatId: "280647",
        }],
        antivirusOverrides: [{
            protocol: "SMTP",
            action: "ALLOW",
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.networksecurity.SecurityProfile("default",
    name="my-security-profile",
    parent="organizations/123456789",
    description="my description",
    type="THREAT_PREVENTION",
    threat_prevention_profile={
        "severity_overrides": [
            {
                "action": "ALLOW",
                "severity": "INFORMATIONAL",
            },
            {
                "action": "DENY",
                "severity": "HIGH",
            },
        ],
        "threat_overrides": [{
            "action": "ALLOW",
            "threat_id": "280647",
        }],
        "antivirus_overrides": [{
            "protocol": "SMTP",
            "action": "ALLOW",
        }],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networksecurity.NewSecurityProfile(ctx, "default", &networksecurity.SecurityProfileArgs{
			Name:        pulumi.String("my-security-profile"),
			Parent:      pulumi.String("organizations/123456789"),
			Description: pulumi.String("my description"),
			Type:        pulumi.String("THREAT_PREVENTION"),
			ThreatPreventionProfile: &networksecurity.SecurityProfileThreatPreventionProfileArgs{
				SeverityOverrides: networksecurity.SecurityProfileThreatPreventionProfileSeverityOverrideArray{
					&networksecurity.SecurityProfileThreatPreventionProfileSeverityOverrideArgs{
						Action:   pulumi.String("ALLOW"),
						Severity: pulumi.String("INFORMATIONAL"),
					},
					&networksecurity.SecurityProfileThreatPreventionProfileSeverityOverrideArgs{
						Action:   pulumi.String("DENY"),
						Severity: pulumi.String("HIGH"),
					},
				},
				ThreatOverrides: networksecurity.SecurityProfileThreatPreventionProfileThreatOverrideArray{
					&networksecurity.SecurityProfileThreatPreventionProfileThreatOverrideArgs{
						Action:   pulumi.String("ALLOW"),
						ThreatId: pulumi.String("280647"),
					},
				},
				AntivirusOverrides: networksecurity.SecurityProfileThreatPreventionProfileAntivirusOverrideArray{
					&networksecurity.SecurityProfileThreatPreventionProfileAntivirusOverrideArgs{
						Protocol: pulumi.String("SMTP"),
						Action:   pulumi.String("ALLOW"),
					},
				},
			},
		})
		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.NetworkSecurity.SecurityProfile("default", new()
    {
        Name = "my-security-profile",
        Parent = "organizations/123456789",
        Description = "my description",
        Type = "THREAT_PREVENTION",
        ThreatPreventionProfile = new Gcp.NetworkSecurity.Inputs.SecurityProfileThreatPreventionProfileArgs
        {
            SeverityOverrides = new[]
            {
                new Gcp.NetworkSecurity.Inputs.SecurityProfileThreatPreventionProfileSeverityOverrideArgs
                {
                    Action = "ALLOW",
                    Severity = "INFORMATIONAL",
                },
                new Gcp.NetworkSecurity.Inputs.SecurityProfileThreatPreventionProfileSeverityOverrideArgs
                {
                    Action = "DENY",
                    Severity = "HIGH",
                },
            },
            ThreatOverrides = new[]
            {
                new Gcp.NetworkSecurity.Inputs.SecurityProfileThreatPreventionProfileThreatOverrideArgs
                {
                    Action = "ALLOW",
                    ThreatId = "280647",
                },
            },
            AntivirusOverrides = new[]
            {
                new Gcp.NetworkSecurity.Inputs.SecurityProfileThreatPreventionProfileAntivirusOverrideArgs
                {
                    Protocol = "SMTP",
                    Action = "ALLOW",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networksecurity.SecurityProfile;
import com.pulumi.gcp.networksecurity.SecurityProfileArgs;
import com.pulumi.gcp.networksecurity.inputs.SecurityProfileThreatPreventionProfileArgs;
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 SecurityProfile("default", SecurityProfileArgs.builder()
            .name("my-security-profile")
            .parent("organizations/123456789")
            .description("my description")
            .type("THREAT_PREVENTION")
            .threatPreventionProfile(SecurityProfileThreatPreventionProfileArgs.builder()
                .severityOverrides(                
                    SecurityProfileThreatPreventionProfileSeverityOverrideArgs.builder()
                        .action("ALLOW")
                        .severity("INFORMATIONAL")
                        .build(),
                    SecurityProfileThreatPreventionProfileSeverityOverrideArgs.builder()
                        .action("DENY")
                        .severity("HIGH")
                        .build())
                .threatOverrides(SecurityProfileThreatPreventionProfileThreatOverrideArgs.builder()
                    .action("ALLOW")
                    .threatId("280647")
                    .build())
                .antivirusOverrides(SecurityProfileThreatPreventionProfileAntivirusOverrideArgs.builder()
                    .protocol("SMTP")
                    .action("ALLOW")
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:SecurityProfile
    properties:
      name: my-security-profile
      parent: organizations/123456789
      description: my description
      type: THREAT_PREVENTION
      threatPreventionProfile:
        severityOverrides:
          - action: ALLOW
            severity: INFORMATIONAL
          - action: DENY
            severity: HIGH
        threatOverrides:
          - action: ALLOW
            threatId: '280647'
        antivirusOverrides:
          - protocol: SMTP
            action: ALLOW

The threatPreventionProfile block contains three override types. The severityOverrides array lets you set actions (ALLOW or DENY) for each severity level. The threatOverrides array targets specific threat IDs by number. The antivirusOverrides array controls actions by protocol (SMTP, HTTP, etc.). Overrides take precedence over default threat prevention behavior.

Filter traffic by URL patterns

Organizations controlling web access use URL filtering to allow or deny traffic based on domain patterns.

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

const _default = new gcp.networksecurity.SecurityProfile("default", {
    name: "my-security-profile",
    parent: "organizations/123456789",
    description: "my description",
    type: "URL_FILTERING",
    urlFilteringProfile: {
        urlFilters: [
            {
                priority: 1,
                filteringAction: "ALLOW",
                urls: [
                    "*example.com",
                    "*about.example.com",
                    "*help.example.com",
                ],
            },
            {
                priority: 2,
                filteringAction: "DENY",
                urls: ["*restricted.example.com"],
            },
        ],
    },
    labels: {
        foo: "bar",
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.networksecurity.SecurityProfile("default",
    name="my-security-profile",
    parent="organizations/123456789",
    description="my description",
    type="URL_FILTERING",
    url_filtering_profile={
        "url_filters": [
            {
                "priority": 1,
                "filtering_action": "ALLOW",
                "urls": [
                    "*example.com",
                    "*about.example.com",
                    "*help.example.com",
                ],
            },
            {
                "priority": 2,
                "filtering_action": "DENY",
                "urls": ["*restricted.example.com"],
            },
        ],
    },
    labels={
        "foo": "bar",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networksecurity.NewSecurityProfile(ctx, "default", &networksecurity.SecurityProfileArgs{
			Name:        pulumi.String("my-security-profile"),
			Parent:      pulumi.String("organizations/123456789"),
			Description: pulumi.String("my description"),
			Type:        pulumi.String("URL_FILTERING"),
			UrlFilteringProfile: &networksecurity.SecurityProfileUrlFilteringProfileArgs{
				UrlFilters: networksecurity.SecurityProfileUrlFilteringProfileUrlFilterArray{
					&networksecurity.SecurityProfileUrlFilteringProfileUrlFilterArgs{
						Priority:        pulumi.Int(1),
						FilteringAction: pulumi.String("ALLOW"),
						Urls: pulumi.StringArray{
							pulumi.String("*example.com"),
							pulumi.String("*about.example.com"),
							pulumi.String("*help.example.com"),
						},
					},
					&networksecurity.SecurityProfileUrlFilteringProfileUrlFilterArgs{
						Priority:        pulumi.Int(2),
						FilteringAction: pulumi.String("DENY"),
						Urls: pulumi.StringArray{
							pulumi.String("*restricted.example.com"),
						},
					},
				},
			},
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
		})
		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.NetworkSecurity.SecurityProfile("default", new()
    {
        Name = "my-security-profile",
        Parent = "organizations/123456789",
        Description = "my description",
        Type = "URL_FILTERING",
        UrlFilteringProfile = new Gcp.NetworkSecurity.Inputs.SecurityProfileUrlFilteringProfileArgs
        {
            UrlFilters = new[]
            {
                new Gcp.NetworkSecurity.Inputs.SecurityProfileUrlFilteringProfileUrlFilterArgs
                {
                    Priority = 1,
                    FilteringAction = "ALLOW",
                    Urls = new[]
                    {
                        "*example.com",
                        "*about.example.com",
                        "*help.example.com",
                    },
                },
                new Gcp.NetworkSecurity.Inputs.SecurityProfileUrlFilteringProfileUrlFilterArgs
                {
                    Priority = 2,
                    FilteringAction = "DENY",
                    Urls = new[]
                    {
                        "*restricted.example.com",
                    },
                },
            },
        },
        Labels = 
        {
            { "foo", "bar" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networksecurity.SecurityProfile;
import com.pulumi.gcp.networksecurity.SecurityProfileArgs;
import com.pulumi.gcp.networksecurity.inputs.SecurityProfileUrlFilteringProfileArgs;
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 SecurityProfile("default", SecurityProfileArgs.builder()
            .name("my-security-profile")
            .parent("organizations/123456789")
            .description("my description")
            .type("URL_FILTERING")
            .urlFilteringProfile(SecurityProfileUrlFilteringProfileArgs.builder()
                .urlFilters(                
                    SecurityProfileUrlFilteringProfileUrlFilterArgs.builder()
                        .priority(1)
                        .filteringAction("ALLOW")
                        .urls(                        
                            "*example.com",
                            "*about.example.com",
                            "*help.example.com")
                        .build(),
                    SecurityProfileUrlFilteringProfileUrlFilterArgs.builder()
                        .priority(2)
                        .filteringAction("DENY")
                        .urls("*restricted.example.com")
                        .build())
                .build())
            .labels(Map.of("foo", "bar"))
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:SecurityProfile
    properties:
      name: my-security-profile
      parent: organizations/123456789
      description: my description
      type: URL_FILTERING
      urlFilteringProfile:
        urlFilters:
          - priority: 1
            filteringAction: ALLOW
            urls:
              - '*example.com'
              - '*about.example.com'
              - '*help.example.com'
          - priority: 2
            filteringAction: DENY
            urls:
              - '*restricted.example.com'
      labels:
        foo: bar

The urlFilteringProfile block contains a urlFilters array where each entry has a priority, filteringAction, and urls list. Lower priority numbers evaluate first. Wildcard patterns like “*example.com” match subdomains. This example allows most example.com traffic but blocks restricted.example.com.

Mirror traffic to third-party collectors

Security operations teams often need to send copies of network traffic to external analysis tools or SIEM platforms.

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

const _default = new gcp.compute.Network("default", {
    name: "my-network",
    autoCreateSubnetworks: false,
});
const defaultMirroringDeploymentGroup = new gcp.networksecurity.MirroringDeploymentGroup("default", {
    mirroringDeploymentGroupId: "my-dg",
    location: "global",
    network: _default.id,
});
const defaultMirroringEndpointGroup = new gcp.networksecurity.MirroringEndpointGroup("default", {
    mirroringEndpointGroupId: "my-eg",
    location: "global",
    mirroringDeploymentGroup: defaultMirroringDeploymentGroup.id,
});
const defaultSecurityProfile = new gcp.networksecurity.SecurityProfile("default", {
    name: "my-security-profile",
    parent: "organizations/123456789",
    description: "my description",
    type: "CUSTOM_MIRRORING",
    customMirroringProfile: {
        mirroringEndpointGroup: defaultMirroringEndpointGroup.id,
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.Network("default",
    name="my-network",
    auto_create_subnetworks=False)
default_mirroring_deployment_group = gcp.networksecurity.MirroringDeploymentGroup("default",
    mirroring_deployment_group_id="my-dg",
    location="global",
    network=default.id)
default_mirroring_endpoint_group = gcp.networksecurity.MirroringEndpointGroup("default",
    mirroring_endpoint_group_id="my-eg",
    location="global",
    mirroring_deployment_group=default_mirroring_deployment_group.id)
default_security_profile = gcp.networksecurity.SecurityProfile("default",
    name="my-security-profile",
    parent="organizations/123456789",
    description="my description",
    type="CUSTOM_MIRRORING",
    custom_mirroring_profile={
        "mirroring_endpoint_group": default_mirroring_endpoint_group.id,
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
			Name:                  pulumi.String("my-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		defaultMirroringDeploymentGroup, err := networksecurity.NewMirroringDeploymentGroup(ctx, "default", &networksecurity.MirroringDeploymentGroupArgs{
			MirroringDeploymentGroupId: pulumi.String("my-dg"),
			Location:                   pulumi.String("global"),
			Network:                    _default.ID(),
		})
		if err != nil {
			return err
		}
		defaultMirroringEndpointGroup, err := networksecurity.NewMirroringEndpointGroup(ctx, "default", &networksecurity.MirroringEndpointGroupArgs{
			MirroringEndpointGroupId: pulumi.String("my-eg"),
			Location:                 pulumi.String("global"),
			MirroringDeploymentGroup: defaultMirroringDeploymentGroup.ID(),
		})
		if err != nil {
			return err
		}
		_, err = networksecurity.NewSecurityProfile(ctx, "default", &networksecurity.SecurityProfileArgs{
			Name:        pulumi.String("my-security-profile"),
			Parent:      pulumi.String("organizations/123456789"),
			Description: pulumi.String("my description"),
			Type:        pulumi.String("CUSTOM_MIRRORING"),
			CustomMirroringProfile: &networksecurity.SecurityProfileCustomMirroringProfileArgs{
				MirroringEndpointGroup: defaultMirroringEndpointGroup.ID(),
			},
		})
		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.Network("default", new()
    {
        Name = "my-network",
        AutoCreateSubnetworks = false,
    });

    var defaultMirroringDeploymentGroup = new Gcp.NetworkSecurity.MirroringDeploymentGroup("default", new()
    {
        MirroringDeploymentGroupId = "my-dg",
        Location = "global",
        Network = @default.Id,
    });

    var defaultMirroringEndpointGroup = new Gcp.NetworkSecurity.MirroringEndpointGroup("default", new()
    {
        MirroringEndpointGroupId = "my-eg",
        Location = "global",
        MirroringDeploymentGroup = defaultMirroringDeploymentGroup.Id,
    });

    var defaultSecurityProfile = new Gcp.NetworkSecurity.SecurityProfile("default", new()
    {
        Name = "my-security-profile",
        Parent = "organizations/123456789",
        Description = "my description",
        Type = "CUSTOM_MIRRORING",
        CustomMirroringProfile = new Gcp.NetworkSecurity.Inputs.SecurityProfileCustomMirroringProfileArgs
        {
            MirroringEndpointGroup = defaultMirroringEndpointGroup.Id,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.networksecurity.MirroringDeploymentGroup;
import com.pulumi.gcp.networksecurity.MirroringDeploymentGroupArgs;
import com.pulumi.gcp.networksecurity.MirroringEndpointGroup;
import com.pulumi.gcp.networksecurity.MirroringEndpointGroupArgs;
import com.pulumi.gcp.networksecurity.SecurityProfile;
import com.pulumi.gcp.networksecurity.SecurityProfileArgs;
import com.pulumi.gcp.networksecurity.inputs.SecurityProfileCustomMirroringProfileArgs;
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 Network("default", NetworkArgs.builder()
            .name("my-network")
            .autoCreateSubnetworks(false)
            .build());

        var defaultMirroringDeploymentGroup = new MirroringDeploymentGroup("defaultMirroringDeploymentGroup", MirroringDeploymentGroupArgs.builder()
            .mirroringDeploymentGroupId("my-dg")
            .location("global")
            .network(default_.id())
            .build());

        var defaultMirroringEndpointGroup = new MirroringEndpointGroup("defaultMirroringEndpointGroup", MirroringEndpointGroupArgs.builder()
            .mirroringEndpointGroupId("my-eg")
            .location("global")
            .mirroringDeploymentGroup(defaultMirroringDeploymentGroup.id())
            .build());

        var defaultSecurityProfile = new SecurityProfile("defaultSecurityProfile", SecurityProfileArgs.builder()
            .name("my-security-profile")
            .parent("organizations/123456789")
            .description("my description")
            .type("CUSTOM_MIRRORING")
            .customMirroringProfile(SecurityProfileCustomMirroringProfileArgs.builder()
                .mirroringEndpointGroup(defaultMirroringEndpointGroup.id())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:compute:Network
    properties:
      name: my-network
      autoCreateSubnetworks: false
  defaultMirroringDeploymentGroup:
    type: gcp:networksecurity:MirroringDeploymentGroup
    name: default
    properties:
      mirroringDeploymentGroupId: my-dg
      location: global
      network: ${default.id}
  defaultMirroringEndpointGroup:
    type: gcp:networksecurity:MirroringEndpointGroup
    name: default
    properties:
      mirroringEndpointGroupId: my-eg
      location: global
      mirroringDeploymentGroup: ${defaultMirroringDeploymentGroup.id}
  defaultSecurityProfile:
    type: gcp:networksecurity:SecurityProfile
    name: default
    properties:
      name: my-security-profile
      parent: organizations/123456789
      description: my description
      type: CUSTOM_MIRRORING
      customMirroringProfile:
        mirroringEndpointGroup: ${defaultMirroringEndpointGroup.id}

The customMirroringProfile block references a mirroringEndpointGroup that defines where traffic copies are sent. You must create the MirroringDeploymentGroup and MirroringEndpointGroup resources first, then reference the endpoint group ID in the profile. The deployment group associates with a VPC network; the endpoint group defines the actual collection endpoints.

Intercept traffic for third-party firewalls

Organizations using third-party firewall appliances need to redirect traffic through those devices for inspection.

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

const _default = new gcp.compute.Network("default", {
    name: "my-network",
    autoCreateSubnetworks: false,
});
const defaultInterceptDeploymentGroup = new gcp.networksecurity.InterceptDeploymentGroup("default", {
    interceptDeploymentGroupId: "my-dg",
    location: "global",
    network: _default.id,
});
const defaultInterceptEndpointGroup = new gcp.networksecurity.InterceptEndpointGroup("default", {
    interceptEndpointGroupId: "my-eg",
    location: "global",
    interceptDeploymentGroup: defaultInterceptDeploymentGroup.id,
});
const defaultSecurityProfile = new gcp.networksecurity.SecurityProfile("default", {
    name: "my-security-profile",
    parent: "organizations/123456789",
    description: "my description",
    type: "CUSTOM_INTERCEPT",
    customInterceptProfile: {
        interceptEndpointGroup: defaultInterceptEndpointGroup.id,
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.Network("default",
    name="my-network",
    auto_create_subnetworks=False)
default_intercept_deployment_group = gcp.networksecurity.InterceptDeploymentGroup("default",
    intercept_deployment_group_id="my-dg",
    location="global",
    network=default.id)
default_intercept_endpoint_group = gcp.networksecurity.InterceptEndpointGroup("default",
    intercept_endpoint_group_id="my-eg",
    location="global",
    intercept_deployment_group=default_intercept_deployment_group.id)
default_security_profile = gcp.networksecurity.SecurityProfile("default",
    name="my-security-profile",
    parent="organizations/123456789",
    description="my description",
    type="CUSTOM_INTERCEPT",
    custom_intercept_profile={
        "intercept_endpoint_group": default_intercept_endpoint_group.id,
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
			Name:                  pulumi.String("my-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		defaultInterceptDeploymentGroup, err := networksecurity.NewInterceptDeploymentGroup(ctx, "default", &networksecurity.InterceptDeploymentGroupArgs{
			InterceptDeploymentGroupId: pulumi.String("my-dg"),
			Location:                   pulumi.String("global"),
			Network:                    _default.ID(),
		})
		if err != nil {
			return err
		}
		defaultInterceptEndpointGroup, err := networksecurity.NewInterceptEndpointGroup(ctx, "default", &networksecurity.InterceptEndpointGroupArgs{
			InterceptEndpointGroupId: pulumi.String("my-eg"),
			Location:                 pulumi.String("global"),
			InterceptDeploymentGroup: defaultInterceptDeploymentGroup.ID(),
		})
		if err != nil {
			return err
		}
		_, err = networksecurity.NewSecurityProfile(ctx, "default", &networksecurity.SecurityProfileArgs{
			Name:        pulumi.String("my-security-profile"),
			Parent:      pulumi.String("organizations/123456789"),
			Description: pulumi.String("my description"),
			Type:        pulumi.String("CUSTOM_INTERCEPT"),
			CustomInterceptProfile: &networksecurity.SecurityProfileCustomInterceptProfileArgs{
				InterceptEndpointGroup: defaultInterceptEndpointGroup.ID(),
			},
		})
		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.Network("default", new()
    {
        Name = "my-network",
        AutoCreateSubnetworks = false,
    });

    var defaultInterceptDeploymentGroup = new Gcp.NetworkSecurity.InterceptDeploymentGroup("default", new()
    {
        InterceptDeploymentGroupId = "my-dg",
        Location = "global",
        Network = @default.Id,
    });

    var defaultInterceptEndpointGroup = new Gcp.NetworkSecurity.InterceptEndpointGroup("default", new()
    {
        InterceptEndpointGroupId = "my-eg",
        Location = "global",
        InterceptDeploymentGroup = defaultInterceptDeploymentGroup.Id,
    });

    var defaultSecurityProfile = new Gcp.NetworkSecurity.SecurityProfile("default", new()
    {
        Name = "my-security-profile",
        Parent = "organizations/123456789",
        Description = "my description",
        Type = "CUSTOM_INTERCEPT",
        CustomInterceptProfile = new Gcp.NetworkSecurity.Inputs.SecurityProfileCustomInterceptProfileArgs
        {
            InterceptEndpointGroup = defaultInterceptEndpointGroup.Id,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.networksecurity.InterceptDeploymentGroup;
import com.pulumi.gcp.networksecurity.InterceptDeploymentGroupArgs;
import com.pulumi.gcp.networksecurity.InterceptEndpointGroup;
import com.pulumi.gcp.networksecurity.InterceptEndpointGroupArgs;
import com.pulumi.gcp.networksecurity.SecurityProfile;
import com.pulumi.gcp.networksecurity.SecurityProfileArgs;
import com.pulumi.gcp.networksecurity.inputs.SecurityProfileCustomInterceptProfileArgs;
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 Network("default", NetworkArgs.builder()
            .name("my-network")
            .autoCreateSubnetworks(false)
            .build());

        var defaultInterceptDeploymentGroup = new InterceptDeploymentGroup("defaultInterceptDeploymentGroup", InterceptDeploymentGroupArgs.builder()
            .interceptDeploymentGroupId("my-dg")
            .location("global")
            .network(default_.id())
            .build());

        var defaultInterceptEndpointGroup = new InterceptEndpointGroup("defaultInterceptEndpointGroup", InterceptEndpointGroupArgs.builder()
            .interceptEndpointGroupId("my-eg")
            .location("global")
            .interceptDeploymentGroup(defaultInterceptDeploymentGroup.id())
            .build());

        var defaultSecurityProfile = new SecurityProfile("defaultSecurityProfile", SecurityProfileArgs.builder()
            .name("my-security-profile")
            .parent("organizations/123456789")
            .description("my description")
            .type("CUSTOM_INTERCEPT")
            .customInterceptProfile(SecurityProfileCustomInterceptProfileArgs.builder()
                .interceptEndpointGroup(defaultInterceptEndpointGroup.id())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:compute:Network
    properties:
      name: my-network
      autoCreateSubnetworks: false
  defaultInterceptDeploymentGroup:
    type: gcp:networksecurity:InterceptDeploymentGroup
    name: default
    properties:
      interceptDeploymentGroupId: my-dg
      location: global
      network: ${default.id}
  defaultInterceptEndpointGroup:
    type: gcp:networksecurity:InterceptEndpointGroup
    name: default
    properties:
      interceptEndpointGroupId: my-eg
      location: global
      interceptDeploymentGroup: ${defaultInterceptDeploymentGroup.id}
  defaultSecurityProfile:
    type: gcp:networksecurity:SecurityProfile
    name: default
    properties:
      name: my-security-profile
      parent: organizations/123456789
      description: my description
      type: CUSTOM_INTERCEPT
      customInterceptProfile:
        interceptEndpointGroup: ${defaultInterceptEndpointGroup.id}

The customInterceptProfile block references an interceptEndpointGroup that defines where traffic is redirected. Like mirroring, you create InterceptDeploymentGroup and InterceptEndpointGroup resources first. The key difference: intercept profiles redirect traffic for inspection and policy enforcement, while mirroring profiles send copies without affecting the original flow.

Beyond these examples

These snippets focus on specific security profile features: threat prevention with severity and protocol overrides, URL filtering with priority-based rules, and traffic mirroring and interception for third-party tools. They’re intentionally minimal rather than full security deployments.

The examples may reference pre-existing infrastructure such as organization IDs and VPC networks for mirroring and intercept profiles. They focus on configuring the profile rather than provisioning the surrounding infrastructure.

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

  • Attaching profiles to firewall policies
  • Regional vs global profile placement
  • Profile versioning and updates (etag handling)
  • Broker-type mirroring with multiple deployment groups

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

Let's configure GCP Network Security Profiles

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Profile Types & Configuration
What security profile types are available?
Four types are available: THREAT_PREVENTION for threat detection and prevention, URL_FILTERING for blocking URLs, CUSTOM_MIRRORING for mirroring traffic to third-party collectors, and CUSTOM_INTERCEPT for intercepting traffic to third-party firewalls.
What's the difference between custom mirroring and custom intercept profiles?
CUSTOM_MIRRORING copies traffic to third-party collectors for analysis without affecting the original flow, while CUSTOM_INTERCEPT redirects traffic through third-party firewall appliances for inspection and filtering. Mirroring uses MirroringEndpointGroup, intercept uses InterceptEndpointGroup.
Immutability & Lifecycle
What fields can't I change after creating a security profile?
The name, type, parent, and location fields are immutable and cannot be modified after creation. Changing any of these requires recreating the resource.
Threat Prevention
How do I configure threat prevention with custom overrides?
Use threatPreventionProfile with three override types: severityOverrides to set actions by severity level (INFORMATIONAL, HIGH, etc.), threatOverrides to override specific threats by ID, and antivirusOverrides to configure actions by protocol (SMTP, etc.).
URL Filtering
How do I set up URL filtering rules?
Configure urlFilteringProfile with urlFilters, where each filter has a priority (lower numbers evaluated first), filteringAction (ALLOW or DENY), and a list of URL patterns. Patterns support wildcards like *example.com.
How does URL filter priority work?
Filters are evaluated in priority order, with lower numbers processed first. In the example, priority 1 allows certain domains, while priority 2 denies restricted subdomains.
Custom Mirroring & Intercept
What resources do I need before creating a custom mirroring profile?
Create a MirroringDeploymentGroup (linked to your network) and a MirroringEndpointGroup (linked to the deployment group) first. Then reference the endpoint group in customMirroringProfile.mirroringEndpointGroup.
What resources do I need before creating a custom intercept profile?
Create an InterceptDeploymentGroup (linked to your network) and an InterceptEndpointGroup (linked to the deployment group) first. Then reference the endpoint group in customInterceptProfile.interceptEndpointGroup.
Can I use multiple deployment groups with mirroring?
Yes, you can specify mirroringDeploymentGroups in customMirroringProfile to mirror traffic from multiple deployment groups. The broker example shows this pattern.
Labels & Metadata
Why aren't all my labels showing up in the labels field?
The labels field is non-authoritative and only manages labels in your configuration. Use effectiveLabels to see all labels on the resource, including those set by other clients and services.

Using a different cloud?

Explore security guides for other cloud providers: