Skip to content

AWS Secrets Manager Provider

The AWS Secrets Manager provider integrates with AWS for centralized secret management.

Providerawssm
URIawssm://[AWS_PROFILE@]REGION[?options]
AccessRead and write; secret references are read-only
Best forWorkloads and teams on AWS
AuthenticationStandard AWS SDK credential chain
Build featureawssm
Default storage[prefix/]secretspec/{project}/{profile}/{key}
Terminal window
# Set a secret
$ secretspec set DATABASE_URL --provider awssm://us-east-1
Enter value for DATABASE_URL: postgresql://localhost/mydb
Secret 'DATABASE_URL' saved to awssm (profile: default)
# Run with secrets
$ secretspec run --provider awssm://us-east-1 -- npm start
  • AWS account with Secrets Manager access
  • AWS credentials configured (CLI, environment variables, IAM roles, or SSO)
  • Build with --features awssm

AWS Secrets Manager uses the standard AWS SDK credential chain:

  1. Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
  2. Shared credentials file (~/.aws/credentials)
  3. AWS SSO (aws sso login)
  4. IAM roles (EC2 instance profiles, ECS task roles, Lambda execution roles)

For identities used only to read secrets, such as those running secretspec get, secretspec check, or secretspec run, use a read-only policy. Replace the example region and account ID with your own:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SecretspecBatchFetch",
"Effect": "Allow",
"Action": "secretsmanager:BatchGetSecretValue",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "us-east-1"
}
}
},
{
"Sid": "SecretspecRead",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:secretspec/*"
}
]
}

Identities that run secretspec set also need this statement in the policy’s Statement array:

{
"Sid": "SecretspecWrite",
"Effect": "Allow",
"Action": [
"secretsmanager:CreateSecret",
"secretsmanager:PutSecretValue"
],
"Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:secretspec/*"
}

If you use a prefix such as ?prefix=myteam, adjust the secret ARN in the read and write statements:

arn:aws:secretsmanager:us-east-1:123456789012:secret:myteam/secretspec/*
awssm://[AWS_PROFILE@]REGION[?prefix=PREFIX][&kms_key_id=KEY][&tag.NAME=VALUE...]
  • REGION: AWS region (e.g., us-east-1). If omitted, the SDK default region chain is used.
  • AWS_PROFILE: Optional AWS profile from ~/.aws/credentials. If omitted, the SDK default credential chain is used.
  • PREFIX: Optional root prefix prepended to all secret names. Useful when IAM policies scope access by prefix (e.g., only allow myteam/*).
  • kms_key_id: Optional KMS key (id, ARN, or alias/...) used to encrypt secrets that secretspec creates.
  • tag.NAME=VALUE: Optional tags applied to secrets that secretspec creates. Repeat for multiple tags.

kms_key_id and tag.NAME=VALUE are applied only when secretspec creates a secret (CreateSecret); updating a value (PutSecretValue) accepts neither, and a pre-existing secret keeps the key and tags it was created with. This supports AWS “tag-on-create” guardrails, where an SCP or IAM condition denies CreateSecret unless required aws:RequestTag/* tags (and often a customer-managed key) are present in the same call.

awssm://us-east-1
awssm://production@us-east-1
awssm://us-east-1?prefix=myteam
awssm://prod@us-east-1?kms_key_id=alias/my-key&tag.team=platform&tag.env=prod
awssm

Because guardrail tags and keys usually vary per environment, they are a natural fit for a checked-in provider alias in secretspec.toml:

[providers]
prod = "awssm://prod@us-east-1?kms_key_id=alias/my-key&tag.team=platform&tag.env=prod"

Route secrets through the alias in project configuration:

secretspec.toml
[profiles.production]
DATABASE_URL = { description = "Database URL", providers = ["prod"] }

Secrets are stored as [prefix/]secretspec/{project}/{profile}/{key}.

For example, DATABASE_URL in project myapp and profile production is stored as secretspec/myapp/production/DATABASE_URL. With ?prefix=myteam, it becomes myteam/secretspec/myapp/production/DATABASE_URL.

In SecretSpec 0.21+, reads accept both AWS SecretString and SecretBinary. Writes use SecretString for UTF-8 values and SecretBinary for other bytes. In 0.21+, get and the Rust byte resolution APIs return binary values inline, and run preserves non-UTF-8 bytes on Unix (except NULs). Declare a binary secret with as_path = true when an application needs a file. Text SDK responses and text exports require UTF-8.

A secret’s ref field names an existing secret instead: item is the secret name (or ARN), and the optional field selects one key of a JSON secret value and therefore requires UTF-8. Without field, the whole secret is returned, including SecretBinary bytes in SecretSpec 0.21+. References are read-only in this provider.

[profiles.production]
# Whole secret value
DATABASE_URL = { description = "DB", ref = { item = "prod/database-url" }, providers = ["awssm://us-east-1"] }
# One key of a JSON secret value
DB_PASSWORD = { description = "DB pw", ref = { item = "prod/db-credentials", field = "password" }, providers = ["awssm://us-east-1"] }
Terminal window
# Using environment variables
$ export AWS_ACCESS_KEY_ID=AKIA...
$ export AWS_SECRET_ACCESS_KEY=...
$ export AWS_DEFAULT_REGION=us-east-1
# Run command
$ secretspec run --provider awssm://us-east-1 -- deploy
# Or with IAM roles (no credentials needed)
$ secretspec run --provider awssm://us-east-1 -- deploy

IPC resolution returns an optional opaque revision derived from the full AWS secret ARN, the version ID returned with its value, and the selected JSON field. Rotation changes the revision; a recreated secret has a different ARN. A new version may change the revision even when the selected value is unchanged. SecretSpec also accounts for its own extraction and decoding before returning the logical value’s revision.

The token uses non-secret version metadata, never the secret value. AWS writers must use ClientRequestToken as non-secret metadata, as intended by AWS; a secret-derived version ID cannot satisfy this contract. Missing ARN or version metadata produces an unknown revision.

Both single and batch reads preserve revisions. A SecretSpec cache returns the revision of its cached value, so rotation can remain unobserved until refresh. See resolver revision semantics for task-cache integration and unknown-revision handling.