Configure GCP Server TLS Policies

The gcp:networksecurity/serverTlsPolicy:ServerTlsPolicy resource, part of the Pulumi GCP provider, defines how servers authenticate incoming TLS connections: certificate provisioning, client validation requirements, and trust anchor configuration. This guide focuses on three capabilities: server certificate provisioning from gRPC endpoints, mTLS client validation modes, and Trust Config integration for certificate authorities.

Server TLS policies don’t affect traffic until attached to HTTPS proxies or endpoint config selectors. Examples reference gRPC endpoints and Certificate Manager TrustConfig resources that must exist separately. The examples are intentionally small. Combine them with your own proxy configuration and certificate infrastructure.

Provision server certificates from a gRPC endpoint

Load balancers need server certificates to terminate TLS. When certificates are managed externally, the policy references a gRPC endpoint that provides certificate material at runtime.

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

const _default = new gcp.networksecurity.ServerTlsPolicy("default", {
    name: "my-server-tls-policy",
    labels: {
        foo: "bar",
    },
    description: "my description",
    location: "global",
    allowOpen: false,
    serverCertificate: {
        grpcEndpoint: {
            targetUri: "unix:mypath",
        },
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.networksecurity.ServerTlsPolicy("default",
    name="my-server-tls-policy",
    labels={
        "foo": "bar",
    },
    description="my description",
    location="global",
    allow_open=False,
    server_certificate={
        "grpc_endpoint": {
            "target_uri": "unix:mypath",
        },
    })
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.NewServerTlsPolicy(ctx, "default", &networksecurity.ServerTlsPolicyArgs{
			Name: pulumi.String("my-server-tls-policy"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Description: pulumi.String("my description"),
			Location:    pulumi.String("global"),
			AllowOpen:   pulumi.Bool(false),
			ServerCertificate: &networksecurity.ServerTlsPolicyServerCertificateArgs{
				GrpcEndpoint: &networksecurity.ServerTlsPolicyServerCertificateGrpcEndpointArgs{
					TargetUri: pulumi.String("unix:mypath"),
				},
			},
		})
		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.ServerTlsPolicy("default", new()
    {
        Name = "my-server-tls-policy",
        Labels = 
        {
            { "foo", "bar" },
        },
        Description = "my description",
        Location = "global",
        AllowOpen = false,
        ServerCertificate = new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyServerCertificateArgs
        {
            GrpcEndpoint = new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyServerCertificateGrpcEndpointArgs
            {
                TargetUri = "unix:mypath",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networksecurity.ServerTlsPolicy;
import com.pulumi.gcp.networksecurity.ServerTlsPolicyArgs;
import com.pulumi.gcp.networksecurity.inputs.ServerTlsPolicyServerCertificateArgs;
import com.pulumi.gcp.networksecurity.inputs.ServerTlsPolicyServerCertificateGrpcEndpointArgs;
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 ServerTlsPolicy("default", ServerTlsPolicyArgs.builder()
            .name("my-server-tls-policy")
            .labels(Map.of("foo", "bar"))
            .description("my description")
            .location("global")
            .allowOpen(false)
            .serverCertificate(ServerTlsPolicyServerCertificateArgs.builder()
                .grpcEndpoint(ServerTlsPolicyServerCertificateGrpcEndpointArgs.builder()
                    .targetUri("unix:mypath")
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:ServerTlsPolicy
    properties:
      name: my-server-tls-policy
      labels:
        foo: bar
      description: my description
      location: global
      allowOpen: 'false'
      serverCertificate:
        grpcEndpoint:
          targetUri: unix:mypath

The serverCertificate block tells the proxy where to fetch its certificate. The grpcEndpoint.targetUri points to a certificate provider (here, a Unix socket). Setting allowOpen to false ensures the server rejects plaintext connections.

Validate client certificates with mTLS

Mutual TLS requires both server and client to present certificates, enabling zero-trust authentication for service-to-service communication.

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

const _default = new gcp.networksecurity.ServerTlsPolicy("default", {
    name: "my-server-tls-policy",
    labels: {
        foo: "bar",
    },
    description: "my description",
    allowOpen: false,
    serverCertificate: {
        certificateProviderInstance: {
            pluginInstance: "google_cloud_private_spiffe",
        },
    },
    mtlsPolicy: {
        clientValidationCas: [{
            grpcEndpoint: {
                targetUri: "unix:mypath",
            },
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.networksecurity.ServerTlsPolicy("default",
    name="my-server-tls-policy",
    labels={
        "foo": "bar",
    },
    description="my description",
    allow_open=False,
    server_certificate={
        "certificate_provider_instance": {
            "plugin_instance": "google_cloud_private_spiffe",
        },
    },
    mtls_policy={
        "client_validation_cas": [{
            "grpc_endpoint": {
                "target_uri": "unix:mypath",
            },
        }],
    })
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.NewServerTlsPolicy(ctx, "default", &networksecurity.ServerTlsPolicyArgs{
			Name: pulumi.String("my-server-tls-policy"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Description: pulumi.String("my description"),
			AllowOpen:   pulumi.Bool(false),
			ServerCertificate: &networksecurity.ServerTlsPolicyServerCertificateArgs{
				CertificateProviderInstance: &networksecurity.ServerTlsPolicyServerCertificateCertificateProviderInstanceArgs{
					PluginInstance: pulumi.String("google_cloud_private_spiffe"),
				},
			},
			MtlsPolicy: &networksecurity.ServerTlsPolicyMtlsPolicyArgs{
				ClientValidationCas: networksecurity.ServerTlsPolicyMtlsPolicyClientValidationCaArray{
					&networksecurity.ServerTlsPolicyMtlsPolicyClientValidationCaArgs{
						GrpcEndpoint: &networksecurity.ServerTlsPolicyMtlsPolicyClientValidationCaGrpcEndpointArgs{
							TargetUri: pulumi.String("unix:mypath"),
						},
					},
				},
			},
		})
		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.ServerTlsPolicy("default", new()
    {
        Name = "my-server-tls-policy",
        Labels = 
        {
            { "foo", "bar" },
        },
        Description = "my description",
        AllowOpen = false,
        ServerCertificate = new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyServerCertificateArgs
        {
            CertificateProviderInstance = new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyServerCertificateCertificateProviderInstanceArgs
            {
                PluginInstance = "google_cloud_private_spiffe",
            },
        },
        MtlsPolicy = new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyMtlsPolicyArgs
        {
            ClientValidationCas = new[]
            {
                new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyMtlsPolicyClientValidationCaArgs
                {
                    GrpcEndpoint = new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyMtlsPolicyClientValidationCaGrpcEndpointArgs
                    {
                        TargetUri = "unix:mypath",
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networksecurity.ServerTlsPolicy;
import com.pulumi.gcp.networksecurity.ServerTlsPolicyArgs;
import com.pulumi.gcp.networksecurity.inputs.ServerTlsPolicyServerCertificateArgs;
import com.pulumi.gcp.networksecurity.inputs.ServerTlsPolicyServerCertificateCertificateProviderInstanceArgs;
import com.pulumi.gcp.networksecurity.inputs.ServerTlsPolicyMtlsPolicyArgs;
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 ServerTlsPolicy("default", ServerTlsPolicyArgs.builder()
            .name("my-server-tls-policy")
            .labels(Map.of("foo", "bar"))
            .description("my description")
            .allowOpen(false)
            .serverCertificate(ServerTlsPolicyServerCertificateArgs.builder()
                .certificateProviderInstance(ServerTlsPolicyServerCertificateCertificateProviderInstanceArgs.builder()
                    .pluginInstance("google_cloud_private_spiffe")
                    .build())
                .build())
            .mtlsPolicy(ServerTlsPolicyMtlsPolicyArgs.builder()
                .clientValidationCas(ServerTlsPolicyMtlsPolicyClientValidationCaArgs.builder()
                    .grpcEndpoint(ServerTlsPolicyMtlsPolicyClientValidationCaGrpcEndpointArgs.builder()
                        .targetUri("unix:mypath")
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:ServerTlsPolicy
    properties:
      name: my-server-tls-policy
      labels:
        foo: bar
      description: my description
      allowOpen: 'false'
      serverCertificate:
        certificateProviderInstance:
          pluginInstance: google_cloud_private_spiffe
      mtlsPolicy:
        clientValidationCas:
          - grpcEndpoint:
              targetUri: unix:mypath

The mtlsPolicy block enables client certificate validation. The clientValidationCas array specifies gRPC endpoints that provide trusted CA certificates for validating client certificates. The serverCertificate block provisions the server’s own certificate using the google_cloud_private_spiffe plugin, which integrates with SPIFFE-based identity systems.

Reject invalid client certificates with Trust Config

Production mTLS deployments often need strict validation against a trusted certificate authority hierarchy managed through Certificate Manager.

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

const project = gcp.organizations.getProject({});
const defaultTrustConfig = new gcp.certificatemanager.TrustConfig("default", {
    name: "my-trust-config",
    description: "sample trust config description",
    location: "global",
    trustStores: [{
        trustAnchors: [{
            pemCertificate: std.file({
                input: "test-fixtures/ca_cert.pem",
            }).then(invoke => invoke.result),
        }],
        intermediateCas: [{
            pemCertificate: std.file({
                input: "test-fixtures/ca_cert.pem",
            }).then(invoke => invoke.result),
        }],
    }],
    labels: {
        foo: "bar",
    },
});
const _default = new gcp.networksecurity.ServerTlsPolicy("default", {
    name: "my-server-tls-policy",
    description: "my description",
    location: "global",
    allowOpen: false,
    mtlsPolicy: {
        clientValidationMode: "REJECT_INVALID",
        clientValidationTrustConfig: pulumi.all([project, defaultTrustConfig.name]).apply(([project, name]) => `projects/${project.number}/locations/global/trustConfigs/${name}`),
    },
    labels: {
        foo: "bar",
    },
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std

project = gcp.organizations.get_project()
default_trust_config = gcp.certificatemanager.TrustConfig("default",
    name="my-trust-config",
    description="sample trust config description",
    location="global",
    trust_stores=[{
        "trust_anchors": [{
            "pem_certificate": std.file(input="test-fixtures/ca_cert.pem").result,
        }],
        "intermediate_cas": [{
            "pem_certificate": std.file(input="test-fixtures/ca_cert.pem").result,
        }],
    }],
    labels={
        "foo": "bar",
    })
default = gcp.networksecurity.ServerTlsPolicy("default",
    name="my-server-tls-policy",
    description="my description",
    location="global",
    allow_open=False,
    mtls_policy={
        "client_validation_mode": "REJECT_INVALID",
        "client_validation_trust_config": default_trust_config.name.apply(lambda name: f"projects/{project.number}/locations/global/trustConfigs/{name}"),
    },
    labels={
        "foo": "bar",
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/certificatemanager"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networksecurity"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		invokeFile, err := std.File(ctx, &std.FileArgs{
			Input: "test-fixtures/ca_cert.pem",
		}, nil)
		if err != nil {
			return err
		}
		invokeFile1, err := std.File(ctx, &std.FileArgs{
			Input: "test-fixtures/ca_cert.pem",
		}, nil)
		if err != nil {
			return err
		}
		defaultTrustConfig, err := certificatemanager.NewTrustConfig(ctx, "default", &certificatemanager.TrustConfigArgs{
			Name:        pulumi.String("my-trust-config"),
			Description: pulumi.String("sample trust config description"),
			Location:    pulumi.String("global"),
			TrustStores: certificatemanager.TrustConfigTrustStoreArray{
				&certificatemanager.TrustConfigTrustStoreArgs{
					TrustAnchors: certificatemanager.TrustConfigTrustStoreTrustAnchorArray{
						&certificatemanager.TrustConfigTrustStoreTrustAnchorArgs{
							PemCertificate: pulumi.String(invokeFile.Result),
						},
					},
					IntermediateCas: certificatemanager.TrustConfigTrustStoreIntermediateCaArray{
						&certificatemanager.TrustConfigTrustStoreIntermediateCaArgs{
							PemCertificate: pulumi.String(invokeFile1.Result),
						},
					},
				},
			},
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
		})
		if err != nil {
			return err
		}
		_, err = networksecurity.NewServerTlsPolicy(ctx, "default", &networksecurity.ServerTlsPolicyArgs{
			Name:        pulumi.String("my-server-tls-policy"),
			Description: pulumi.String("my description"),
			Location:    pulumi.String("global"),
			AllowOpen:   pulumi.Bool(false),
			MtlsPolicy: &networksecurity.ServerTlsPolicyMtlsPolicyArgs{
				ClientValidationMode: pulumi.String("REJECT_INVALID"),
				ClientValidationTrustConfig: defaultTrustConfig.Name.ApplyT(func(name string) (string, error) {
					return fmt.Sprintf("projects/%v/locations/global/trustConfigs/%v", project.Number, name), nil
				}).(pulumi.StringOutput),
			},
			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;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var project = Gcp.Organizations.GetProject.Invoke();

    var defaultTrustConfig = new Gcp.CertificateManager.TrustConfig("default", new()
    {
        Name = "my-trust-config",
        Description = "sample trust config description",
        Location = "global",
        TrustStores = new[]
        {
            new Gcp.CertificateManager.Inputs.TrustConfigTrustStoreArgs
            {
                TrustAnchors = new[]
                {
                    new Gcp.CertificateManager.Inputs.TrustConfigTrustStoreTrustAnchorArgs
                    {
                        PemCertificate = Std.File.Invoke(new()
                        {
                            Input = "test-fixtures/ca_cert.pem",
                        }).Apply(invoke => invoke.Result),
                    },
                },
                IntermediateCas = new[]
                {
                    new Gcp.CertificateManager.Inputs.TrustConfigTrustStoreIntermediateCaArgs
                    {
                        PemCertificate = Std.File.Invoke(new()
                        {
                            Input = "test-fixtures/ca_cert.pem",
                        }).Apply(invoke => invoke.Result),
                    },
                },
            },
        },
        Labels = 
        {
            { "foo", "bar" },
        },
    });

    var @default = new Gcp.NetworkSecurity.ServerTlsPolicy("default", new()
    {
        Name = "my-server-tls-policy",
        Description = "my description",
        Location = "global",
        AllowOpen = false,
        MtlsPolicy = new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyMtlsPolicyArgs
        {
            ClientValidationMode = "REJECT_INVALID",
            ClientValidationTrustConfig = Output.Tuple(project, defaultTrustConfig.Name).Apply(values =>
            {
                var project = values.Item1;
                var name = values.Item2;
                return $"projects/{project.Apply(getProjectResult => getProjectResult.Number)}/locations/global/trustConfigs/{name}";
            }),
        },
        Labels = 
        {
            { "foo", "bar" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.certificatemanager.TrustConfig;
import com.pulumi.gcp.certificatemanager.TrustConfigArgs;
import com.pulumi.gcp.certificatemanager.inputs.TrustConfigTrustStoreArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.FileArgs;
import com.pulumi.gcp.networksecurity.ServerTlsPolicy;
import com.pulumi.gcp.networksecurity.ServerTlsPolicyArgs;
import com.pulumi.gcp.networksecurity.inputs.ServerTlsPolicyMtlsPolicyArgs;
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) {
        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var defaultTrustConfig = new TrustConfig("defaultTrustConfig", TrustConfigArgs.builder()
            .name("my-trust-config")
            .description("sample trust config description")
            .location("global")
            .trustStores(TrustConfigTrustStoreArgs.builder()
                .trustAnchors(TrustConfigTrustStoreTrustAnchorArgs.builder()
                    .pemCertificate(StdFunctions.file(FileArgs.builder()
                        .input("test-fixtures/ca_cert.pem")
                        .build()).result())
                    .build())
                .intermediateCas(TrustConfigTrustStoreIntermediateCaArgs.builder()
                    .pemCertificate(StdFunctions.file(FileArgs.builder()
                        .input("test-fixtures/ca_cert.pem")
                        .build()).result())
                    .build())
                .build())
            .labels(Map.of("foo", "bar"))
            .build());

        var default_ = new ServerTlsPolicy("default", ServerTlsPolicyArgs.builder()
            .name("my-server-tls-policy")
            .description("my description")
            .location("global")
            .allowOpen(false)
            .mtlsPolicy(ServerTlsPolicyMtlsPolicyArgs.builder()
                .clientValidationMode("REJECT_INVALID")
                .clientValidationTrustConfig(defaultTrustConfig.name().applyValue(_name -> String.format("projects/%s/locations/global/trustConfigs/%s", project.number(),_name)))
                .build())
            .labels(Map.of("foo", "bar"))
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:ServerTlsPolicy
    properties:
      name: my-server-tls-policy
      description: my description
      location: global
      allowOpen: 'false'
      mtlsPolicy:
        clientValidationMode: REJECT_INVALID
        clientValidationTrustConfig: projects/${project.number}/locations/global/trustConfigs/${defaultTrustConfig.name}
      labels:
        foo: bar
  defaultTrustConfig:
    type: gcp:certificatemanager:TrustConfig
    name: default
    properties:
      name: my-trust-config
      description: sample trust config description
      location: global
      trustStores:
        - trustAnchors:
            - pemCertificate:
                fn::invoke:
                  function: std:file
                  arguments:
                    input: test-fixtures/ca_cert.pem
                  return: result
          intermediateCas:
            - pemCertificate:
                fn::invoke:
                  function: std:file
                  arguments:
                    input: test-fixtures/ca_cert.pem
                  return: result
      labels:
        foo: bar
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

This configuration extends basic mTLS with strict validation. The clientValidationMode set to REJECT_INVALID refuses connections from clients with invalid or missing certificates. The clientValidationTrustConfig references a Certificate Manager TrustConfig resource that defines trust anchors and intermediate CAs. The TrustConfig resource loads CA certificates from PEM files and manages the trust hierarchy.

Allow connections with missing or invalid client certificates

During migration to mTLS, services may need to accept both authenticated and unauthenticated clients while monitoring certificate adoption.

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

const _default = new gcp.networksecurity.ServerTlsPolicy("default", {
    name: "my-server-tls-policy",
    labels: {
        foo: "bar",
    },
    description: "my description",
    location: "global",
    allowOpen: false,
    mtlsPolicy: {
        clientValidationMode: "ALLOW_INVALID_OR_MISSING_CLIENT_CERT",
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.networksecurity.ServerTlsPolicy("default",
    name="my-server-tls-policy",
    labels={
        "foo": "bar",
    },
    description="my description",
    location="global",
    allow_open=False,
    mtls_policy={
        "client_validation_mode": "ALLOW_INVALID_OR_MISSING_CLIENT_CERT",
    })
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.NewServerTlsPolicy(ctx, "default", &networksecurity.ServerTlsPolicyArgs{
			Name: pulumi.String("my-server-tls-policy"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Description: pulumi.String("my description"),
			Location:    pulumi.String("global"),
			AllowOpen:   pulumi.Bool(false),
			MtlsPolicy: &networksecurity.ServerTlsPolicyMtlsPolicyArgs{
				ClientValidationMode: pulumi.String("ALLOW_INVALID_OR_MISSING_CLIENT_CERT"),
			},
		})
		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.ServerTlsPolicy("default", new()
    {
        Name = "my-server-tls-policy",
        Labels = 
        {
            { "foo", "bar" },
        },
        Description = "my description",
        Location = "global",
        AllowOpen = false,
        MtlsPolicy = new Gcp.NetworkSecurity.Inputs.ServerTlsPolicyMtlsPolicyArgs
        {
            ClientValidationMode = "ALLOW_INVALID_OR_MISSING_CLIENT_CERT",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networksecurity.ServerTlsPolicy;
import com.pulumi.gcp.networksecurity.ServerTlsPolicyArgs;
import com.pulumi.gcp.networksecurity.inputs.ServerTlsPolicyMtlsPolicyArgs;
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 ServerTlsPolicy("default", ServerTlsPolicyArgs.builder()
            .name("my-server-tls-policy")
            .labels(Map.of("foo", "bar"))
            .description("my description")
            .location("global")
            .allowOpen(false)
            .mtlsPolicy(ServerTlsPolicyMtlsPolicyArgs.builder()
                .clientValidationMode("ALLOW_INVALID_OR_MISSING_CLIENT_CERT")
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:networksecurity:ServerTlsPolicy
    properties:
      name: my-server-tls-policy
      labels:
        foo: bar
      description: my description
      location: global
      allowOpen: 'false'
      mtlsPolicy:
        clientValidationMode: ALLOW_INVALID_OR_MISSING_CLIENT_CERT

The clientValidationMode set to ALLOW_INVALID_OR_MISSING_CLIENT_CERT permits connections even when clients don’t present valid certificates. This supports gradual mTLS rollout: you can deploy the policy, observe which clients send certificates, and later switch to REJECT_INVALID for strict enforcement.

Beyond these examples

These snippets focus on specific server TLS policy features: server certificate provisioning, mTLS client validation modes, and Trust Config integration. They’re intentionally minimal rather than full load balancer configurations.

The examples reference pre-existing infrastructure such as HTTPS proxies or endpoint config selectors (policy attachment points), gRPC endpoints for certificate provisioning, Certificate Manager TrustConfig resources, and CA certificate files for trust anchors. They focus on configuring the policy rather than provisioning the surrounding infrastructure.

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

  • Policy attachment to HTTPS proxies or endpoint selectors
  • Certificate rotation and renewal workflows
  • Custom certificate provider plugins
  • Traffic Director-specific configurations (allowOpen with plaintext)

These omissions are intentional: the goal is to illustrate how each TLS policy feature is wired, not provide drop-in load balancer modules. See the ServerTlsPolicy resource reference for all available configuration options.

Let's configure GCP Server TLS Policies

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Policy Attachment & Activation
Does creating a ServerTlsPolicy automatically enable TLS on my services?
No. The policy doesn’t affect configuration until you attach it to a target HTTPS proxy or endpoint config selector resource.
mTLS Configuration
When is mtlsPolicy required?
The mtlsPolicy field is required for external HTTPS load balancers but can be empty for Traffic Director policies.
How does serverCertificate affect mTLS?
The presence of serverCertificate dictates whether mTLS is enabled. It provisions client identity (public and private keys) for peer-to-peer authentication.
How do I configure mTLS with a TrustConfig?
Set mtlsPolicy.clientValidationTrustConfig to reference your TrustConfig resource, and configure clientValidationMode (e.g., REJECT_INVALID).
What client validation modes are available?
You can set clientValidationMode to values like ALLOW_INVALID_OR_MISSING_CLIENT_CERT (permissive) or REJECT_INVALID (strict validation).
Traffic Director vs External HTTPS Load Balancer
What's the difference between Traffic Director and external HTTPS load balancer policies?
Traffic Director policies can use allowOpen for plaintext connections and have optional mtlsPolicy. External HTTPS load balancer policies must set allowOpen to false and require mtlsPolicy.
What's allowOpen and when should I use it?
The allowOpen field allows plaintext connections alongside TLS/mTLS. Use it for in-place upgrades when you have mixed TLS and non-TLS traffic. It only applies to Traffic Director policies and must be false for external HTTPS load balancers.
Resource Management
What properties are immutable after creation?
The name and project properties cannot be changed after the ServerTlsPolicy is created.
Why don't my label changes show up in effectiveLabels?
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.
What's the default location for a ServerTlsPolicy?
The default location is global.

Using a different cloud?

Explore security guides for other cloud providers: