The gcp:secretmanager/regionalSecret:RegionalSecret resource, part of the Pulumi GCP provider, defines the secret container and its configuration within a specific GCP region: encryption, rotation, and lifecycle policies. This guide focuses on four capabilities: regional secret creation with metadata, customer-managed encryption, rotation scheduling, and version lifecycle controls.
Regional secrets are containers that hold configuration but not the actual secret data. Secret values are stored in separate RegionalSecretVersion resources. The examples are intentionally small. Combine them with version resources, IAM policies, and your own KMS keys or Pub/Sub topics.
Create a regional secret with labels and annotations
Most deployments start by creating a secret container in a specific region with organizational metadata.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const regional_secret_basic = new gcp.secretmanager.RegionalSecret("regional-secret-basic", {
secretId: "tf-reg-secret",
location: "us-central1",
labels: {
label: "my-label",
},
annotations: {
key1: "value1",
key2: "value2",
key3: "value3",
},
deletionProtection: false,
});
import pulumi
import pulumi_gcp as gcp
regional_secret_basic = gcp.secretmanager.RegionalSecret("regional-secret-basic",
secret_id="tf-reg-secret",
location="us-central1",
labels={
"label": "my-label",
},
annotations={
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
deletion_protection=False)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := secretmanager.NewRegionalSecret(ctx, "regional-secret-basic", &secretmanager.RegionalSecretArgs{
SecretId: pulumi.String("tf-reg-secret"),
Location: pulumi.String("us-central1"),
Labels: pulumi.StringMap{
"label": pulumi.String("my-label"),
},
Annotations: pulumi.StringMap{
"key1": pulumi.String("value1"),
"key2": pulumi.String("value2"),
"key3": pulumi.String("value3"),
},
DeletionProtection: pulumi.Bool(false),
})
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 regional_secret_basic = new Gcp.SecretManager.RegionalSecret("regional-secret-basic", new()
{
SecretId = "tf-reg-secret",
Location = "us-central1",
Labels =
{
{ "label", "my-label" },
},
Annotations =
{
{ "key1", "value1" },
{ "key2", "value2" },
{ "key3", "value3" },
},
DeletionProtection = false,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.secretmanager.RegionalSecret;
import com.pulumi.gcp.secretmanager.RegionalSecretArgs;
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 regional_secret_basic = new RegionalSecret("regional-secret-basic", RegionalSecretArgs.builder()
.secretId("tf-reg-secret")
.location("us-central1")
.labels(Map.of("label", "my-label"))
.annotations(Map.ofEntries(
Map.entry("key1", "value1"),
Map.entry("key2", "value2"),
Map.entry("key3", "value3")
))
.deletionProtection(false)
.build());
}
}
resources:
regional-secret-basic:
type: gcp:secretmanager:RegionalSecret
properties:
secretId: tf-reg-secret
location: us-central1
labels:
label: my-label
annotations:
key1: value1
key2: value2
key3: value3
deletionProtection: false
The secretId provides a unique identifier within the project, while location pins the secret to a specific region (us-central1 in this example). Labels support resource organization and billing, while annotations store tool-specific metadata without requiring a database. The secret container exists but holds no data until you create a RegionalSecretVersion.
Encrypt secrets with customer-managed KMS keys
Organizations with compliance requirements often control their own encryption keys rather than using Google-managed encryption.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = gcp.organizations.getProject({});
const kms_secret_binding = new gcp.kms.CryptoKeyIAMMember("kms-secret-binding", {
cryptoKeyId: "kms-key",
role: "roles/cloudkms.cryptoKeyEncrypterDecrypter",
member: project.then(project => `serviceAccount:service-${project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com`),
});
const regional_secret_with_cmek = new gcp.secretmanager.RegionalSecret("regional-secret-with-cmek", {
secretId: "tf-reg-secret",
location: "us-central1",
customerManagedEncryption: {
kmsKeyName: "kms-key",
},
}, {
dependsOn: [kms_secret_binding],
});
import pulumi
import pulumi_gcp as gcp
project = gcp.organizations.get_project()
kms_secret_binding = gcp.kms.CryptoKeyIAMMember("kms-secret-binding",
crypto_key_id="kms-key",
role="roles/cloudkms.cryptoKeyEncrypterDecrypter",
member=f"serviceAccount:service-{project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com")
regional_secret_with_cmek = gcp.secretmanager.RegionalSecret("regional-secret-with-cmek",
secret_id="tf-reg-secret",
location="us-central1",
customer_managed_encryption={
"kms_key_name": "kms-key",
},
opts = pulumi.ResourceOptions(depends_on=[kms_secret_binding]))
package main
import (
"fmt"
"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/secretmanager"
"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
}
kms_secret_binding, err := kms.NewCryptoKeyIAMMember(ctx, "kms-secret-binding", &kms.CryptoKeyIAMMemberArgs{
CryptoKeyId: pulumi.String("kms-key"),
Role: pulumi.String("roles/cloudkms.cryptoKeyEncrypterDecrypter"),
Member: pulumi.Sprintf("serviceAccount:service-%v@gcp-sa-secretmanager.iam.gserviceaccount.com", project.Number),
})
if err != nil {
return err
}
_, err = secretmanager.NewRegionalSecret(ctx, "regional-secret-with-cmek", &secretmanager.RegionalSecretArgs{
SecretId: pulumi.String("tf-reg-secret"),
Location: pulumi.String("us-central1"),
CustomerManagedEncryption: &secretmanager.RegionalSecretCustomerManagedEncryptionArgs{
KmsKeyName: pulumi.String("kms-key"),
},
}, pulumi.DependsOn([]pulumi.Resource{
kms_secret_binding,
}))
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 kms_secret_binding = new Gcp.Kms.CryptoKeyIAMMember("kms-secret-binding", new()
{
CryptoKeyId = "kms-key",
Role = "roles/cloudkms.cryptoKeyEncrypterDecrypter",
Member = $"serviceAccount:service-{project.Apply(getProjectResult => getProjectResult.Number)}@gcp-sa-secretmanager.iam.gserviceaccount.com",
});
var regional_secret_with_cmek = new Gcp.SecretManager.RegionalSecret("regional-secret-with-cmek", new()
{
SecretId = "tf-reg-secret",
Location = "us-central1",
CustomerManagedEncryption = new Gcp.SecretManager.Inputs.RegionalSecretCustomerManagedEncryptionArgs
{
KmsKeyName = "kms-key",
},
}, new CustomResourceOptions
{
DependsOn =
{
kms_secret_binding,
},
});
});
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.secretmanager.RegionalSecret;
import com.pulumi.gcp.secretmanager.RegionalSecretArgs;
import com.pulumi.gcp.secretmanager.inputs.RegionalSecretCustomerManagedEncryptionArgs;
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 kms_secret_binding = new CryptoKeyIAMMember("kms-secret-binding", CryptoKeyIAMMemberArgs.builder()
.cryptoKeyId("kms-key")
.role("roles/cloudkms.cryptoKeyEncrypterDecrypter")
.member(String.format("serviceAccount:service-%s@gcp-sa-secretmanager.iam.gserviceaccount.com", project.number()))
.build());
var regional_secret_with_cmek = new RegionalSecret("regional-secret-with-cmek", RegionalSecretArgs.builder()
.secretId("tf-reg-secret")
.location("us-central1")
.customerManagedEncryption(RegionalSecretCustomerManagedEncryptionArgs.builder()
.kmsKeyName("kms-key")
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(kms_secret_binding)
.build());
}
}
resources:
kms-secret-binding:
type: gcp:kms:CryptoKeyIAMMember
properties:
cryptoKeyId: kms-key
role: roles/cloudkms.cryptoKeyEncrypterDecrypter
member: serviceAccount:service-${project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com
regional-secret-with-cmek:
type: gcp:secretmanager:RegionalSecret
properties:
secretId: tf-reg-secret
location: us-central1
customerManagedEncryption:
kmsKeyName: kms-key
options:
dependsOn:
- ${["kms-secret-binding"]}
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The customerManagedEncryption block references a KMS key by name. Before creating the secret, you must grant the Secret Manager service account cryptoKeyEncrypterDecrypter permissions on the KMS key. The dependsOn ensures the IAM binding completes before secret creation.
Schedule automatic rotation notifications
Secrets requiring periodic updates can trigger Pub/Sub notifications at scheduled intervals for external rotation systems.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = gcp.organizations.getProject({});
const topic = new gcp.pubsub.Topic("topic", {name: "tf-topic"});
const secretsManagerAccess = new gcp.pubsub.TopicIAMMember("secrets_manager_access", {
topic: topic.name,
role: "roles/pubsub.publisher",
member: project.then(project => `serviceAccount:service-${project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com`),
});
const regional_secret_with_rotation = new gcp.secretmanager.RegionalSecret("regional-secret-with-rotation", {
secretId: "tf-reg-secret",
location: "us-central1",
topics: [{
name: topic.id,
}],
rotation: {
rotationPeriod: "3600s",
nextRotationTime: "2045-11-30T00:00:00Z",
},
}, {
dependsOn: [secretsManagerAccess],
});
import pulumi
import pulumi_gcp as gcp
project = gcp.organizations.get_project()
topic = gcp.pubsub.Topic("topic", name="tf-topic")
secrets_manager_access = gcp.pubsub.TopicIAMMember("secrets_manager_access",
topic=topic.name,
role="roles/pubsub.publisher",
member=f"serviceAccount:service-{project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com")
regional_secret_with_rotation = gcp.secretmanager.RegionalSecret("regional-secret-with-rotation",
secret_id="tf-reg-secret",
location="us-central1",
topics=[{
"name": topic.id,
}],
rotation={
"rotation_period": "3600s",
"next_rotation_time": "2045-11-30T00:00:00Z",
},
opts = pulumi.ResourceOptions(depends_on=[secrets_manager_access]))
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/pubsub"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
"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
}
topic, err := pubsub.NewTopic(ctx, "topic", &pubsub.TopicArgs{
Name: pulumi.String("tf-topic"),
})
if err != nil {
return err
}
secretsManagerAccess, err := pubsub.NewTopicIAMMember(ctx, "secrets_manager_access", &pubsub.TopicIAMMemberArgs{
Topic: topic.Name,
Role: pulumi.String("roles/pubsub.publisher"),
Member: pulumi.Sprintf("serviceAccount:service-%v@gcp-sa-secretmanager.iam.gserviceaccount.com", project.Number),
})
if err != nil {
return err
}
_, err = secretmanager.NewRegionalSecret(ctx, "regional-secret-with-rotation", &secretmanager.RegionalSecretArgs{
SecretId: pulumi.String("tf-reg-secret"),
Location: pulumi.String("us-central1"),
Topics: secretmanager.RegionalSecretTopicArray{
&secretmanager.RegionalSecretTopicArgs{
Name: topic.ID(),
},
},
Rotation: &secretmanager.RegionalSecretRotationArgs{
RotationPeriod: pulumi.String("3600s"),
NextRotationTime: pulumi.String("2045-11-30T00:00:00Z"),
},
}, pulumi.DependsOn([]pulumi.Resource{
secretsManagerAccess,
}))
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 topic = new Gcp.PubSub.Topic("topic", new()
{
Name = "tf-topic",
});
var secretsManagerAccess = new Gcp.PubSub.TopicIAMMember("secrets_manager_access", new()
{
Topic = topic.Name,
Role = "roles/pubsub.publisher",
Member = $"serviceAccount:service-{project.Apply(getProjectResult => getProjectResult.Number)}@gcp-sa-secretmanager.iam.gserviceaccount.com",
});
var regional_secret_with_rotation = new Gcp.SecretManager.RegionalSecret("regional-secret-with-rotation", new()
{
SecretId = "tf-reg-secret",
Location = "us-central1",
Topics = new[]
{
new Gcp.SecretManager.Inputs.RegionalSecretTopicArgs
{
Name = topic.Id,
},
},
Rotation = new Gcp.SecretManager.Inputs.RegionalSecretRotationArgs
{
RotationPeriod = "3600s",
NextRotationTime = "2045-11-30T00:00:00Z",
},
}, new CustomResourceOptions
{
DependsOn =
{
secretsManagerAccess,
},
});
});
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.pubsub.Topic;
import com.pulumi.gcp.pubsub.TopicArgs;
import com.pulumi.gcp.pubsub.TopicIAMMember;
import com.pulumi.gcp.pubsub.TopicIAMMemberArgs;
import com.pulumi.gcp.secretmanager.RegionalSecret;
import com.pulumi.gcp.secretmanager.RegionalSecretArgs;
import com.pulumi.gcp.secretmanager.inputs.RegionalSecretTopicArgs;
import com.pulumi.gcp.secretmanager.inputs.RegionalSecretRotationArgs;
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 topic = new Topic("topic", TopicArgs.builder()
.name("tf-topic")
.build());
var secretsManagerAccess = new TopicIAMMember("secretsManagerAccess", TopicIAMMemberArgs.builder()
.topic(topic.name())
.role("roles/pubsub.publisher")
.member(String.format("serviceAccount:service-%s@gcp-sa-secretmanager.iam.gserviceaccount.com", project.number()))
.build());
var regional_secret_with_rotation = new RegionalSecret("regional-secret-with-rotation", RegionalSecretArgs.builder()
.secretId("tf-reg-secret")
.location("us-central1")
.topics(RegionalSecretTopicArgs.builder()
.name(topic.id())
.build())
.rotation(RegionalSecretRotationArgs.builder()
.rotationPeriod("3600s")
.nextRotationTime("2045-11-30T00:00:00Z")
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(secretsManagerAccess)
.build());
}
}
resources:
topic:
type: gcp:pubsub:Topic
properties:
name: tf-topic
secretsManagerAccess:
type: gcp:pubsub:TopicIAMMember
name: secrets_manager_access
properties:
topic: ${topic.name}
role: roles/pubsub.publisher
member: serviceAccount:service-${project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com
regional-secret-with-rotation:
type: gcp:secretmanager:RegionalSecret
properties:
secretId: tf-reg-secret
location: us-central1
topics:
- name: ${topic.id}
rotation:
rotationPeriod: 3600s
nextRotationTime: 2045-11-30T00:00:00Z
options:
dependsOn:
- ${secretsManagerAccess}
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The rotation block sets when notifications begin (nextRotationTime) and how often they repeat (rotationPeriod). Secret Manager publishes messages to the configured Pub/Sub topics; your systems subscribe to these topics and perform the actual rotation. The topics array can include up to 10 Pub/Sub topic references.
Set time-to-live for automatic expiration
Temporary secrets like short-lived tokens can expire automatically after a fixed duration.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const regional_secret_with_ttl = new gcp.secretmanager.RegionalSecret("regional-secret-with-ttl", {
secretId: "tf-reg-secret",
location: "us-central1",
labels: {
label: "my-label",
},
annotations: {
key1: "value1",
key2: "value2",
key3: "value3",
},
ttl: "36000s",
});
import pulumi
import pulumi_gcp as gcp
regional_secret_with_ttl = gcp.secretmanager.RegionalSecret("regional-secret-with-ttl",
secret_id="tf-reg-secret",
location="us-central1",
labels={
"label": "my-label",
},
annotations={
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
ttl="36000s")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := secretmanager.NewRegionalSecret(ctx, "regional-secret-with-ttl", &secretmanager.RegionalSecretArgs{
SecretId: pulumi.String("tf-reg-secret"),
Location: pulumi.String("us-central1"),
Labels: pulumi.StringMap{
"label": pulumi.String("my-label"),
},
Annotations: pulumi.StringMap{
"key1": pulumi.String("value1"),
"key2": pulumi.String("value2"),
"key3": pulumi.String("value3"),
},
Ttl: pulumi.String("36000s"),
})
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 regional_secret_with_ttl = new Gcp.SecretManager.RegionalSecret("regional-secret-with-ttl", new()
{
SecretId = "tf-reg-secret",
Location = "us-central1",
Labels =
{
{ "label", "my-label" },
},
Annotations =
{
{ "key1", "value1" },
{ "key2", "value2" },
{ "key3", "value3" },
},
Ttl = "36000s",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.secretmanager.RegionalSecret;
import com.pulumi.gcp.secretmanager.RegionalSecretArgs;
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 regional_secret_with_ttl = new RegionalSecret("regional-secret-with-ttl", RegionalSecretArgs.builder()
.secretId("tf-reg-secret")
.location("us-central1")
.labels(Map.of("label", "my-label"))
.annotations(Map.ofEntries(
Map.entry("key1", "value1"),
Map.entry("key2", "value2"),
Map.entry("key3", "value3")
))
.ttl("36000s")
.build());
}
}
resources:
regional-secret-with-ttl:
type: gcp:secretmanager:RegionalSecret
properties:
secretId: tf-reg-secret
location: us-central1
labels:
label: my-label
annotations:
key1: value1
key2: value2
key3: value3
ttl: 36000s
The ttl property sets a duration from creation time (36000 seconds, or 10 hours). After this period, the secret expires automatically. You can use ttl or expireTime, but not both.
Delay version destruction for recovery windows
Production secrets often need a grace period before permanent deletion to allow recovery from accidental operations.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const regional_secret_with_version_destroy_ttl = new gcp.secretmanager.RegionalSecret("regional-secret-with-version-destroy-ttl", {
secretId: "tf-reg-secret",
location: "us-central1",
labels: {
label: "my-label",
},
annotations: {
key1: "value1",
key2: "value2",
key3: "value3",
},
versionDestroyTtl: "86400s",
});
import pulumi
import pulumi_gcp as gcp
regional_secret_with_version_destroy_ttl = gcp.secretmanager.RegionalSecret("regional-secret-with-version-destroy-ttl",
secret_id="tf-reg-secret",
location="us-central1",
labels={
"label": "my-label",
},
annotations={
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
version_destroy_ttl="86400s")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := secretmanager.NewRegionalSecret(ctx, "regional-secret-with-version-destroy-ttl", &secretmanager.RegionalSecretArgs{
SecretId: pulumi.String("tf-reg-secret"),
Location: pulumi.String("us-central1"),
Labels: pulumi.StringMap{
"label": pulumi.String("my-label"),
},
Annotations: pulumi.StringMap{
"key1": pulumi.String("value1"),
"key2": pulumi.String("value2"),
"key3": pulumi.String("value3"),
},
VersionDestroyTtl: pulumi.String("86400s"),
})
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 regional_secret_with_version_destroy_ttl = new Gcp.SecretManager.RegionalSecret("regional-secret-with-version-destroy-ttl", new()
{
SecretId = "tf-reg-secret",
Location = "us-central1",
Labels =
{
{ "label", "my-label" },
},
Annotations =
{
{ "key1", "value1" },
{ "key2", "value2" },
{ "key3", "value3" },
},
VersionDestroyTtl = "86400s",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.secretmanager.RegionalSecret;
import com.pulumi.gcp.secretmanager.RegionalSecretArgs;
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 regional_secret_with_version_destroy_ttl = new RegionalSecret("regional-secret-with-version-destroy-ttl", RegionalSecretArgs.builder()
.secretId("tf-reg-secret")
.location("us-central1")
.labels(Map.of("label", "my-label"))
.annotations(Map.ofEntries(
Map.entry("key1", "value1"),
Map.entry("key2", "value2"),
Map.entry("key3", "value3")
))
.versionDestroyTtl("86400s")
.build());
}
}
resources:
regional-secret-with-version-destroy-ttl:
type: gcp:secretmanager:RegionalSecret
properties:
secretId: tf-reg-secret
location: us-central1
labels:
label: my-label
annotations:
key1: value1
key2: value2
key3: value3
versionDestroyTtl: 86400s
The versionDestroyTtl property sets a minimum 24-hour delay between destroy requests and actual deletion. During this window, versions enter a disabled state but remain recoverable. This provides a safety net for production secrets.
Beyond these examples
These snippets focus on specific regional secret features: regional secret creation with metadata, customer-managed encryption, and rotation scheduling and version lifecycle. They’re intentionally minimal rather than full secret management solutions.
The examples may reference pre-existing infrastructure such as KMS keys for customer-managed encryption, Pub/Sub topics for rotation notifications, and IAM permissions for Secret Manager service accounts. They focus on configuring the secret container rather than provisioning everything around it.
To keep things focused, common secret patterns are omitted, including:
- Secret version creation and data storage (requires RegionalSecretVersion resource)
- IAM access policies for secret consumers
- Version aliases for stable references
- Expire time for absolute expiration dates (alternative to TTL)
These omissions are intentional: the goal is to illustrate how each regional secret feature is wired, not provide drop-in secret management modules. See the Regional Secret resource reference for all available configuration options.
Let's create GCP Regional Secrets
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Expiration & Lifecycle
ttl or expireTime can be provided. Use ttl for duration-based expiration (e.g., “36000s”) or expireTime for timestamp-based expiration (e.g., “2055-11-30T00:00:00Z”).versionDestroyTtl must be at least 24 hours (86400s). Versions go to a disabled state first, then are destroyed after the TTL expires.versionDestroyTtl to at least “86400s” (24 hours). Versions will be disabled first, then destroyed after the TTL expires.Rotation & Notifications
rotation with rotationPeriod and nextRotationTime, set topics with Pub/Sub topic IDs, and grant the Secret Manager service account roles/pubsub.publisher role. Use dependsOn to ensure IAM binding is created first.topics property must be set to configure rotation. Secret Manager sends Pub/Sub notifications at nextRotationTime.Encryption
customerManagedEncryption.kmsKeyName and ensure the Secret Manager service account has roles/cloudkms.cryptoKeyEncrypterDecrypter role on the KMS key. Use dependsOn to enforce IAM binding creation first.Metadata & Labels
labels and annotations fields are non-authoritative, meaning Pulumi only manages the labels/annotations present in your configuration. To see all labels/annotations on the resource, use the effectiveLabels and effectiveAnnotations output properties.Immutability & Constraints
location, secretId, project, and tags. Changing these requires recreating the resource.[\p{Ll}\p{Lo}][\p{Ll}\p{Lo}\p{N}_-]{0,62}, and have UTF-8 encoding up to 128 bytes. Label values must be 0-63 characters, match [\p{Ll}\p{Lo}\p{N}_-]{0,63}, and have UTF-8 encoding up to 128 bytes. Maximum 64 labels per resource.