Configure GCP Network Security Profile Groups

The gcp:networksecurity/securityProfileGroup:SecurityProfileGroup resource, part of the Pulumi GCP provider, defines a container that groups security profiles for threat prevention, URL filtering, traffic mirroring, or inline inspection. This guide focuses on three capabilities: threat prevention profiles, traffic mirroring and inline inspection, and URL filtering policies.

Security profile groups reference SecurityProfile resources and may require deployment groups, endpoint groups, and VPC networks depending on the profile type. The examples are intentionally small. Combine them with your own firewall policies and network infrastructure.

Apply threat prevention to network traffic

Organizations protecting cloud workloads often start by applying threat prevention profiles that detect and block malicious traffic patterns at the network layer.

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

const securityProfile = new gcp.networksecurity.SecurityProfile("security_profile", {
    name: "sec-profile",
    type: "THREAT_PREVENTION",
    parent: "organizations/123456789",
    location: "global",
});
const _default = new gcp.networksecurity.SecurityProfileGroup("default", {
    name: "sec-profile-group",
    parent: "organizations/123456789",
    description: "my description",
    threatPreventionProfile: securityProfile.id,
    labels: {
        foo: "bar",
    },
});
import pulumi
import pulumi_gcp as gcp

security_profile = gcp.networksecurity.SecurityProfile("security_profile",
    name="sec-profile",
    type="THREAT_PREVENTION",
    parent="organizations/123456789",
    location="global")
default = gcp.networksecurity.SecurityProfileGroup("default",
    name="sec-profile-group",
    parent="organizations/123456789",
    description="my description",
    threat_prevention_profile=security_profile.id,
    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 {
		securityProfile, err := networksecurity.NewSecurityProfile(ctx, "security_profile", &networksecurity.SecurityProfileArgs{
			Name:     pulumi.String("sec-profile"),
			Type:     pulumi.String("THREAT_PREVENTION"),
			Parent:   pulumi.String("organizations/123456789"),
			Location: pulumi.String("global"),
		})
		if err != nil {
			return err
		}
		_, err = networksecurity.NewSecurityProfileGroup(ctx, "default", &networksecurity.SecurityProfileGroupArgs{
			Name:                    pulumi.String("sec-profile-group"),
			Parent:                  pulumi.String("organizations/123456789"),
			Description:             pulumi.String("my description"),
			ThreatPreventionProfile: securityProfile.ID(),
			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 securityProfile = new Gcp.NetworkSecurity.SecurityProfile("security_profile", new()
    {
        Name = "sec-profile",
        Type = "THREAT_PREVENTION",
        Parent = "organizations/123456789",
        Location = "global",
    });

    var @default = new Gcp.NetworkSecurity.SecurityProfileGroup("default", new()
    {
        Name = "sec-profile-group",
        Parent = "organizations/123456789",
        Description = "my description",
        ThreatPreventionProfile = securityProfile.Id,
        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.SecurityProfileGroup;
import com.pulumi.gcp.networksecurity.SecurityProfileGroupArgs;
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 securityProfile = new SecurityProfile("securityProfile", SecurityProfileArgs.builder()
            .name("sec-profile")
            .type("THREAT_PREVENTION")
            .parent("organizations/123456789")
            .location("global")
            .build());

        var default_ = new SecurityProfileGroup("default", SecurityProfileGroupArgs.builder()
            .name("sec-profile-group")
            .parent("organizations/123456789")
            .description("my description")
            .threatPreventionProfile(securityProfile.id())
            .labels(Map.of("foo", "bar"))
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:SecurityProfileGroup
    properties:
      name: sec-profile-group
      parent: organizations/123456789
      description: my description
      threatPreventionProfile: ${securityProfile.id}
      labels:
        foo: bar
  securityProfile:
    type: gcp:networksecurity:SecurityProfile
    name: security_profile
    properties:
      name: sec-profile
      type: THREAT_PREVENTION
      parent: organizations/123456789
      location: global

The threatPreventionProfile property references a SecurityProfile configured with Google’s threat intelligence. The parent property specifies the organization scope, and location defaults to “global” for organization-wide application. The profile group acts as a container that can be attached to firewall policies.

Mirror traffic to inspection endpoints

Security teams analyzing network behavior deploy mirroring profiles to copy traffic to dedicated inspection endpoints without disrupting production flows.

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

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

default = gcp.compute.Network("default",
    name="network",
    auto_create_subnetworks=False)
default_mirroring_deployment_group = gcp.networksecurity.MirroringDeploymentGroup("default",
    mirroring_deployment_group_id="deployment-group",
    location="global",
    network=default.id)
default_mirroring_endpoint_group = gcp.networksecurity.MirroringEndpointGroup("default",
    mirroring_endpoint_group_id="endpoint-group",
    location="global",
    mirroring_deployment_group=default_mirroring_deployment_group.id)
default_security_profile = gcp.networksecurity.SecurityProfile("default",
    name="sec-profile",
    parent="organizations/123456789",
    description="my description",
    type="CUSTOM_MIRRORING",
    custom_mirroring_profile={
        "mirroring_endpoint_group": default_mirroring_endpoint_group.id,
    })
default_security_profile_group = gcp.networksecurity.SecurityProfileGroup("default",
    name="sec-profile-group",
    parent="organizations/123456789",
    description="my description",
    custom_mirroring_profile=default_security_profile.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("network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		defaultMirroringDeploymentGroup, err := networksecurity.NewMirroringDeploymentGroup(ctx, "default", &networksecurity.MirroringDeploymentGroupArgs{
			MirroringDeploymentGroupId: pulumi.String("deployment-group"),
			Location:                   pulumi.String("global"),
			Network:                    _default.ID(),
		})
		if err != nil {
			return err
		}
		defaultMirroringEndpointGroup, err := networksecurity.NewMirroringEndpointGroup(ctx, "default", &networksecurity.MirroringEndpointGroupArgs{
			MirroringEndpointGroupId: pulumi.String("endpoint-group"),
			Location:                 pulumi.String("global"),
			MirroringDeploymentGroup: defaultMirroringDeploymentGroup.ID(),
		})
		if err != nil {
			return err
		}
		defaultSecurityProfile, err := networksecurity.NewSecurityProfile(ctx, "default", &networksecurity.SecurityProfileArgs{
			Name:        pulumi.String("sec-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
		}
		_, err = networksecurity.NewSecurityProfileGroup(ctx, "default", &networksecurity.SecurityProfileGroupArgs{
			Name:                   pulumi.String("sec-profile-group"),
			Parent:                 pulumi.String("organizations/123456789"),
			Description:            pulumi.String("my description"),
			CustomMirroringProfile: defaultSecurityProfile.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 = "network",
        AutoCreateSubnetworks = false,
    });

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

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

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

    var defaultSecurityProfileGroup = new Gcp.NetworkSecurity.SecurityProfileGroup("default", new()
    {
        Name = "sec-profile-group",
        Parent = "organizations/123456789",
        Description = "my description",
        CustomMirroringProfile = defaultSecurityProfile.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 com.pulumi.gcp.networksecurity.SecurityProfileGroup;
import com.pulumi.gcp.networksecurity.SecurityProfileGroupArgs;
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("network")
            .autoCreateSubnetworks(false)
            .build());

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

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

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

        var defaultSecurityProfileGroup = new SecurityProfileGroup("defaultSecurityProfileGroup", SecurityProfileGroupArgs.builder()
            .name("sec-profile-group")
            .parent("organizations/123456789")
            .description("my description")
            .customMirroringProfile(defaultSecurityProfile.id())
            .build());

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

Traffic mirroring requires three components: a VPC network, a MirroringDeploymentGroup that defines where mirroring occurs, and a MirroringEndpointGroup that specifies inspection destinations. The customMirroringProfile property references a SecurityProfile that ties these together. Mirrored traffic flows to your endpoints while original traffic continues unmodified.

Intercept and inspect traffic inline

Applications requiring deep packet inspection deploy intercept profiles to route traffic through inline security appliances before reaching destinations.

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

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

default = gcp.compute.Network("default",
    name="network",
    auto_create_subnetworks=False)
default_intercept_deployment_group = gcp.networksecurity.InterceptDeploymentGroup("default",
    intercept_deployment_group_id="deployment-group",
    location="global",
    network=default.id)
default_intercept_endpoint_group = gcp.networksecurity.InterceptEndpointGroup("default",
    intercept_endpoint_group_id="endpoint-group",
    location="global",
    intercept_deployment_group=default_intercept_deployment_group.id)
default_security_profile = gcp.networksecurity.SecurityProfile("default",
    name="sec-profile",
    parent="organizations/123456789",
    description="my description",
    type="CUSTOM_INTERCEPT",
    custom_intercept_profile={
        "intercept_endpoint_group": default_intercept_endpoint_group.id,
    })
default_security_profile_group = gcp.networksecurity.SecurityProfileGroup("default",
    name="sec-profile-group",
    parent="organizations/123456789",
    description="my description",
    custom_intercept_profile=default_security_profile.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("network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		defaultInterceptDeploymentGroup, err := networksecurity.NewInterceptDeploymentGroup(ctx, "default", &networksecurity.InterceptDeploymentGroupArgs{
			InterceptDeploymentGroupId: pulumi.String("deployment-group"),
			Location:                   pulumi.String("global"),
			Network:                    _default.ID(),
		})
		if err != nil {
			return err
		}
		defaultInterceptEndpointGroup, err := networksecurity.NewInterceptEndpointGroup(ctx, "default", &networksecurity.InterceptEndpointGroupArgs{
			InterceptEndpointGroupId: pulumi.String("endpoint-group"),
			Location:                 pulumi.String("global"),
			InterceptDeploymentGroup: defaultInterceptDeploymentGroup.ID(),
		})
		if err != nil {
			return err
		}
		defaultSecurityProfile, err := networksecurity.NewSecurityProfile(ctx, "default", &networksecurity.SecurityProfileArgs{
			Name:        pulumi.String("sec-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
		}
		_, err = networksecurity.NewSecurityProfileGroup(ctx, "default", &networksecurity.SecurityProfileGroupArgs{
			Name:                   pulumi.String("sec-profile-group"),
			Parent:                 pulumi.String("organizations/123456789"),
			Description:            pulumi.String("my description"),
			CustomInterceptProfile: defaultSecurityProfile.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 = "network",
        AutoCreateSubnetworks = false,
    });

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

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

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

    var defaultSecurityProfileGroup = new Gcp.NetworkSecurity.SecurityProfileGroup("default", new()
    {
        Name = "sec-profile-group",
        Parent = "organizations/123456789",
        Description = "my description",
        CustomInterceptProfile = defaultSecurityProfile.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 com.pulumi.gcp.networksecurity.SecurityProfileGroup;
import com.pulumi.gcp.networksecurity.SecurityProfileGroupArgs;
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("network")
            .autoCreateSubnetworks(false)
            .build());

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

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

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

        var defaultSecurityProfileGroup = new SecurityProfileGroup("defaultSecurityProfileGroup", SecurityProfileGroupArgs.builder()
            .name("sec-profile-group")
            .parent("organizations/123456789")
            .description("my description")
            .customInterceptProfile(defaultSecurityProfile.id())
            .build());

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

Intercept profiles work similarly to mirroring but modify the traffic path. The InterceptDeploymentGroup and InterceptEndpointGroup define where traffic is redirected for inspection. Unlike mirroring, intercepted traffic must pass through your security appliances before reaching its destination, enabling active blocking or modification.

Filter traffic by URL patterns

Organizations enforcing acceptable use policies apply URL filtering to allow or block traffic based on domain patterns and URL paths.

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

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

security_profile = gcp.networksecurity.SecurityProfile("security_profile",
    name="sec-profile",
    location="global",
    type="URL_FILTERING",
    url_filtering_profile={
        "url_filters": [{
            "priority": 1,
            "filtering_action": "ALLOW",
            "urls": [
                "*example.com",
                "*about.example.com",
                "*help.example.com",
            ],
        }],
    },
    parent="organizations/123456789")
default = gcp.networksecurity.SecurityProfileGroup("default",
    name="sec-profile-group",
    parent="organizations/123456789",
    description="my description",
    url_filtering_profile=security_profile.id,
    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 {
		securityProfile, err := networksecurity.NewSecurityProfile(ctx, "security_profile", &networksecurity.SecurityProfileArgs{
			Name:     pulumi.String("sec-profile"),
			Location: pulumi.String("global"),
			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"),
						},
					},
				},
			},
			Parent: pulumi.String("organizations/123456789"),
		})
		if err != nil {
			return err
		}
		_, err = networksecurity.NewSecurityProfileGroup(ctx, "default", &networksecurity.SecurityProfileGroupArgs{
			Name:                pulumi.String("sec-profile-group"),
			Parent:              pulumi.String("organizations/123456789"),
			Description:         pulumi.String("my description"),
			UrlFilteringProfile: securityProfile.ID(),
			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 securityProfile = new Gcp.NetworkSecurity.SecurityProfile("security_profile", new()
    {
        Name = "sec-profile",
        Location = "global",
        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",
                    },
                },
            },
        },
        Parent = "organizations/123456789",
    });

    var @default = new Gcp.NetworkSecurity.SecurityProfileGroup("default", new()
    {
        Name = "sec-profile-group",
        Parent = "organizations/123456789",
        Description = "my description",
        UrlFilteringProfile = securityProfile.Id,
        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 com.pulumi.gcp.networksecurity.SecurityProfileGroup;
import com.pulumi.gcp.networksecurity.SecurityProfileGroupArgs;
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 securityProfile = new SecurityProfile("securityProfile", SecurityProfileArgs.builder()
            .name("sec-profile")
            .location("global")
            .type("URL_FILTERING")
            .urlFilteringProfile(SecurityProfileUrlFilteringProfileArgs.builder()
                .urlFilters(SecurityProfileUrlFilteringProfileUrlFilterArgs.builder()
                    .priority(1)
                    .filteringAction("ALLOW")
                    .urls(                    
                        "*example.com",
                        "*about.example.com",
                        "*help.example.com")
                    .build())
                .build())
            .parent("organizations/123456789")
            .build());

        var default_ = new SecurityProfileGroup("default", SecurityProfileGroupArgs.builder()
            .name("sec-profile-group")
            .parent("organizations/123456789")
            .description("my description")
            .urlFilteringProfile(securityProfile.id())
            .labels(Map.of("foo", "bar"))
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:SecurityProfileGroup
    properties:
      name: sec-profile-group
      parent: organizations/123456789
      description: my description
      urlFilteringProfile: ${securityProfile.id}
      labels:
        foo: bar
  securityProfile:
    type: gcp:networksecurity:SecurityProfile
    name: security_profile
    properties:
      name: sec-profile
      location: global
      type: URL_FILTERING
      urlFilteringProfile:
        urlFilters:
          - priority: 1
            filteringAction: ALLOW
            urls:
              - '*example.com'
              - '*about.example.com'
              - '*help.example.com'
      parent: organizations/123456789

The urlFilteringProfile references a SecurityProfile with URL filter rules. Each filter specifies a priority, filteringAction (ALLOW or BLOCK), and URL patterns using wildcards. Lower priority numbers are evaluated first. This example allows traffic to example.com and specific subdomains.

Beyond these examples

These snippets focus on specific security profile group features: threat prevention and URL filtering, and traffic mirroring and inline inspection. They’re intentionally minimal rather than full network security deployments.

The examples require pre-existing infrastructure such as a GCP organization with valid organization ID, and VPC networks (created in examples but could reference existing). They focus on configuring profile groups rather than provisioning the complete security architecture.

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

  • Firewall policy attachment (how profile groups apply to traffic)
  • Multiple profile types in one group (combining threat prevention with URL filtering)
  • Regional vs global deployment considerations
  • Label-based organization and filtering

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

Let's configure GCP Network Security Profile Groups

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Setup
What properties can't I change after creating a security profile group?
The name, parent, and location properties are immutable and cannot be changed after creation.
What format should I use for the parent property?
Use the format organizations/{organization_id}, where {organization_id} is your GCP organization ID.
What's the default location for a security profile group?
The default location is global if not specified.
Security Profiles
What types of security profiles can I attach to a security profile group?

You can attach four types of security profiles:

  1. Threat Prevention - Use threatPreventionProfile
  2. Custom Mirroring - Use customMirroringProfile
  3. Custom Intercept - Use customInterceptProfile
  4. URL Filtering - Use urlFilteringProfile
What's required to use mirroring or intercept profiles?
Mirroring profiles require a MirroringDeploymentGroup and MirroringEndpointGroup. Intercept profiles require an InterceptDeploymentGroup and InterceptEndpointGroup.
Labels & Metadata
Why aren't all my labels showing up in the labels field?
The labels field is non-authoritative and only manages labels present 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: