Deploy GCP Secure Source Manager Instances

The gcp:securesourcemanager/instance:Instance resource, part of the Pulumi GCP provider, provisions a Secure Source Manager instance: a regional Git hosting service with web interface access. This guide focuses on four capabilities: basic instance creation with labels, customer-managed encryption keys, private networking with Certificate Authority, and workforce identity federation.

Instances may reference Cloud KMS keys, Certificate Authority pools, VPC networks, and identity providers that must exist separately. The examples are intentionally small. Combine them with your own encryption, networking, and identity infrastructure.

Create a basic instance with labels

Most deployments start with a regional instance, using labels for organization and cost tracking.

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

const _default = new gcp.securesourcemanager.Instance("default", {
    location: "us-central1",
    instanceId: "my-instance",
    labels: {
        foo: "bar",
    },
    deletionPolicy: "PREVENT",
});
import pulumi
import pulumi_gcp as gcp

default = gcp.securesourcemanager.Instance("default",
    location="us-central1",
    instance_id="my-instance",
    labels={
        "foo": "bar",
    },
    deletion_policy="PREVENT")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := securesourcemanager.NewInstance(ctx, "default", &securesourcemanager.InstanceArgs{
			Location:   pulumi.String("us-central1"),
			InstanceId: pulumi.String("my-instance"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			DeletionPolicy: pulumi.String("PREVENT"),
		})
		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.SecureSourceManager.Instance("default", new()
    {
        Location = "us-central1",
        InstanceId = "my-instance",
        Labels = 
        {
            { "foo", "bar" },
        },
        DeletionPolicy = "PREVENT",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.securesourcemanager.Instance;
import com.pulumi.gcp.securesourcemanager.InstanceArgs;
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 Instance("default", InstanceArgs.builder()
            .location("us-central1")
            .instanceId("my-instance")
            .labels(Map.of("foo", "bar"))
            .deletionPolicy("PREVENT")
            .build());

    }
}
resources:
  default:
    type: gcp:securesourcemanager:Instance
    properties:
      location: us-central1
      instanceId: my-instance
      labels:
        foo: bar
      deletionPolicy: PREVENT

The location property places the instance in a Google Cloud region. The instanceId provides a unique name within that region. The deletionPolicy property controls what happens during resource deletion; PREVENT blocks accidental deletion by failing the plan.

Encrypt instance data with customer-managed keys

Organizations with strict data governance requirements use customer-managed encryption keys (CMEK) to control encryption of source code repositories.

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

const project = gcp.organizations.getProject({});
const cryptoKeyBinding = new gcp.kms.CryptoKeyIAMMember("crypto_key_binding", {
    cryptoKeyId: "my-key",
    role: "roles/cloudkms.cryptoKeyEncrypterDecrypter",
    member: project.then(project => `serviceAccount:service-${project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com`),
});
const _default = new gcp.securesourcemanager.Instance("default", {
    location: "us-central1",
    instanceId: "my-instance",
    kmsKey: "my-key",
    deletionPolicy: "PREVENT",
}, {
    dependsOn: [cryptoKeyBinding],
});
import pulumi
import pulumi_gcp as gcp

project = gcp.organizations.get_project()
crypto_key_binding = gcp.kms.CryptoKeyIAMMember("crypto_key_binding",
    crypto_key_id="my-key",
    role="roles/cloudkms.cryptoKeyEncrypterDecrypter",
    member=f"serviceAccount:service-{project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com")
default = gcp.securesourcemanager.Instance("default",
    location="us-central1",
    instance_id="my-instance",
    kms_key="my-key",
    deletion_policy="PREVENT",
    opts = pulumi.ResourceOptions(depends_on=[crypto_key_binding]))
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/kms"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/securesourcemanager"
	"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
		}
		cryptoKeyBinding, err := kms.NewCryptoKeyIAMMember(ctx, "crypto_key_binding", &kms.CryptoKeyIAMMemberArgs{
			CryptoKeyId: pulumi.String("my-key"),
			Role:        pulumi.String("roles/cloudkms.cryptoKeyEncrypterDecrypter"),
			Member:      pulumi.Sprintf("serviceAccount:service-%v@gcp-sa-sourcemanager.iam.gserviceaccount.com", project.Number),
		})
		if err != nil {
			return err
		}
		_, err = securesourcemanager.NewInstance(ctx, "default", &securesourcemanager.InstanceArgs{
			Location:       pulumi.String("us-central1"),
			InstanceId:     pulumi.String("my-instance"),
			KmsKey:         pulumi.String("my-key"),
			DeletionPolicy: pulumi.String("PREVENT"),
		}, pulumi.DependsOn([]pulumi.Resource{
			cryptoKeyBinding,
		}))
		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 project = Gcp.Organizations.GetProject.Invoke();

    var cryptoKeyBinding = new Gcp.Kms.CryptoKeyIAMMember("crypto_key_binding", new()
    {
        CryptoKeyId = "my-key",
        Role = "roles/cloudkms.cryptoKeyEncrypterDecrypter",
        Member = $"serviceAccount:service-{project.Apply(getProjectResult => getProjectResult.Number)}@gcp-sa-sourcemanager.iam.gserviceaccount.com",
    });

    var @default = new Gcp.SecureSourceManager.Instance("default", new()
    {
        Location = "us-central1",
        InstanceId = "my-instance",
        KmsKey = "my-key",
        DeletionPolicy = "PREVENT",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            cryptoKeyBinding,
        },
    });

});
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.kms.CryptoKeyIAMMember;
import com.pulumi.gcp.kms.CryptoKeyIAMMemberArgs;
import com.pulumi.gcp.securesourcemanager.Instance;
import com.pulumi.gcp.securesourcemanager.InstanceArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var cryptoKeyBinding = new CryptoKeyIAMMember("cryptoKeyBinding", CryptoKeyIAMMemberArgs.builder()
            .cryptoKeyId("my-key")
            .role("roles/cloudkms.cryptoKeyEncrypterDecrypter")
            .member(String.format("serviceAccount:service-%s@gcp-sa-sourcemanager.iam.gserviceaccount.com", project.number()))
            .build());

        var default_ = new Instance("default", InstanceArgs.builder()
            .location("us-central1")
            .instanceId("my-instance")
            .kmsKey("my-key")
            .deletionPolicy("PREVENT")
            .build(), CustomResourceOptions.builder()
                .dependsOn(cryptoKeyBinding)
                .build());

    }
}
resources:
  cryptoKeyBinding:
    type: gcp:kms:CryptoKeyIAMMember
    name: crypto_key_binding
    properties:
      cryptoKeyId: my-key
      role: roles/cloudkms.cryptoKeyEncrypterDecrypter
      member: serviceAccount:service-${project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com
  default:
    type: gcp:securesourcemanager:Instance
    properties:
      location: us-central1
      instanceId: my-instance
      kmsKey: my-key
      deletionPolicy: PREVENT
    options:
      dependsOn:
        - ${cryptoKeyBinding}
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The kmsKey property references a Cloud KMS key for encryption. Before the instance can use the key, the Secure Source Manager service account needs the cryptoKeyEncrypterDecrypter role. The CryptoKeyIAMMember resource grants this permission, and the dependsOn ensures the binding completes before instance creation.

Deploy a private instance with Certificate Authority

Teams that need to isolate source code from the public internet deploy private instances using Private Service Connect.

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

const caPool = new gcp.certificateauthority.CaPool("ca_pool", {
    name: "ca-pool",
    location: "us-central1",
    tier: "ENTERPRISE",
    publishingOptions: {
        publishCaCert: true,
        publishCrl: true,
    },
});
const rootCa = new gcp.certificateauthority.Authority("root_ca", {
    pool: caPool.name,
    certificateAuthorityId: "root-ca",
    location: "us-central1",
    config: {
        subjectConfig: {
            subject: {
                organization: "google",
                commonName: "my-certificate-authority",
            },
        },
        x509Config: {
            caOptions: {
                isCa: true,
            },
            keyUsage: {
                baseKeyUsage: {
                    certSign: true,
                    crlSign: true,
                },
                extendedKeyUsage: {
                    serverAuth: true,
                },
            },
        },
    },
    keySpec: {
        algorithm: "RSA_PKCS1_4096_SHA256",
    },
    deletionProtection: false,
    ignoreActiveCertificatesOnDeletion: true,
    skipGracePeriod: true,
});
const project = gcp.organizations.getProject({});
const caPoolBinding = new gcp.certificateauthority.CaPoolIamBinding("ca_pool_binding", {
    caPool: caPool.id,
    role: "roles/privateca.certificateRequester",
    members: [project.then(project => `serviceAccount:service-${project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com`)],
});
// ca pool IAM permissions can take time to propagate
const wait120Seconds = new time.Sleep("wait_120_seconds", {createDuration: "120s"}, {
    dependsOn: [caPoolBinding],
});
const _default = new gcp.securesourcemanager.Instance("default", {
    instanceId: "my-instance",
    location: "us-central1",
    privateConfig: {
        isPrivate: true,
        caPool: caPool.id,
    },
    deletionPolicy: "PREVENT",
}, {
    dependsOn: [
        rootCa,
        wait120Seconds,
    ],
});
import pulumi
import pulumi_gcp as gcp
import pulumiverse_time as time

ca_pool = gcp.certificateauthority.CaPool("ca_pool",
    name="ca-pool",
    location="us-central1",
    tier="ENTERPRISE",
    publishing_options={
        "publish_ca_cert": True,
        "publish_crl": True,
    })
root_ca = gcp.certificateauthority.Authority("root_ca",
    pool=ca_pool.name,
    certificate_authority_id="root-ca",
    location="us-central1",
    config={
        "subject_config": {
            "subject": {
                "organization": "google",
                "common_name": "my-certificate-authority",
            },
        },
        "x509_config": {
            "ca_options": {
                "is_ca": True,
            },
            "key_usage": {
                "base_key_usage": {
                    "cert_sign": True,
                    "crl_sign": True,
                },
                "extended_key_usage": {
                    "server_auth": True,
                },
            },
        },
    },
    key_spec={
        "algorithm": "RSA_PKCS1_4096_SHA256",
    },
    deletion_protection=False,
    ignore_active_certificates_on_deletion=True,
    skip_grace_period=True)
project = gcp.organizations.get_project()
ca_pool_binding = gcp.certificateauthority.CaPoolIamBinding("ca_pool_binding",
    ca_pool=ca_pool.id,
    role="roles/privateca.certificateRequester",
    members=[f"serviceAccount:service-{project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com"])
# ca pool IAM permissions can take time to propagate
wait120_seconds = time.Sleep("wait_120_seconds", create_duration="120s",
opts = pulumi.ResourceOptions(depends_on=[ca_pool_binding]))
default = gcp.securesourcemanager.Instance("default",
    instance_id="my-instance",
    location="us-central1",
    private_config={
        "is_private": True,
        "ca_pool": ca_pool.id,
    },
    deletion_policy="PREVENT",
    opts = pulumi.ResourceOptions(depends_on=[
            root_ca,
            wait120_seconds,
        ]))
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/certificateauthority"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/securesourcemanager"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
	"github.com/pulumiverse/pulumi-time/sdk/go/time"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		caPool, err := certificateauthority.NewCaPool(ctx, "ca_pool", &certificateauthority.CaPoolArgs{
			Name:     pulumi.String("ca-pool"),
			Location: pulumi.String("us-central1"),
			Tier:     pulumi.String("ENTERPRISE"),
			PublishingOptions: &certificateauthority.CaPoolPublishingOptionsArgs{
				PublishCaCert: pulumi.Bool(true),
				PublishCrl:    pulumi.Bool(true),
			},
		})
		if err != nil {
			return err
		}
		rootCa, err := certificateauthority.NewAuthority(ctx, "root_ca", &certificateauthority.AuthorityArgs{
			Pool:                   caPool.Name,
			CertificateAuthorityId: pulumi.String("root-ca"),
			Location:               pulumi.String("us-central1"),
			Config: &certificateauthority.AuthorityConfigArgs{
				SubjectConfig: &certificateauthority.AuthorityConfigSubjectConfigArgs{
					Subject: &certificateauthority.AuthorityConfigSubjectConfigSubjectArgs{
						Organization: pulumi.String("google"),
						CommonName:   pulumi.String("my-certificate-authority"),
					},
				},
				X509Config: &certificateauthority.AuthorityConfigX509ConfigArgs{
					CaOptions: &certificateauthority.AuthorityConfigX509ConfigCaOptionsArgs{
						IsCa: pulumi.Bool(true),
					},
					KeyUsage: &certificateauthority.AuthorityConfigX509ConfigKeyUsageArgs{
						BaseKeyUsage: &certificateauthority.AuthorityConfigX509ConfigKeyUsageBaseKeyUsageArgs{
							CertSign: pulumi.Bool(true),
							CrlSign:  pulumi.Bool(true),
						},
						ExtendedKeyUsage: &certificateauthority.AuthorityConfigX509ConfigKeyUsageExtendedKeyUsageArgs{
							ServerAuth: pulumi.Bool(true),
						},
					},
				},
			},
			KeySpec: &certificateauthority.AuthorityKeySpecArgs{
				Algorithm: pulumi.String("RSA_PKCS1_4096_SHA256"),
			},
			DeletionProtection:                 pulumi.Bool(false),
			IgnoreActiveCertificatesOnDeletion: pulumi.Bool(true),
			SkipGracePeriod:                    pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		caPoolBinding, err := certificateauthority.NewCaPoolIamBinding(ctx, "ca_pool_binding", &certificateauthority.CaPoolIamBindingArgs{
			CaPool: caPool.ID(),
			Role:   pulumi.String("roles/privateca.certificateRequester"),
			Members: pulumi.StringArray{
				pulumi.Sprintf("serviceAccount:service-%v@gcp-sa-sourcemanager.iam.gserviceaccount.com", project.Number),
			},
		})
		if err != nil {
			return err
		}
		// ca pool IAM permissions can take time to propagate
		wait120Seconds, err := time.NewSleep(ctx, "wait_120_seconds", &time.SleepArgs{
			CreateDuration: pulumi.String("120s"),
		}, pulumi.DependsOn([]pulumi.Resource{
			caPoolBinding,
		}))
		if err != nil {
			return err
		}
		_, err = securesourcemanager.NewInstance(ctx, "default", &securesourcemanager.InstanceArgs{
			InstanceId: pulumi.String("my-instance"),
			Location:   pulumi.String("us-central1"),
			PrivateConfig: &securesourcemanager.InstancePrivateConfigArgs{
				IsPrivate: pulumi.Bool(true),
				CaPool:    caPool.ID(),
			},
			DeletionPolicy: pulumi.String("PREVENT"),
		}, pulumi.DependsOn([]pulumi.Resource{
			rootCa,
			wait120Seconds,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Time = Pulumiverse.Time;

return await Deployment.RunAsync(() => 
{
    var caPool = new Gcp.CertificateAuthority.CaPool("ca_pool", new()
    {
        Name = "ca-pool",
        Location = "us-central1",
        Tier = "ENTERPRISE",
        PublishingOptions = new Gcp.CertificateAuthority.Inputs.CaPoolPublishingOptionsArgs
        {
            PublishCaCert = true,
            PublishCrl = true,
        },
    });

    var rootCa = new Gcp.CertificateAuthority.Authority("root_ca", new()
    {
        Pool = caPool.Name,
        CertificateAuthorityId = "root-ca",
        Location = "us-central1",
        Config = new Gcp.CertificateAuthority.Inputs.AuthorityConfigArgs
        {
            SubjectConfig = new Gcp.CertificateAuthority.Inputs.AuthorityConfigSubjectConfigArgs
            {
                Subject = new Gcp.CertificateAuthority.Inputs.AuthorityConfigSubjectConfigSubjectArgs
                {
                    Organization = "google",
                    CommonName = "my-certificate-authority",
                },
            },
            X509Config = new Gcp.CertificateAuthority.Inputs.AuthorityConfigX509ConfigArgs
            {
                CaOptions = new Gcp.CertificateAuthority.Inputs.AuthorityConfigX509ConfigCaOptionsArgs
                {
                    IsCa = true,
                },
                KeyUsage = new Gcp.CertificateAuthority.Inputs.AuthorityConfigX509ConfigKeyUsageArgs
                {
                    BaseKeyUsage = new Gcp.CertificateAuthority.Inputs.AuthorityConfigX509ConfigKeyUsageBaseKeyUsageArgs
                    {
                        CertSign = true,
                        CrlSign = true,
                    },
                    ExtendedKeyUsage = new Gcp.CertificateAuthority.Inputs.AuthorityConfigX509ConfigKeyUsageExtendedKeyUsageArgs
                    {
                        ServerAuth = true,
                    },
                },
            },
        },
        KeySpec = new Gcp.CertificateAuthority.Inputs.AuthorityKeySpecArgs
        {
            Algorithm = "RSA_PKCS1_4096_SHA256",
        },
        DeletionProtection = false,
        IgnoreActiveCertificatesOnDeletion = true,
        SkipGracePeriod = true,
    });

    var project = Gcp.Organizations.GetProject.Invoke();

    var caPoolBinding = new Gcp.CertificateAuthority.CaPoolIamBinding("ca_pool_binding", new()
    {
        CaPool = caPool.Id,
        Role = "roles/privateca.certificateRequester",
        Members = new[]
        {
            $"serviceAccount:service-{project.Apply(getProjectResult => getProjectResult.Number)}@gcp-sa-sourcemanager.iam.gserviceaccount.com",
        },
    });

    // ca pool IAM permissions can take time to propagate
    var wait120Seconds = new Time.Sleep("wait_120_seconds", new()
    {
        CreateDuration = "120s",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            caPoolBinding,
        },
    });

    var @default = new Gcp.SecureSourceManager.Instance("default", new()
    {
        InstanceId = "my-instance",
        Location = "us-central1",
        PrivateConfig = new Gcp.SecureSourceManager.Inputs.InstancePrivateConfigArgs
        {
            IsPrivate = true,
            CaPool = caPool.Id,
        },
        DeletionPolicy = "PREVENT",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            rootCa,
            wait120Seconds,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.certificateauthority.CaPool;
import com.pulumi.gcp.certificateauthority.CaPoolArgs;
import com.pulumi.gcp.certificateauthority.inputs.CaPoolPublishingOptionsArgs;
import com.pulumi.gcp.certificateauthority.Authority;
import com.pulumi.gcp.certificateauthority.AuthorityArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityConfigArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityConfigSubjectConfigArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityConfigSubjectConfigSubjectArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityConfigX509ConfigArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityConfigX509ConfigCaOptionsArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityConfigX509ConfigKeyUsageArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityConfigX509ConfigKeyUsageBaseKeyUsageArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityConfigX509ConfigKeyUsageExtendedKeyUsageArgs;
import com.pulumi.gcp.certificateauthority.inputs.AuthorityKeySpecArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.certificateauthority.CaPoolIamBinding;
import com.pulumi.gcp.certificateauthority.CaPoolIamBindingArgs;
import com.pulumiverse.time.Sleep;
import com.pulumiverse.time.SleepArgs;
import com.pulumi.gcp.securesourcemanager.Instance;
import com.pulumi.gcp.securesourcemanager.InstanceArgs;
import com.pulumi.gcp.securesourcemanager.inputs.InstancePrivateConfigArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var caPool = new CaPool("caPool", CaPoolArgs.builder()
            .name("ca-pool")
            .location("us-central1")
            .tier("ENTERPRISE")
            .publishingOptions(CaPoolPublishingOptionsArgs.builder()
                .publishCaCert(true)
                .publishCrl(true)
                .build())
            .build());

        var rootCa = new Authority("rootCa", AuthorityArgs.builder()
            .pool(caPool.name())
            .certificateAuthorityId("root-ca")
            .location("us-central1")
            .config(AuthorityConfigArgs.builder()
                .subjectConfig(AuthorityConfigSubjectConfigArgs.builder()
                    .subject(AuthorityConfigSubjectConfigSubjectArgs.builder()
                        .organization("google")
                        .commonName("my-certificate-authority")
                        .build())
                    .build())
                .x509Config(AuthorityConfigX509ConfigArgs.builder()
                    .caOptions(AuthorityConfigX509ConfigCaOptionsArgs.builder()
                        .isCa(true)
                        .build())
                    .keyUsage(AuthorityConfigX509ConfigKeyUsageArgs.builder()
                        .baseKeyUsage(AuthorityConfigX509ConfigKeyUsageBaseKeyUsageArgs.builder()
                            .certSign(true)
                            .crlSign(true)
                            .build())
                        .extendedKeyUsage(AuthorityConfigX509ConfigKeyUsageExtendedKeyUsageArgs.builder()
                            .serverAuth(true)
                            .build())
                        .build())
                    .build())
                .build())
            .keySpec(AuthorityKeySpecArgs.builder()
                .algorithm("RSA_PKCS1_4096_SHA256")
                .build())
            .deletionProtection(false)
            .ignoreActiveCertificatesOnDeletion(true)
            .skipGracePeriod(true)
            .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var caPoolBinding = new CaPoolIamBinding("caPoolBinding", CaPoolIamBindingArgs.builder()
            .caPool(caPool.id())
            .role("roles/privateca.certificateRequester")
            .members(String.format("serviceAccount:service-%s@gcp-sa-sourcemanager.iam.gserviceaccount.com", project.number()))
            .build());

        // ca pool IAM permissions can take time to propagate
        var wait120Seconds = new Sleep("wait120Seconds", SleepArgs.builder()
            .createDuration("120s")
            .build(), CustomResourceOptions.builder()
                .dependsOn(caPoolBinding)
                .build());

        var default_ = new Instance("default", InstanceArgs.builder()
            .instanceId("my-instance")
            .location("us-central1")
            .privateConfig(InstancePrivateConfigArgs.builder()
                .isPrivate(true)
                .caPool(caPool.id())
                .build())
            .deletionPolicy("PREVENT")
            .build(), CustomResourceOptions.builder()
                .dependsOn(                
                    rootCa,
                    wait120Seconds)
                .build());

    }
}
resources:
  caPool:
    type: gcp:certificateauthority:CaPool
    name: ca_pool
    properties:
      name: ca-pool
      location: us-central1
      tier: ENTERPRISE
      publishingOptions:
        publishCaCert: true
        publishCrl: true
  rootCa:
    type: gcp:certificateauthority:Authority
    name: root_ca
    properties:
      pool: ${caPool.name}
      certificateAuthorityId: root-ca
      location: us-central1
      config:
        subjectConfig:
          subject:
            organization: google
            commonName: my-certificate-authority
        x509Config:
          caOptions:
            isCa: true
          keyUsage:
            baseKeyUsage:
              certSign: true
              crlSign: true
            extendedKeyUsage:
              serverAuth: true
      keySpec:
        algorithm: RSA_PKCS1_4096_SHA256
      deletionProtection: false
      ignoreActiveCertificatesOnDeletion: true
      skipGracePeriod: true
  caPoolBinding:
    type: gcp:certificateauthority:CaPoolIamBinding
    name: ca_pool_binding
    properties:
      caPool: ${caPool.id}
      role: roles/privateca.certificateRequester
      members:
        - serviceAccount:service-${project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com
  default:
    type: gcp:securesourcemanager:Instance
    properties:
      instanceId: my-instance
      location: us-central1
      privateConfig:
        isPrivate: true
        caPool: ${caPool.id}
      deletionPolicy: PREVENT
    options:
      dependsOn:
        - ${rootCa}
        - ${wait120Seconds}
  # ca pool IAM permissions can take time to propagate
  wait120Seconds:
    type: time:Sleep
    name: wait_120_seconds
    properties:
      createDuration: 120s
    options:
      dependsOn:
        - ${caPoolBinding}
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The privateConfig block enables private networking by setting isPrivate to true and referencing a Certificate Authority pool. Private instances require a CA pool and root CA for TLS certificate issuance. The example includes a 120-second wait after granting CA pool permissions because IAM bindings can take time to propagate.

Enable third-party identity provider integration

Organizations using external identity providers can enable Workforce Identity Federation to authenticate users without Google accounts.

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

const _default = new gcp.securesourcemanager.Instance("default", {
    location: "us-central1",
    instanceId: "my-instance",
    workforceIdentityFederationConfig: {
        enabled: true,
    },
    deletionPolicy: "PREVENT",
});
import pulumi
import pulumi_gcp as gcp

default = gcp.securesourcemanager.Instance("default",
    location="us-central1",
    instance_id="my-instance",
    workforce_identity_federation_config={
        "enabled": True,
    },
    deletion_policy="PREVENT")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := securesourcemanager.NewInstance(ctx, "default", &securesourcemanager.InstanceArgs{
			Location:   pulumi.String("us-central1"),
			InstanceId: pulumi.String("my-instance"),
			WorkforceIdentityFederationConfig: &securesourcemanager.InstanceWorkforceIdentityFederationConfigArgs{
				Enabled: pulumi.Bool(true),
			},
			DeletionPolicy: pulumi.String("PREVENT"),
		})
		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.SecureSourceManager.Instance("default", new()
    {
        Location = "us-central1",
        InstanceId = "my-instance",
        WorkforceIdentityFederationConfig = new Gcp.SecureSourceManager.Inputs.InstanceWorkforceIdentityFederationConfigArgs
        {
            Enabled = true,
        },
        DeletionPolicy = "PREVENT",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.securesourcemanager.Instance;
import com.pulumi.gcp.securesourcemanager.InstanceArgs;
import com.pulumi.gcp.securesourcemanager.inputs.InstanceWorkforceIdentityFederationConfigArgs;
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 Instance("default", InstanceArgs.builder()
            .location("us-central1")
            .instanceId("my-instance")
            .workforceIdentityFederationConfig(InstanceWorkforceIdentityFederationConfigArgs.builder()
                .enabled(true)
                .build())
            .deletionPolicy("PREVENT")
            .build());

    }
}
resources:
  default:
    type: gcp:securesourcemanager:Instance
    properties:
      location: us-central1
      instanceId: my-instance
      workforceIdentityFederationConfig:
        enabled: true
      deletionPolicy: PREVENT

The workforceIdentityFederationConfig block enables integration with corporate identity systems like Okta or Azure AD. Setting enabled to true allows users to authenticate through their organization’s identity provider instead of requiring Google accounts.

Beyond these examples

These snippets focus on specific instance-level features: basic instance deployment and labeling, customer-managed encryption (CMEK), private networking with Certificate Authority, and workforce identity federation. They’re intentionally minimal rather than full source code management deployments.

The examples may reference pre-existing infrastructure such as Cloud KMS keys and IAM bindings, Certificate Authority pools and root CAs, and VPC networks, subnets, and DNS zones for private instances. They focus on configuring the instance rather than provisioning everything around it.

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

  • Private Service Connect backend configuration (load balancers, network endpoint groups)
  • Private Service Connect endpoint configuration (forwarding rules, DNS records)
  • IAM permissions and service account setup
  • Network topology and firewall rules

These omissions are intentional: the goal is to illustrate how each instance feature is wired, not provide drop-in source management modules. See the Secure Source Manager Instance resource reference for all available configuration options.

Let's deploy GCP Secure Source Manager Instances

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Instance Configuration & Immutability
What properties can't be changed after creating an instance?
The following properties are immutable: instanceId, location, project, kmsKey, privateConfig, and workforceIdentityFederationConfig. Changing any of these requires recreating the instance.
How does deletionPolicy control instance deletion?
deletionPolicy defaults to PREVENT, which blocks accidental deletion by erroring during plan. Set to DELETE to allow deletion, or ABANDON to remove from Pulumi state without deleting the GCP resource.
Encryption & Security
How do I enable customer-managed encryption (CMEK)?
Set kmsKey to your crypto key ID and grant roles/cloudkms.cryptoKeyEncrypterDecrypter to the service account service-PROJECT_NUMBER@gcp-sa-sourcemanager.iam.gserviceaccount.com. Use dependsOn to ensure the IAM binding completes before instance creation.
Private Instances & Networking
How do I create a private Secure Source Manager instance?
Configure privateConfig with isPrivate: true and a CA pool ID. Grant the service account roles/privateca.certificateRequester on the CA pool, then wait 120 seconds for IAM permissions to propagate before creating the instance.
Why do I need to wait 120 seconds when creating a private instance?
CA pool IAM permissions can take time to propagate. The examples use a 120-second wait (via time.Sleep) after granting permissions to prevent instance creation failures.
What's the difference between PSC backend and PSC endpoint configurations?
PSC backend uses an L4 proxy internal load balancer with a network endpoint group for more complex networking scenarios. PSC endpoint uses a simpler forwarding rule that connects directly to the service attachment.
Labels & Metadata
Why aren't all my labels showing in Pulumi state?
The labels field is non-authoritative and only manages labels defined in your configuration. Use the effectiveLabels output to see all labels present on the resource in GCP, including those set by other clients or services.

Using a different cloud?

Explore integration guides for other cloud providers: