AWS Secrets Manager
The AWS Secrets Manager key store persists encryption keys as SecretString values in AWS Secrets Manager, encrypted at rest with AWS KMS. Use it when policy mandates Secrets Manager (rotation, replication, resource-based policies) or when you are using a per-tenant key model where the secret count is small.
What SecretString actually means
SecretString is the JSON field name in Secrets Manager's CreateSecret and GetSecretValue API payloads - it is the UTF-8 text payload of the secret. Secrets Manager always encrypts every secret value at rest with KMS; there is no plaintext option. The companion field SecretBinary exists for non-text payloads, but Tayra always uses SecretString because it stores a Base64-encoded representation of the AES-256 key bytes.
In other words: SecretString is not a security mode you opt into - it is just "here is my secret value, as text." The encryption is implicit and unavoidable, controlled by the KMS key set on the secret (the AWS-managed alias/aws/secretsmanager by default, or your own CMK via KmsKeyId).
Cost - read this first
AWS Secrets Manager bills $0.40 per secret per month + $0.05 per 10,000 API calls. With Tayra's default per-data-subject key model, every customer gets their own encryption key - and therefore their own secret. At 100,000 subjects that is $40,000 per month just for storage, before API calls.
For per-data-subject keys at scale, prefer:
- AWS Parameter Store - free at standard tier, KMS-encrypted, same IAM/CloudTrail story.
- HashiCorp Vault - HSM-backed, fine-grained policies, no per-key billing.
- PostgreSQL - flat per-row cost, hardenable for production.
Use Secrets Manager when:
- You have a per-tenant or per-organization key model (tens or hundreds of secrets, not millions).
- Internal policy requires Secrets Manager over Parameter Store.
- You need built-in automatic rotation, cross-region replication, or resource-based policies that Parameter Store does not provide.
Installation
dotnet add package Tayra.KeyStore.AwsSecretsManagerInstall-Package Tayra.KeyStore.AwsSecretsManagerBasic Setup
The simplest registration uses the default AWS credentials chain (environment, profile, instance profile, IAM role, etc.):
var services = new ServiceCollection();
// Use AWS Secrets Manager with the default AWS credentials chain
services.AddTayra(opts => opts.LicenseKey = licenseKey)
.UseAwsSecretsManagerKeyStore();Configuration Options
var services = new ServiceCollection();
services.AddTayra(opts => opts.LicenseKey = licenseKey)
.UseAwsSecretsManagerKeyStore(options =>
{
// Name prefix for secrets (default: "tayra/"). Trailing '/' added automatically.
options.NamePrefix = "myapp/encryption/keys/";
// Optional custom KMS CMK for encrypting the secret value
// (defaults to alias/aws/secretsmanager when null)
options.KmsKeyId = "alias/my-cmk";
// Optional AWS region override
options.Region = "us-west-2";
// Crypto-shredding: 0 = ForceDeleteWithoutRecovery (recommended for GDPR erasure).
// 7-30 = soft delete with recovery window.
options.RecoveryWindowInDays = 0;
// Optional cross-region replication for HA/DR
options.ReplicaRegions = ["eu-west-1"];
// Retry tuning
options.MaxRetries = 5;
options.RetryBaseDelay = TimeSpan.FromMilliseconds(200);
});Options Reference
| Property | Type | Default | Description |
|---|---|---|---|
NamePrefix | string | "tayra/" | Name prefix for secrets in Secrets Manager. Trailing / is added automatically if missing. |
KmsKeyId | string? | null | Optional custom KMS key ID, ARN, or alias for encrypting the secret value. When null, the AWS-managed key (alias/aws/secretsmanager) is used. |
Region | string? | null | Optional AWS region override. When null, the region from the default credentials chain is used. |
RecoveryWindowInDays | int | 7 | Recovery window for soft-deleted secrets (7-30). Set to 0 for ForceDeleteWithoutRecovery - recommended for crypto-shredding. |
ReplicaRegions | IReadOnlyList<string> | [] | AWS regions to replicate each secret to on creation. Empty by default. |
MaxRetries | int | 3 | Maximum retries for transient errors. |
RetryBaseDelay | TimeSpan | 100ms | Base delay for exponential backoff on retries. |
Pre-configured Client
If you already have an IAmazonSecretsManager (e.g., with assumed-role credentials), pass it directly:
var services = new ServiceCollection();
var smClient = new Amazon.SecretsManager.AmazonSecretsManagerClient(
Amazon.RegionEndpoint.USWest2);
services.AddTayra(opts => opts.LicenseKey = licenseKey)
.UseAwsSecretsManagerKeyStore(smClient, options =>
{
options.NamePrefix = "myapp/encryption/keys/";
});Per-Subject vs Per-Tenant Decision
Tayra's default crypto-shredding model uses one key per data subject. Secrets Manager makes this expensive - pick the model deliberately.
| Model | How | Secret count | Erasure granularity | Cost (monthly storage) |
|---|---|---|---|---|
| Per-data-subject (default) | [DataSubjectId] on a per-user identifier | 1 per user | Per-user GDPR Article 17 | $0.40 × N users |
| Per-tenant / per-organization | [DataSubjectId] on OrgId (with Prefix = "org-") | 1 per tenant | Per-tenant offboarding only | $0.40 × N tenants |
| Tenant-namespaced per-subject | TenantAwareKeyStore decorator wrapping this provider | 1 per tenant × users | Both | $0.40 × N tenants × users |
Recommendation:
- If you need per-user GDPR right-to-be-forgotten → use Parameter Store, HashiCorp Vault, or PostgreSQL, not Secrets Manager.
- If you only need tenant-level isolation (offboard whole orgs) → set
[DataSubjectId]to the org ID. Secrets Manager cost stays trivial. - If you need both → wrap with
TenantAwareKeyStorefrom the Compliance edition; understand the multiplicative cost. - At consumer scale, the cleanest answer is envelope encryption: one master key per org in Secrets Manager + N wrapped DEKs in a cheap data keystore. 15M subjects ≈ $1/mo total.
Crypto-Shredding and the Recovery Window
By default, AWS schedules deleted secrets for permanent removal after a 7-day recovery window. Tayra's default RecoveryWindowInDays = 7 matches this behavior, but it means a "shredded" key can technically be restored within 7 days - which is inconsistent with GDPR Article 17 erasure semantics.
For irreversible crypto-shredding, set RecoveryWindowInDays = 0:
options.RecoveryWindowInDays = 0; // ForceDeleteWithoutRecoveryThis calls DeleteSecret with ForceDeleteWithoutRecovery = true, which permanently destroys the secret immediately. There is no undo. This is the right setting for production crypto-shredding.
TIP
Keep the recovery window for development/staging where accidental deletions are recoverable. Set RecoveryWindowInDays = 0 only in production (or any environment where erasure must be auditable as immediate).
Cross-Region Replication
Secrets Manager can automatically replicate each secret to other AWS regions for high availability or disaster recovery:
options.ReplicaRegions = ["us-west-2", "eu-west-1"];When configured, replicas are created at secret-creation time using the same KMS key (or the AWS-managed key) in each region. There is no replication cost beyond the per-region per-secret storage charge ($0.40/secret/region/month).
Crypto-shredding affects all replicas
Deleting a primary secret automatically deletes all replicas. This is the desired behavior for GDPR - erasure must be global, not local.
NamePrefix Convention
Tayra builds the full secret name as:
{name_prefix}{sanitized_key_id}| Component | Value | Source |
|---|---|---|
name_prefix | tayra/ | NamePrefix option (trailing / added automatically). |
sanitized_key_id | user-123/personal/name | Tayra key identifier with colons (:) converted to slashes (/). |
For a key ID of user-123:personal:name and the default prefix, the secret name is:
tayra/user-123/personal/nameThis naming enables IAM policies scoped to a path-like prefix and ListSecrets filter queries for prefix-based operations.
IAM Policy Requirements
The IAM role or user must have the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:CreateSecret",
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:DeleteSecret",
"secretsmanager:ListSecrets"
],
"Resource": "arn:aws:secretsmanager:*:*:secret:tayra/*"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:Encrypt",
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:*:*:key/*",
"Condition": {
"StringEquals": {
"kms:ViaService": "secretsmanager.*.amazonaws.com"
}
}
}
]
}If you set ReplicaRegions, also grant secretsmanager:ReplicateSecretToRegions and secretsmanager:RemoveRegionsFromReplication.
Least Privilege
Scope the Resource ARN to match your NamePrefix. The example above matches the default tayra/ prefix.
Retry Logic
The Secrets Manager key store includes built-in exponential-backoff retries for transient errors. Defaults: 3 retries, base delay 100ms, doubling each attempt (100ms → 200ms → 400ms). Tune with MaxRetries and RetryBaseDelay.
Service Limits
| Limit | Value | Notes |
|---|---|---|
| Max secrets per region | 500,000 | Soft limit, raisable via AWS Support. |
| Max secret value size | 64 KB | AES-256 keys are 32 bytes - well within. |
| API request rate | Region-specific (DescribeSecret 50 TPS, GetSecretValue 10,000 TPS) | Tayra's in-process key cache means steady-state requests are minimal. |
| Soft delete recovery window | 7-30 days | Or ForceDeleteWithoutRecovery. See above. |
See Also
- AWS Parameter Store - Cheaper alternative for per-subject keys
- Key Stores Overview - Comparison of all providers
- Custom Key Store - Build your own
IKeyStore
