Create GCP Regional Secret Versions

The gcp:secretmanager/regionalSecretVersion:RegionalSecretVersion resource, part of the Pulumi GCP provider, stores the actual secret payload as a versioned snapshot within a regional Secret Manager secret. This guide focuses on three capabilities: plaintext and base64-encoded secret storage, version lifecycle management, and deletion policies for infrastructure changes.

Each version belongs to a RegionalSecret parent resource that defines the secret’s identity and location. The examples are intentionally small. Combine them with your own access policies and rotation workflows.

Store plaintext secret data in a version

Most workflows begin by storing sensitive data as a new version of a regional secret.

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

const secret_basic = new gcp.secretmanager.RegionalSecret("secret-basic", {
    secretId: "secret-version",
    location: "us-central1",
});
const regionalSecretVersionBasic = new gcp.secretmanager.RegionalSecretVersion("regional_secret_version_basic", {
    secret: secret_basic.id,
    secretData: "secret-data",
});
import pulumi
import pulumi_gcp as gcp

secret_basic = gcp.secretmanager.RegionalSecret("secret-basic",
    secret_id="secret-version",
    location="us-central1")
regional_secret_version_basic = gcp.secretmanager.RegionalSecretVersion("regional_secret_version_basic",
    secret=secret_basic.id,
    secret_data="secret-data")
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 {
		secret_basic, err := secretmanager.NewRegionalSecret(ctx, "secret-basic", &secretmanager.RegionalSecretArgs{
			SecretId: pulumi.String("secret-version"),
			Location: pulumi.String("us-central1"),
		})
		if err != nil {
			return err
		}
		_, err = secretmanager.NewRegionalSecretVersion(ctx, "regional_secret_version_basic", &secretmanager.RegionalSecretVersionArgs{
			Secret:     secret_basic.ID(),
			SecretData: pulumi.String("secret-data"),
		})
		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 secret_basic = new Gcp.SecretManager.RegionalSecret("secret-basic", new()
    {
        SecretId = "secret-version",
        Location = "us-central1",
    });

    var regionalSecretVersionBasic = new Gcp.SecretManager.RegionalSecretVersion("regional_secret_version_basic", new()
    {
        Secret = secret_basic.Id,
        SecretData = "secret-data",
    });

});
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 com.pulumi.gcp.secretmanager.RegionalSecretVersion;
import com.pulumi.gcp.secretmanager.RegionalSecretVersionArgs;
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 secret_basic = new RegionalSecret("secret-basic", RegionalSecretArgs.builder()
            .secretId("secret-version")
            .location("us-central1")
            .build());

        var regionalSecretVersionBasic = new RegionalSecretVersion("regionalSecretVersionBasic", RegionalSecretVersionArgs.builder()
            .secret(secret_basic.id())
            .secretData("secret-data")
            .build());

    }
}
resources:
  secret-basic:
    type: gcp:secretmanager:RegionalSecret
    properties:
      secretId: secret-version
      location: us-central1
  regionalSecretVersionBasic:
    type: gcp:secretmanager:RegionalSecretVersion
    name: regional_secret_version_basic
    properties:
      secret: ${["secret-basic"].id}
      secretData: secret-data

The secret property references the parent RegionalSecret resource. The secretData property holds the actual payload (API keys, passwords, credentials). Secret Manager creates a new version number automatically; each update to secretData creates a new version rather than modifying the existing one.

Store binary files as base64-encoded secrets

Applications storing certificates or keystores can encode them as base64 and flag the version accordingly.

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

const secret_basic = new gcp.secretmanager.RegionalSecret("secret-basic", {
    secretId: "secret-version",
    location: "us-central1",
});
const regionalSecretVersionBase64 = new gcp.secretmanager.RegionalSecretVersion("regional_secret_version_base64", {
    secret: secret_basic.id,
    secretData: std.filebase64({
        input: "secret-data.pfx",
    }).then(invoke => invoke.result),
    isSecretDataBase64: true,
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std

secret_basic = gcp.secretmanager.RegionalSecret("secret-basic",
    secret_id="secret-version",
    location="us-central1")
regional_secret_version_base64 = gcp.secretmanager.RegionalSecretVersion("regional_secret_version_base64",
    secret=secret_basic.id,
    secret_data=std.filebase64(input="secret-data.pfx").result,
    is_secret_data_base64=True)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
	"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 {
		secret_basic, err := secretmanager.NewRegionalSecret(ctx, "secret-basic", &secretmanager.RegionalSecretArgs{
			SecretId: pulumi.String("secret-version"),
			Location: pulumi.String("us-central1"),
		})
		if err != nil {
			return err
		}
		invokeFilebase64, err := std.Filebase64(ctx, &std.Filebase64Args{
			Input: "secret-data.pfx",
		}, nil)
		if err != nil {
			return err
		}
		_, err = secretmanager.NewRegionalSecretVersion(ctx, "regional_secret_version_base64", &secretmanager.RegionalSecretVersionArgs{
			Secret:             secret_basic.ID(),
			SecretData:         pulumi.String(invokeFilebase64.Result),
			IsSecretDataBase64: pulumi.Bool(true),
		})
		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 secret_basic = new Gcp.SecretManager.RegionalSecret("secret-basic", new()
    {
        SecretId = "secret-version",
        Location = "us-central1",
    });

    var regionalSecretVersionBase64 = new Gcp.SecretManager.RegionalSecretVersion("regional_secret_version_base64", new()
    {
        Secret = secret_basic.Id,
        SecretData = Std.Filebase64.Invoke(new()
        {
            Input = "secret-data.pfx",
        }).Apply(invoke => invoke.Result),
        IsSecretDataBase64 = true,
    });

});
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 com.pulumi.gcp.secretmanager.RegionalSecretVersion;
import com.pulumi.gcp.secretmanager.RegionalSecretVersionArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.Filebase64Args;
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 secret_basic = new RegionalSecret("secret-basic", RegionalSecretArgs.builder()
            .secretId("secret-version")
            .location("us-central1")
            .build());

        var regionalSecretVersionBase64 = new RegionalSecretVersion("regionalSecretVersionBase64", RegionalSecretVersionArgs.builder()
            .secret(secret_basic.id())
            .secretData(StdFunctions.filebase64(Filebase64Args.builder()
                .input("secret-data.pfx")
                .build()).result())
            .isSecretDataBase64(true)
            .build());

    }
}
resources:
  secret-basic:
    type: gcp:secretmanager:RegionalSecret
    properties:
      secretId: secret-version
      location: us-central1
  regionalSecretVersionBase64:
    type: gcp:secretmanager:RegionalSecretVersion
    name: regional_secret_version_base64
    properties:
      secret: ${["secret-basic"].id}
      secretData:
        fn::invoke:
          function: std:filebase64
          arguments:
            input: secret-data.pfx
          return: result
      isSecretDataBase64: true

The isSecretDataBase64 property tells Secret Manager to treat secretData as base64-encoded rather than plaintext. The filebase64 function reads and encodes the file in one step. This approach works for certificates, keystores, or any binary credential that can’t be stored as plaintext.

Create a disabled version for staged rollouts

Teams preparing new credentials often create versions in a disabled state, then enable them during maintenance windows.

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

const secret_basic = new gcp.secretmanager.RegionalSecret("secret-basic", {
    secretId: "secret-version",
    location: "us-central1",
});
const regionalSecretVersionDisabled = new gcp.secretmanager.RegionalSecretVersion("regional_secret_version_disabled", {
    secret: secret_basic.id,
    secretData: "secret-data",
    enabled: false,
});
import pulumi
import pulumi_gcp as gcp

secret_basic = gcp.secretmanager.RegionalSecret("secret-basic",
    secret_id="secret-version",
    location="us-central1")
regional_secret_version_disabled = gcp.secretmanager.RegionalSecretVersion("regional_secret_version_disabled",
    secret=secret_basic.id,
    secret_data="secret-data",
    enabled=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 {
		secret_basic, err := secretmanager.NewRegionalSecret(ctx, "secret-basic", &secretmanager.RegionalSecretArgs{
			SecretId: pulumi.String("secret-version"),
			Location: pulumi.String("us-central1"),
		})
		if err != nil {
			return err
		}
		_, err = secretmanager.NewRegionalSecretVersion(ctx, "regional_secret_version_disabled", &secretmanager.RegionalSecretVersionArgs{
			Secret:     secret_basic.ID(),
			SecretData: pulumi.String("secret-data"),
			Enabled:    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 secret_basic = new Gcp.SecretManager.RegionalSecret("secret-basic", new()
    {
        SecretId = "secret-version",
        Location = "us-central1",
    });

    var regionalSecretVersionDisabled = new Gcp.SecretManager.RegionalSecretVersion("regional_secret_version_disabled", new()
    {
        Secret = secret_basic.Id,
        SecretData = "secret-data",
        Enabled = 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 com.pulumi.gcp.secretmanager.RegionalSecretVersion;
import com.pulumi.gcp.secretmanager.RegionalSecretVersionArgs;
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 secret_basic = new RegionalSecret("secret-basic", RegionalSecretArgs.builder()
            .secretId("secret-version")
            .location("us-central1")
            .build());

        var regionalSecretVersionDisabled = new RegionalSecretVersion("regionalSecretVersionDisabled", RegionalSecretVersionArgs.builder()
            .secret(secret_basic.id())
            .secretData("secret-data")
            .enabled(false)
            .build());

    }
}
resources:
  secret-basic:
    type: gcp:secretmanager:RegionalSecret
    properties:
      secretId: secret-version
      location: us-central1
  regionalSecretVersionDisabled:
    type: gcp:secretmanager:RegionalSecretVersion
    name: regional_secret_version_disabled
    properties:
      secret: ${["secret-basic"].id}
      secretData: secret-data
      enabled: false

The enabled property controls whether applications can access this version. Setting it to false creates the version but prevents retrieval until you flip it to true. This pattern supports credential rotation with minimal downtime: create the new version disabled, update application configuration, then enable the version.

Preserve versions when removing from Pulumi state

Infrastructure migrations sometimes require removing resources from Pulumi without deleting the underlying secret data.

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

const secret_basic = new gcp.secretmanager.RegionalSecret("secret-basic", {
    secretId: "secret-version",
    location: "us-central1",
});
const regionalSecretVersionDeletionPolicy = new gcp.secretmanager.RegionalSecretVersion("regional_secret_version_deletion_policy", {
    secret: secret_basic.id,
    secretData: "secret-data",
    deletionPolicy: "ABANDON",
});
import pulumi
import pulumi_gcp as gcp

secret_basic = gcp.secretmanager.RegionalSecret("secret-basic",
    secret_id="secret-version",
    location="us-central1")
regional_secret_version_deletion_policy = gcp.secretmanager.RegionalSecretVersion("regional_secret_version_deletion_policy",
    secret=secret_basic.id,
    secret_data="secret-data",
    deletion_policy="ABANDON")
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 {
		secret_basic, err := secretmanager.NewRegionalSecret(ctx, "secret-basic", &secretmanager.RegionalSecretArgs{
			SecretId: pulumi.String("secret-version"),
			Location: pulumi.String("us-central1"),
		})
		if err != nil {
			return err
		}
		_, err = secretmanager.NewRegionalSecretVersion(ctx, "regional_secret_version_deletion_policy", &secretmanager.RegionalSecretVersionArgs{
			Secret:         secret_basic.ID(),
			SecretData:     pulumi.String("secret-data"),
			DeletionPolicy: pulumi.String("ABANDON"),
		})
		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 secret_basic = new Gcp.SecretManager.RegionalSecret("secret-basic", new()
    {
        SecretId = "secret-version",
        Location = "us-central1",
    });

    var regionalSecretVersionDeletionPolicy = new Gcp.SecretManager.RegionalSecretVersion("regional_secret_version_deletion_policy", new()
    {
        Secret = secret_basic.Id,
        SecretData = "secret-data",
        DeletionPolicy = "ABANDON",
    });

});
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 com.pulumi.gcp.secretmanager.RegionalSecretVersion;
import com.pulumi.gcp.secretmanager.RegionalSecretVersionArgs;
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 secret_basic = new RegionalSecret("secret-basic", RegionalSecretArgs.builder()
            .secretId("secret-version")
            .location("us-central1")
            .build());

        var regionalSecretVersionDeletionPolicy = new RegionalSecretVersion("regionalSecretVersionDeletionPolicy", RegionalSecretVersionArgs.builder()
            .secret(secret_basic.id())
            .secretData("secret-data")
            .deletionPolicy("ABANDON")
            .build());

    }
}
resources:
  secret-basic:
    type: gcp:secretmanager:RegionalSecret
    properties:
      secretId: secret-version
      location: us-central1
  regionalSecretVersionDeletionPolicy:
    type: gcp:secretmanager:RegionalSecretVersion
    name: regional_secret_version_deletion_policy
    properties:
      secret: ${["secret-basic"].id}
      secretData: secret-data
      deletionPolicy: ABANDON

The deletionPolicy property controls what happens when you remove the version from your Pulumi program. Setting it to ABANDON removes the version from Pulumi state but leaves the secret data intact in GCP. The default DELETE policy destroys the version and its data. The DISABLE policy (not shown) disables the version rather than deleting it.

Beyond these examples

These snippets focus on specific version-level features: plaintext and base64-encoded secret storage, version lifecycle (enabled/disabled states), and deletion policies for state management. They’re intentionally minimal rather than full secret management solutions.

The examples create pre-existing infrastructure inline (the RegionalSecret parent resource). They focus on version configuration rather than access policies or rotation automation.

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

  • Customer-managed encryption keys (customerManagedEncryptions)
  • Version metadata (createTime, destroyTime, version number)
  • DISABLE deletion policy (similar to ABANDON)

These omissions are intentional: the goal is to illustrate how each version feature is wired, not provide drop-in secret management modules. See the Regional Secret Version resource reference for all available configuration options.

Let's create GCP Regional Secret Versions

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Secret Data & Encoding
How do I store binary files like certificates in a secret version?
Set isSecretDataBase64 to true and provide base64-encoded data in secretData. The example shows using filebase64 to encode a .pfx file.
What's the size limit for secret data?
Secret data must be no larger than 64KiB.
Why doesn't my secret data appear in the Pulumi plan output?
The secretData property is marked as sensitive and won’t be displayed in plan or preview output for security reasons. The data is still stored and managed correctly.
Version Lifecycle & Deletion
What happens when I delete a secret version?
By default, the version is permanently deleted. You can change this with deletionPolicy: set to DISABLE to disable the version instead, or ABANDON to leave it in GCP without managing it.
How do I disable a secret version without deleting it?
You can either set enabled to false when creating the version, or use deletionPolicy: "DISABLE" to disable it on deletion.
Immutability & Updates
What properties can't be changed after creating a secret version?
Three properties are immutable: secret (which secret it belongs to), secretData (the actual secret content), and isSecretDataBase64 (encoding flag). To change secret data, create a new version.

Using a different cloud?

Explore security guides for other cloud providers: