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 belong to GCP organizations. Mirroring and intercept configurations require VPC networks, deployment groups, and endpoint groups. 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 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 (format: organizations/{organization_id}), and location defaults to global for organization-wide application. The profile group acts as a container; you attach it to firewall policies to enforce protection.

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 of type CUSTOM_MIRRORING 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 deployment works similarly to mirroring but modifies the traffic path. The InterceptDeploymentGroup and InterceptEndpointGroup define where and how traffic is redirected. The customInterceptProfile property references a SecurityProfile of type CUSTOM_INTERCEPT. Unlike mirroring, intercepted traffic must pass through your inspection endpoints before reaching its destination.

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 property references a SecurityProfile that defines URL filtering rules. Each rule specifies a priority, filteringAction (ALLOW or BLOCK), and URL patterns using wildcards. Rules are evaluated in priority order; the first match determines the action. 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 networks). They focus on configuring profile groups rather than provisioning complete security architectures.

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

  • Attaching profile groups to firewall policies
  • Regional vs global profile group placement
  • Label-based organization and filtering
  • Profile group lifecycle (updates, versioning)

These omissions are intentional: the goal is to illustrate how each security profile type is wired, not provide drop-in security modules. See the SecurityProfileGroup 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 & Immutability
What properties can't I change after creating a security profile group?
The name, location, and parent properties are immutable. Changing any of these requires recreating the resource.
What format should I use for the parent parameter?
Use the format organizations/{organization_id}, as shown in all examples (e.g., organizations/123456789).
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 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
Can I attach multiple security profiles to one group?
Yes, the examples show you can configure different profile types (threat prevention, mirroring, intercept, URL filtering) on the same group by setting the corresponding properties.
Advanced Configurations
How do I set up custom mirroring for a security profile group?

Create the following resources in order:

  1. gcp.networksecurity.MirroringDeploymentGroup with a network
  2. gcp.networksecurity.MirroringEndpointGroup referencing the deployment group
  3. gcp.networksecurity.SecurityProfile with customMirroringProfile referencing the endpoint group
  4. Reference the security profile in your profile group’s customMirroringProfile property
How do I set up custom intercept for a security profile group?

Create the following resources in order:

  1. gcp.networksecurity.InterceptDeploymentGroup with a network
  2. gcp.networksecurity.InterceptEndpointGroup referencing the deployment group
  3. gcp.networksecurity.SecurityProfile with customInterceptProfile referencing the endpoint group
  4. Reference the security profile in your profile group’s customInterceptProfile property
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 Pulumi configuration. To see all labels on the resource (including those set by other clients), use the effectiveLabels output property.
What's the maximum length for the description field?
The description has a maximum length of 512 characters.

Using a different cloud?

Explore security guides for other cloud providers: