Manage AWS Secrets Manager Secret Versions

The aws:secretsmanager/secretVersion:SecretVersion resource, part of the Pulumi AWS provider, manages the actual secret value and its version within an existing Secrets Manager secret container. This guide focuses on three capabilities: string secret storage, JSON-encoded key-value pairs, and reading structured secrets.

Secret versions require an existing aws.secretsmanager.Secret resource as the container. The examples are intentionally small. Combine them with your own secret containers and rotation policies.

Store a simple string secret

Most secrets start as plain text values like API keys or passwords that need encryption at rest.

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

const example = new aws.secretsmanager.SecretVersion("example", {
    secretId: exampleAwsSecretsmanagerSecret.id,
    secretString: "example-string-to-protect",
});
import pulumi
import pulumi_aws as aws

example = aws.secretsmanager.SecretVersion("example",
    secret_id=example_aws_secretsmanager_secret["id"],
    secret_string="example-string-to-protect")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/secretsmanager"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := secretsmanager.NewSecretVersion(ctx, "example", &secretsmanager.SecretVersionArgs{
			SecretId:     pulumi.Any(exampleAwsSecretsmanagerSecret.Id),
			SecretString: pulumi.String("example-string-to-protect"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.SecretsManager.SecretVersion("example", new()
    {
        SecretId = exampleAwsSecretsmanagerSecret.Id,
        SecretString = "example-string-to-protect",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.secretsmanager.SecretVersion;
import com.pulumi.aws.secretsmanager.SecretVersionArgs;
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 example = new SecretVersion("example", SecretVersionArgs.builder()
            .secretId(exampleAwsSecretsmanagerSecret.id())
            .secretString("example-string-to-protect")
            .build());

    }
}
resources:
  example:
    type: aws:secretsmanager:SecretVersion
    properties:
      secretId: ${exampleAwsSecretsmanagerSecret.id}
      secretString: example-string-to-protect

The secretId property references the secret container that must already exist. The secretString property holds the value to encrypt. Secrets Manager encrypts the value automatically and assigns it a version ID.

Store structured data as JSON

Applications often need multiple related values grouped together, like database credentials with host, username, and password.

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

const config = new pulumi.Config();
const example = config.getObject<Record<string, string>>("example") || {
    key1: "value1",
    key2: "value2",
};
const exampleSecretVersion = new aws.secretsmanager.SecretVersion("example", {
    secretId: exampleAwsSecretsmanagerSecret.id,
    secretString: JSON.stringify(example),
});
import pulumi
import json
import pulumi_aws as aws

config = pulumi.Config()
example = config.get_object("example")
if example is None:
    example = {
        "key1": "value1",
        "key2": "value2",
    }
example_secret_version = aws.secretsmanager.SecretVersion("example",
    secret_id=example_aws_secretsmanager_secret["id"],
    secret_string=json.dumps(example))
package main

import (
	"encoding/json"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/secretsmanager"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		cfg := config.New(ctx, "")
		example := map[string]interface{}{
			"key1": "value1",
			"key2": "value2",
		}
		if param := cfg.GetObject("example"); param != nil {
			example = param
		}
		tmpJSON0, err := json.Marshal(example)
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		_, err = secretsmanager.NewSecretVersion(ctx, "example", &secretsmanager.SecretVersionArgs{
			SecretId:     pulumi.Any(exampleAwsSecretsmanagerSecret.Id),
			SecretString: pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var config = new Config();
    var example = config.GetObject<Dictionary<string, string>>("example") ?? 
    {
        { "key1", "value1" },
        { "key2", "value2" },
    };
    var exampleSecretVersion = new Aws.SecretsManager.SecretVersion("example", new()
    {
        SecretId = exampleAwsSecretsmanagerSecret.Id,
        SecretString = JsonSerializer.Serialize(example),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.secretsmanager.SecretVersion;
import com.pulumi.aws.secretsmanager.SecretVersionArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 config = ctx.config();
        final var example = config.get("example").orElse(Map.ofEntries(
            Map.entry("key1", "value1"),
            Map.entry("key2", "value2")
        ));
        var exampleSecretVersion = new SecretVersion("exampleSecretVersion", SecretVersionArgs.builder()
            .secretId(exampleAwsSecretsmanagerSecret.id())
            .secretString(serializeJson(
                example))
            .build());

    }
}
configuration:
  # The map here can come from other supported configurations
  # like locals, resource attribute, map() built-in, etc.
  example:
    type: map(string)
    default:
      key1: value1
      key2: value2
resources:
  exampleSecretVersion:
    type: aws:secretsmanager:SecretVersion
    name: example
    properties:
      secretId: ${exampleAwsSecretsmanagerSecret.id}
      secretString:
        fn::toJSON: ${example}

Secrets Manager accepts JSON-encoded strings, allowing you to store multiple key-value pairs in a single secret version. Use JSON.stringify to convert your data structure before passing it to secretString. This keeps related configuration together while maintaining encryption.

Read JSON secrets back into native structures

After storing JSON in a secret, applications need to parse it back into usable data structures.

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

export const example = std.jsondecode({
    input: exampleAwsSecretsmanagerSecretVersion.secretString,
}).then(invoke => invoke.result?.key1);
import pulumi
import pulumi_std as std

pulumi.export("example", std.jsondecode(input=example_aws_secretsmanager_secret_version["secretString"]).result["key1"])
package main

import (
	"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 {
		ctx.Export("example", pulumi.Any(std.Jsondecode(ctx, &std.JsondecodeArgs{
			Input: exampleAwsSecretsmanagerSecretVersion.SecretString,
		}, nil).Result.Key1))
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    return new Dictionary<string, object?>
    {
        ["example"] = Std.Jsondecode.Invoke(new()
        {
            Input = exampleAwsSecretsmanagerSecretVersion.SecretString,
        }).Apply(invoke => invoke.Result?.Key1),
    };
});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.JsondecodeArgs;
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) {
        ctx.export("example", StdFunctions.jsondecode(JsondecodeArgs.builder()
            .input(exampleAwsSecretsmanagerSecretVersion.secretString())
            .build()).result().key1());
    }
}
outputs:
  example:
    fn::invoke:
      function: std:jsondecode
      arguments:
        input: ${exampleAwsSecretsmanagerSecretVersion.secretString}
      return: result.key1

The jsondecode function converts the stored JSON string back into a native map, letting you extract individual values. This complements JSON storage by showing how to retrieve and use the structured data in your application code.

Beyond these examples

These snippets focus on specific secret version features: string and JSON secret storage, and JSON parsing for structured data. They’re intentionally minimal rather than full secrets management solutions.

The examples require pre-existing infrastructure such as the aws.secretsmanager.Secret resource (the secret container itself). They focus on storing and retrieving secret values rather than managing secret metadata or rotation.

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

  • Binary secret storage (secretBinary)
  • Version staging labels (versionStages)
  • Write-only secrets (secretStringWo, secretStringWoVersion)
  • Secret rotation and lifecycle policies

These omissions are intentional: the goal is to illustrate how secret values are stored and retrieved, not provide drop-in secrets management modules. See the SecretVersion resource reference for all available configuration options.

Let's manage AWS Secrets Manager 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

Staging Labels & Lifecycle
Why does my secret version stay active after I delete the resource?
If the AWSCURRENT staging label is present during deletion, it cannot be removed and will keep the secret version active. Move the AWSCURRENT label to another version before or after deleting this resource to fully deprecate the version.
Why am I seeing a perpetual difference with versionStages?
If you configure versionStages, you must include AWSCURRENT when this is the only version or when the label is currently present on this version. Otherwise, Pulumi will show a perpetual difference.
What happens if I don't specify versionStages?
AWS Secrets Manager automatically moves the AWSCURRENT staging label to the new version on creation.
Secret Value Types & Formats
What's the difference between secretString, secretBinary, and secretStringWo?

You must provide exactly one of these three options:

  • secretString: Text data (immutable, stored in state)
  • secretBinary: Binary data encoded as base64 (immutable, stored in state)
  • secretStringWo: Write-only text data (not stored in state after creation)
How do I update a write-only secret value?
Use secretStringWo with secretStringWoVersion. Increment secretStringWoVersion each time you need to update the secretStringWo value to trigger an update.
What format does secretBinary require?
Binary data must be encoded to base64 before passing it to secretBinary.
Working with JSON Secrets
How do I store JSON key-value pairs in a secret?
Use JSON.stringify() to convert your object to a string and pass it to secretString, as shown in the key-value pairs example.
How do I read JSON values back from a secret?
Use std.jsondecode() with the secretString output to parse the JSON back into a native object and access individual keys.

Using a different cloud?

Explore security guides for other cloud providers: