Overview
CustomerManagedKey provisions an AWS KMS customer-managed key (CMK) for protecting data at rest. It creates the key and its alias together, turns on automatic rotation, and resolves the key’s removal policy from the required protects prop.
Resource class
CustomerManagedKey, KEY_PROTECTION_SCOPES and the KeyProtectionScope type are exported. The props interface is not, so pass an inline object literal, or type a helper parameter with KeyProtectionScope.
Basic usage
Configuration options
CDK prefixes an alias with
alias/ when the value omits it, so the default alias reaches AWS as alias/cmk/<id>. That is the string aws kms describe-key --key-id expects.
Choosing protects
protects is required and has no default, because the two answers fail in opposite directions and only one of the failures is visible.
"stack-scoped"means everything the key encrypts is deleted along with the stack that created it: an SSM SecureString parameter, a Secrets Manager secret, RDS performance-insights data. The key then follows the same env-aware default as every other Fjall wrapper,RETAINin production,DESTROYeverywhere else."outlives-stack"means at least one encrypted resource survives the stack: an RDS final snapshot, a retained audit bucket, a Backup vault’s recovery points. The key isRETAINin every environment.
An unrecognised
ENVIRONMENT throws at synth rather than guessing, since guessing DESTROY deletes data and guessing RETAIN leaks it. An explicit removalPolicy overrides the table and skips that check entirely.
Default features
EveryCustomerManagedKey includes:
- Automatic rotation:
enableKeyRotationis always on. AWS rotates the backing key material annually. The construct exposes no option to turn it off. - Removal policy: resolved from
protects(see the table above), or taken verbatim from an explicitremovalPolicy. - Pending deletion window: 30 days whenever the key resolves to
DESTROY. The key is disabled immediately and stays recoverable until the window elapses, long enough to cover the 30-day recovery window of a deleted Secrets Manager secret. - Retention marker tag:
fjall:kms:retention, valued with theprotectsscope, on every key that resolves toRETAIN. Tags outlive the stack, so a posture scan can tell a key retained on purpose from one that was forgotten. - Automatic alias: created with the supplied or default name.
- CloudFormation outputs: key ARN and alias ARN, both exported under a stack-scoped name.
Key components
The KMS key
The key alias
Key rotation
Rotation is on for every key the construct creates. No configuration is needed, and there is no prop to disable it. AWS rotates the key material once a year and keeps every previous version, so ciphertext written under an older version stays decryptable. Rotation is billed. See Cost considerations before creating a key per resource.Removal policy
protects decides the policy (see Choosing protects). Pass removalPolicy only to override that, either to keep a non-production key that would otherwise be destroyed, or to destroy one in an environment the library cannot resolve.
RemovalPolicy.DESTROY, from protects or from an explicit override, the construct sets a 30-day pending window. AWS disables the key immediately, then deletes it after the window elapses. You can cancel the deletion during that window to recover the key and any data it protects.
Prefer binding removalPolicy to the policy of the thing being encrypted rather than choosing independently. The CloudTrail construct passes the same storagePolicy to its bucket and its key precisely so the two cannot drift apart.
Outputs
The construct creates two CloudFormation outputs.<Id> below is the construct id run through toPascalCase, which strips the hyphens and underscores CloudFormation rejects in an output key.
Export names are unique per account per region, so a name built only from a construct id collides between two applications that happen to share the id. Prefixing with the emitting stack’s name makes each export globally unique and puts the application name in it.
Build a cross-stack import from the full stack-scoped name:
Common patterns
Database encryption
RDS constructs create their own keys only when you ask for a CMK with theUSE_CMK marker. The storage key is created "outlives-stack" (an RDS stack teardown leaves a final snapshot behind) and the performance-insights key "stack-scoped".
S3 bucket encryption
Secrets Manager integration
TheSecret construct creates its own "stack-scoped" key and exposes it as secretsCustomerManagedKey. The property is undefined when the secret was imported with importExisting: true, since an imported secret keeps the key of the stack that owns it.
EBS volume encryption
Key policies
Default key policy
The default policy grants the account root full access, so IAM policies in the same account govern who can use and administer the key.Granting access
key.key.grant* only for principals the resource grant does not cover:
Cross-account access
Service integration
With Lambda
With CloudWatch Logs
Cost considerations
Pricing
Because rotation is always on, a key that has rotated twice converges on about **1.00, when deciding how many keys an application needs.
Cost optimisation
Share one key across resources with the same lifetime and the same audience.bucketKeyEnabled: true collapses per-object KMS calls into one call per bucket key, cutting request charges by up to 99%.
Cache decrypted values in Lambda outside the handler so a warm invocation skips the KMS call.
Complete example
Best practices
- Pick
protectsfrom the lifetime of the data, not the key. If anything the key encrypts can outlive the stack, pass"outlives-stack". - Separate keys by purpose (data, secrets, logs) so a grant to one audience does not reach another.
- Share a key across resources with the same lifetime to keep the per-key charge down.
- Use aliases so a rotated or replaced key does not require a config change.
- Grant least privilege.
grantDecryptfor readers,grantEncryptDecryptfor writers,grantAdminonly for operators. - Monitor key usage with CloudTrail. Every KMS API call is logged.
- Tag keys for cost allocation and posture scanning.
Security considerations
Key deletion protection
Restricting a key to specific services
Deny every use that does not arrive through the services you expect, so a leaked credential cannot call KMS directly.Troubleshooting
Inspecting a key
Run AWS commands against a connected account with Fjall-minted credentials.fjall target list shows the available targets.
Next Steps
Secrets Manager
Store and rotate secrets encrypted with a customer-managed key.
S3 Bucket
Encrypt object storage at rest with your KMS key.
RDS Aurora
Provision an Aurora cluster with KMS storage and backup encryption.
IAM Role
Grant roles least-privilege encrypt and decrypt permissions.