Overview
TheSecret resource stores sensitive values such as database passwords and API keys in AWS Secrets Manager. Each secret it creates is encrypted with its own Customer Managed Key (CMK), and accepts a generated password, a JSON object of SecretValue references, or a plain string.
Fjall creates these secrets for you inside the database, compute and pattern constructs. Declare one directly when an application needs a credential no other construct owns.
Resource Class
lib/... path is a published subpath of the package. Secrets constructs are not re-exported from the package root, so this import is the only one that compiles.
This page covers using the construct class directly. The scaffolded
fjall/<app>/infrastructure.ts that fjall create app writes never does
that: it imports App and the *Factory symbols from the package root, and
fjall add edits it through the codemod engine. For runtime secrets you set
yourself, use fjall secrets, which writes SSM Parameter
Store SecureStrings rather than Secrets Manager entries.Basic Usage
Generated Password
Prefer this shape. The value is generated inside AWS and never appears in your CDK source, the synthesised template, or any deploy artefact.JSON Secret from Existing Values
UsesecretObjectValue with SecretValue references when the value already lives somewhere secure, such as an SSM SecureString parameter.
Plain String (Escape Hatch)
secretStringValue wins over generateSecretString. Supplying both silently ignores the generator.
Configuration Options
Core Properties
KMS aliases are unique per account and region. If your construct id is not
account-unique (a fixed-name id inside a pattern deployed once per application, for
example), pass an application-scoped
aliasName or the second deployment fails.Secret Value Options (use one)
Importing an Existing Secret
importExisting: true changes the construct’s behaviour: it references the secret by name and creates no CMK, so secretsCustomerManagedKey stays undefined. Every value option is ignored.
Default Features
Every secret the construct creates gets:- KMS encryption with its own Customer Managed Key
- Automatic key and alias creation, alias
cmk/${id} - Key rotation enabled on the CMK
getImport()for cross-stack consumption
CMK Removal Policy
The CMK is minted withprotects: "stack-scoped", which resolves through the env-aware default rather than an unconditional RETAIN:
The 30-day pending window matches Secrets Manager’s own 30-day recovery window, so a secret deleted with its stack stays recoverable for as long as the key does. See KMS Key for the full
protects contract.
Generated Passwords
Excluding Characters
Database Password with Username
API Key Generation
Consuming a Secret from Another Stack
getImport(field?) returns a SecretImport, the shape every Fjall compute construct accepts in its secretsImport map.
The SecretImport Shape
Supply exactly one of
name or arn. Hand-write an import when the secret is managed outside your stack:
Deploy-Time ARN Resolution
resolveImportedSecret(scope, id, secretImport) turns a SecretImport into an ISecret whose ARN carries the AWS 6-character suffix. It resolves in three steps:
- An explicit
arnon the import. - The
fjallResolvedSecretArnscontext map, which@fjall/deploy-corewrites at deploy time after aDescribeSecreton every name. Secret.fromSecretNameV2as an offlinecdk synthfallback.
Integration with Resources
With RDS
Database constructs create and own their credentials secret. Read it withgetCredentials(), which returns the same Secret wrapper.
With ECS
Pass imports through a container’ssecretsImport map. Fjall resolves each one and injects it as an environment variable at task launch.
With Lambda
LambdaFunction takes the same map.
ISecret:
KMS Encryption
Default CMK Creation
Access the CMK
secretsCustomerManagedKey is optional, because a secret created with importExisting: true has no key. Narrow it before use, or strictNullChecks rejects the read.
Secret Rotation
Attach CDK’sSecretRotation to the underlying ISecret. Database constructs do this for you.
Factory Pattern
Secret.build returns a factory that a StackBuilder invokes.
IAM Permissions
Grant Read Access
grantRead also grants kms:Decrypt on the CMK through the Secrets Manager service principal, so no separate key grant is needed.
Custom Permissions
Outputs
The nestedCustomerManagedKey construct emits both CloudFormation outputs. Their names key off the CMK construct id, ${id}CustomerManagedKey, run through toPascalCase. Call that name.
Export names carry the emitting stack’s name as a prefix, because
CloudFormation export names are unique per account and region. The output
key is not prefixed. Build a cross-stack import from
Stack.of(this).stackName, never from the bare ${name}KeyArn string.Secret with id ApiKey in a stack named AcmeApiStorage:
Complete Example
Best Practices
- Generate values in AWS. Reach for
generateSecretStringfirst,SecretValue.ssmSecuresecond,secretStringValuenever. - Inject through
secretsImport, notenvironment. Environment variables land in the task definition in clear text. - Import a single field with
getImport("password")rather than handing a whole JSON blob to a container. - Pass an application-scoped
aliasNamewhenever the construct id repeats across applications in one account and region. - Rotate database credentials on a 30 to 90 day schedule.
- Apply least-privilege IAM. Grant on the exact secret ARN, not a wildcard.
- Separate secrets by purpose so a single grant does not expose unrelated credentials.
- Monitor access with CloudTrail.
Cost
AWS list price,us-east-1:
- $0.40 per secret per month
- $0.05 per 10,000 API calls
- 3 as key rotation mints its first two versions
Cost Saving Tips
Combine related values into one JSON secret rather than minting a secret per field. Each secret carries its own monthly charge and its own CMK.Security Considerations
Least-Privilege Access
Non-Production Key Deletion
Outside production, the CMK resolves toDESTROY. Deleting a staging stack schedules the key for deletion with a 30-day window, after which anything still encrypted with it becomes permanently unreadable. If a secret must survive its stack, create its key separately with protects: "outlives-stack".
Troubleshooting
Next Steps
KMS Key
Configure the customer-managed key that encrypts each secret.
IAM Role
Grant roles least-privilege read access to secrets.
RDS Instance
Manage database credentials with generated secrets.
ECS Cluster
Inject secrets into container tasks with
secretsImport.fjall secrets
Manage application secrets from the CLI in SSM Parameter Store.
Lambda Function
Inject secrets into Lambda handlers at runtime.