☰ All modules Tier 1 · Security and encryption (KMS, Secrets Manager, Parameter Store) GuideCheat sheet ‹ dynamodbadvanced-identity ›
Contents
  1. Encryption models and KMS key types
  2. Key policies grants and cross account access
  3. KMS API operations and the 4 KB limit
  4. Envelope encryption and the Encryption SDK
  5. Request quotas throttling and S3 Bucket Keys
  6. Key rotation deletion and multi Region keys
  7. CloudHSM versus KMS and custom key stores
  8. SSM Parameter Store
  9. Secrets Manager basics and Parameter Store comparison
  10. Secrets Manager rotation and replication
  11. CloudFormation dynamic references and RDS managed secrets
  12. CloudWatch Logs encryption and CodeBuild secrets
  13. Nitro Enclaves and attested KMS requests
  14. Numbers to know
  15. Decision rules
  16. Memory hooks

Security and encryption (KMS, Secrets Manager, Parameter Store) — Cheat Sheet

Verified against AWS documentation on 2026-10-12 · ⚠️ = changed vs older material: learn the value shown here (older practice material may say otherwise; full list in the guide's "Changed vs older material") · ⚠️ unverified = not confirmed in AWS docs, don't rely on it · explanations and examples: notes/security-encryption-guide.md.

Encryption models and KMS key types

Topic Current facts Memory hook
Where to encrypt In transit = TLS; server-side at rest = the service encrypts with a key it may use; client-side = your code encrypts and the service stores only ciphertext Who ever sees the plaintext?
Customer managed key You write the key policy; usable from your code; shareable across accounts; logged in CloudTrail; $1 per key-month; optional rotation Yours to govern
AWS managed key Alias aws/<service>; usable only by that service; policy viewable, not editable; rotates yearly; no monthly fee but requests are billed ⚠️; legacy type since 2021 ⚠️ Borrowed, not owned
AWS owned key Lives in an AWS service account; invisible; free; not in your CloudTrail; doesn't count against your quotas Out of sight
SYMMETRIC_DEFAULT AES-256-GCM; the spec integrated services use; the only spec with automatic rotation and custom key stores The default workhorse
RSA keys RSA_2048/3072/4096; key usage ENCRYPT_DECRYPT or SIGN_VERIFY, chosen once One job per key
ECC keys NIST P-256/384/521 sign/verify or key agreement; secp256k1 and Ed25519 ⚠️ sign/verify only
HMAC keys ⚠️ HMAC_224 to HMAC_512; GenerateMac/VerifyMac; since April 2022 Tags, not ciphertext
ML-DSA keys ⚠️ ML_DSA_44/65/87 post-quantum signing keys since June 2025
Public key use GetPublicKey lets parties without AWS access encrypt or verify offline; the private key never leaves KMS
Key identifiers Key ID, key ARN, alias name, alias ARN; another account's key needs an ARN; alias/aws/ is reserved; multi-Region key IDs start with mrk-
DynamoDB default AWS owned key by default; switchable to aws/dynamodb or a customer managed key at any time

Key policies grants and cross account access

Topic Current facts Memory hook
Key policy basics Exactly one per key, Regional, up to 32 KB, Resource "*", PolicyName "default"; nothing is allowed unless a statement allows it No policy, no access
Default policy (API/CLI) One statement: account principal arn:aws:iam::<account>:root with kms:*, which enables IAM policies Root = the whole account
Default policy (console) Adds key administrators (manage, not use) and key users (crypto operations + grants limited by kms:GrantIsForAWSResource)
IAM vs key policy An IAM allow works only if the key policy delegates to the account; an IAM deny always works
Lockout check PutKeyPolicy rejects a policy that locks out the caller unless BypassPolicyLockoutSafetyCheck = true (default false)
kms:ViaService Allows use only when a named service calls for the principal, value <service>.<region>.amazonaws.com; all AWS managed keys use it Through the service only
Grants Allow only (never deny), one key each, grant token for immediate use, up to 50,000 per key, ended by retire or revoke Temporary permission slip
Cross-account Owner's key policy + caller's IAM policy + key ARN; only crypto, describe and grant operations; the caller's account is throttled Two locks, two keys
Valid principals Accounts, roles, users, sessions, some service principals; * accepted but never without narrowing conditions (AWS warning); IAM groups never

KMS API operations and the 4 KB limit

Operation or error Fact Memory hook
Encrypt Up to 4,096 bytes with a symmetric key; RSA_2048 with OAEP-SHA-256 only 190 bytes The 4 KB door
Decrypt KeyId optional for symmetric ciphertext, required with the algorithm for asymmetric The blob knows its key
ReEncrypt Decrypts and re-encrypts inside KMS; needs kms:ReEncryptFrom (source) and kms:ReEncryptTo (destination) Key swap in the dark
GenerateDataKey Plaintext + encrypted data key; KeySpec AES_256/AES_128 or NumberOfBytes 1–1,024 Envelope maker
GenerateDataKeyWithoutPlaintext Encrypted data key only, for a component that encrypts later Key for later
GenerateRandom 1–1,024 random bytes; no KMS key involved; permission in an IAM policy
Encryption context Exact, case-sensitive match required to decrypt; logged in plaintext in CloudTrail; symmetric keys only Same words to open
InvalidCiphertextException Corrupt ciphertext or an encryption context that differs from the one used to encrypt
IncorrectKeyException The KeyId passed isn't the key that encrypted the ciphertext
DisabledException / KMSInvalidStateException Key disabled / key pending deletion, pending import or unavailable
DryRun Tests permissions without doing the work; an allowed call returns DryRunOperationException
Format mix-up KMS Decrypt can't open Encryption SDK messages, and the SDK can't open raw Encrypt output

Envelope encryption and the Encryption SDK

Topic Current facts Memory hook
Envelope encryption Data key encrypts the data locally; the KMS key encrypts the data key; store the encrypted data key with the ciphertext; wipe the plaintext key Lock the key, not the data
When to use it Any client-side encryption above 4 KB; never chunk data into 4 KB Encrypt calls
Encryption SDK defaults Unique data key per message, AES-GCM + HKDF, key commitment, ECDSA signature, portable message with encrypted data keys in the header
SDK languages ⚠️ C, C#/.NET, Java, JavaScript, Python, Rust, Go, plus the AWS Encryption CLI
Commitment policy Default RequireEncryptRequireDecrypt since version 2.0
Data key caching Caching CMM + local cache (LocalCryptoMaterialsCache); thresholds: max age (required), max messages, max bytes; fewer KMS calls at the cost of key reuse; not in .NET, deprecated in Java 3.x Reuse with a timer
Hierarchical keyring Branch keys in a DynamoDB key store, cached locally; few KMS calls; decrypting needs access to the same key store
Permissions Encrypt needs kms:GenerateDataKey; decrypt needs kms:Decrypt on the wrapping key

Request quotas throttling and S3 Bucket Keys

Topic Current facts Memory hook
Symmetric quota ⚠️ 10,000/s default, 20,000/s in seven large Regions, 100,000/s in us-east-1, us-west-2, eu-west-1; shared by all symmetric crypto operations One bucket of tokens
Asymmetric quotas ⚠️ RSA 1,000/s shared; ECC and SM2 1,000/s shared; ML-DSA 1,000/s
Throttling error ThrottlingException (HTTP 400): backoff with jitter, cache, Bucket Keys, quota increase
Who is throttled The calling account, also for cross-account requests; AWS owned keys never count Caller pays the quota
Service calls count SSE-KMS uploads make S3 call GenerateDataKey, downloads call Decrypt, against your quota
Raising quotas Service Quotas (or Support); every KMS request quota is adjustable except the CloudHSM key store quota
S3 Bucket Keys Bucket-level key derives per-object data keys inside S3; up to 99 % fewer KMS requests; no code change One key per bucket
Bucket Key scope ⚠️ New objects automatically; convert old SSE-S3/SSE-KMS objects in place with UpdateObjectEncryption (ETag and Last-Modified kept), others (unencrypted, SSE-C, DSSE-KMS) by rewriting them as SSE-KMS with CopyObject; Bucket Keys don't work with DSSE-KMS
Bucket Key logs CloudTrail shows the bucket ARN as encryption context and fewer events; update object-ARN policy conditions
SSE-KMS permissions Upload kms:GenerateDataKey; download kms:Decrypt; multipart upload both

Key rotation deletion and multi Region keys

Topic Current facts Memory hook
What rotation does New material for new encryption; old material kept for decryption; same key ID, ARN and policy; no data re-encrypted New lock, same door
Customer managed automatic ⚠️ Optional, off by default; RotationPeriodInDays 90–2,560, default 365; symmetric AWS_KMS keys only
On-demand rotation ⚠️ RotateKeyOnDemand, max 25 per key, not adjustable; schedule unchanged; symmetric incl. imported material 25 tickets
AWS managed rotation ⚠️ Every year (since May 2022); can't be changed or triggered
No KMS rotation Asymmetric, HMAC and custom key store keys: rotate manually with a new key + UpdateAlias
Rotation price ⚠️ First and second rotations add $1/month each; later rotations free
Rotation monitoring GetKeyRotationStatus, ListKeyRotations, CloudTrail RotateKey, EventBridge KMS CMK Rotation
Deletion Customer managed keys only; PendingWindowInDays 7–30, default 30; PendingDeletion blocks use; no monthly fee meanwhile Disable to pause, delete to destroy
Cancel deletion CancelKeyDeletion leaves the key Disabled; call EnableKey
Imported material Symmetric, asymmetric (not ML-DSA), HMAC, multi-Region; you keep the durable copy; expiry or DeleteImportedKeyMaterial
Multi-Region keys ⚠️ Same key ID (mrk-) and material in several Regions; own policy, grants and aliases per Region; can't convert existing keys Same key, many Regions

CloudHSM versus KMS and custom key stores

Topic Current facts Memory hook
CloudHSM Single-tenant HSM cluster in your VPC; AWS runs the hardware; you manage keys and HSM users; AWS can't recover lost credentials Your HSM, your problem
FIPS levels ⚠️ KMS HSMs FIPS 140-3 Level 3; CloudHSM hsm2m.medium FIPS 140-3 Level 3, hsm1.medium FIPS 140-2 Level 3
Cluster mode FIPS or non-FIPS, chosen at creation and fixed; non-FIPS only on hsm2m.medium
Availability At least two HSMs in different AZs for production Two AZs or bust
Pricing CloudHSM per HSM-hour, no upfront fee, no free tier; KMS has a 20,000 requests/month free tier
Custom key store KMS front end over a CloudHSM cluster or an external key manager (XKS); symmetric keys only; no automatic or on-demand rotation, no multi-Region keys, no imported material Control, not speed
Custom key store limits 1,800 requests/s per store; up to 10 stores per account and Region
SSE-C default ⚠️ Disabled by default for new S3 general purpose buckets since April 2026; enable with BlockedEncryptionTypes = NONE

SSM Parameter Store

Topic Current facts Memory hook
Standard tier 10,000 parameters, 4 KB values, no policies, no sharing, no storage charge 4 KB free
Advanced tier 100,000 parameters, 8 KB values, policies, sharing through AWS RAM, $0.05 per parameter-month 8 KB paid
Tier changes Standard → advanced allowed; advanced → standard impossible (delete and recreate) One-way door
Default throughput 40 TPS shared by GetParameter, GetParameters, GetParametersByPath 40 until you pay
Higher throughput GetParameter 10,000 TPS, GetParameters 1,000, GetParametersByPath 100; $0.05 per 10,000 interactions
SecureString standard Parameter Store calls KMS Encrypt directly; writer needs kms:Encrypt
SecureString advanced Envelope encryption with the Encryption SDK; writer needs kms:GenerateDataKey
Reading SecureString WithDecryption=true + kms:Decrypt; encryption context PARAMETER_ARN
Hierarchies Up to 15 levels; GetParametersByPath --recursive, at most 10 per page
Versions and labels 100 versions kept; name:version or name:label; up to 10 labels per version
Parameter policies Advanced only, up to 10: Expiration, ExpirationNotification, NoChangeNotification (EventBridge)
Secrets pass-through /aws/reference/secretsmanager/<id> works with GetParameter/GetParameters only
AL2023 public parameter ⚠️ /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 (Amazon Linux 2 ended 2026-06-30)
Sharing Advanced parameters via AWS RAM, read-only, full ARN; SecureString needs a customer managed key shared too; not usable in dynamic references, CodeBuild or ECS

Secrets Manager basics and Parameter Store comparison

Topic Current facts Memory hook
Secret value SecretString or SecretBinary, up to 65,536 bytes, usually JSON
Encryption Always KMS envelope encryption; aws/secretsmanager or a symmetric customer managed key; context SecretARN + SecretVersionId Always locked
Not encrypted Name, description, tags, rotation settings, KMS key ARN
Staging labels AWSCURRENT (default), AWSPREVIOUS, AWSPENDING; up to 20 labels per secret
ARN suffix Six random characters; a recreated secret with the same name gets a new ARN
Cross-account Secret resource policy + customer managed key (never aws/secretsmanager) + caller IAM policy + full ARN
Deletion Recovery window 7–30 days (default 30) or ForceDeleteWithoutRecovery; reads fail until RestoreSecret
Price $0.40 per secret-month + $0.05 per 10,000 API calls
Caching Client caches for Java, Python, .NET, Go, Rust (Python refreshes hourly); Lambda extension TTL 300 s Cache or pay
Batch reads BatchGetSecretValue up to 20 secrets per call; needs GetSecretValue on each secret
Store choice Configuration and cheap secrets → Parameter Store; rotation, replication, cross-account, RDS → Secrets Manager

Secrets Manager rotation and replication

Topic Current facts Memory hook
Schedule ⚠️ rate() or cron() in UTC; as often as every 4 hours; window at least 1 hour; rate() up to 999 days 4 hours minimum
Managed rotation RDS, Aurora, Redshift, DocumentDB master credentials, ECS Service Connect certificates, managed external secrets; no Lambda
Lambda steps create_secret → set_secret → test_secret → finish_secret Create, set, test, finish
Label moves New value is AWSPENDING; finish_secret moves AWSCURRENT; the old version becomes AWSPREVIOUS
Single user Simplest; open connections survive; brief window of failed new logins
Alternating users Clones the user; needs a superuser secret; always one valid login; not with RDS Proxy Always one valid login
Function permissions DescribeSecret, GetSecretValue, PutSecretValue, UpdateSecretVersionStage, GetRandomPassword + resource policy for secretsmanager.amazonaws.com
Network Rotation function needs a Secrets Manager VPC endpoint or NAT, plus database access No endpoint, no rotation
RotateImmediately Default true; false only runs the testSecret step
RDS managed secret ManageMasterUserPassword; secret rds!…; rotates every 7 days by default; KMS key fixed afterwards
Replication Replica per Region with its own Regional KMS key; rotation in the primary propagates; StopReplicationToReplica promotes

CloudFormation dynamic references and RDS managed secrets

Topic Current facts Memory hook
ssm reference {{resolve:ssm:/name}} or …:version}}; version optional ⚠️; public parameters allowed; no labels or shared parameters
ssm-secure reference {{resolve:ssm-secure:/name}}; only in supported properties (RDS, IAM user, Redshift, ElastiCache passwords) Secure only where allowed
secretsmanager reference {{resolve:secretsmanager:id:SecretString:json-key:stage:version-id}}; almost any property (not custom resources, UserData or AWS::CloudFormation::Init); full ARN for other accounts
Limits Up to 60 dynamic references per template; not in custom resources (secure values), UserData or AWS::CloudFormation::Init
Staleness Values resolve only when the resource is created or updated; secret changes need a stack update Resolved at deploy time only
RDS pattern 1 ManageMasterUserPassword: true (+ MasterUserSecret.KmsKeyId); RDS creates and rotates the secret
RDS pattern 2 GenerateSecretString secret + references + SecretTargetAttachment + RotationSchedule

CloudWatch Logs encryption and CodeBuild secrets

Topic Current facts Memory hook
Logs default Always encrypted at rest with AES-256-GCM service keys
Associate a key create-log-group --kms-key-id <ARN> or associate-kms-key; up to 5 minutes to apply; symmetric keys only CLI for existing groups
Console limit Can't associate a key with an existing log group in the console (create form: ⚠️ unverified)
Key policy Allow logs.<region>.amazonaws.com; scope with kms:EncryptionContext:aws:logs:arn; caller needs kms:DescribeKey
Old data Only new data uses the key; disassociated data still needs the key; disabling the key makes it unreadable
CodeBuild variable types PLAINTEXT (visible), PARAMETER_STORE, SECRETS_MANAGER Plaintext is public
CodeBuild permissions ssm:GetParameters for env/parameter-store; secretsmanager:GetSecretValue for env/secrets-manager
Masking Exact Parameter Store and Secrets Manager values are hidden in logs; transformed values are not
CodeBuild VPC VPC ID, private subnets, security groups; internet access needs a NAT gateway, not an internet gateway

Nitro Enclaves and attested KMS requests

Topic Current facts Memory hook
Enclave Isolated VM from a Nitro instance's vCPUs and memory; no storage, no SSH, no external network; vsock to the parent only A vault inside the server
Launch --enclave-options 'Enabled=true'; up to 4 enclaves per parent; enclave runs Linux; no extra charge
Nitro CLI build-enclave makes the .eif and prints PCRs; run-enclave --cpu-count --memory --eif-path
Measurements PCR0 image, PCR1 kernel, PCR2 application, PCR3 parent IAM role, PCR4 parent instance ID, PCR8 signing certificate
Debug mode --debug-mode gives all-zero PCRs, so attestation policies deny it Debug = zero PCRs
KMS Recipient Decrypt, GenerateDataKey, GenerateDataKeyPair, GenerateRandom, DeriveSharedSecret; response in CiphertextForRecipient
Policy conditions kms:RecipientAttestation:ImageSha384 and kms:RecipientAttestation:PCR<n>

Numbers to know

Item Value Note
Encrypt plaintext, symmetric key 4,096 bytes Larger data → envelope encryption
Encrypt plaintext, RSA_2048 OAEP-SHA-256 190 bytes RSA_4096 SHA-256: 446 bytes
KMS ciphertext blob, maximum 6,144 bytes
GenerateDataKey / GenerateRandom NumberOfBytes 1–1,024 Or KeySpec AES_256 / AES_128 for data keys
Symmetric crypto quota, default 10,000/s ⚠️ Shared by all symmetric cryptographic operations
Symmetric crypto quota, us-east-1 / us-west-2 / eu-west-1 100,000/s ⚠️ 20,000/s in us-east-2, ap-southeast-1/2, ap-northeast-1, eu-central-1, eu-west-2, eu-south-2
RSA and ECC shared quotas 1,000/s each ⚠️ Older material: 500 and 300
Custom key store quota 1,800/s per store CloudHSM key store quota not adjustable
KMS keys per account and Region 100,000 Customer managed keys only
Aliases per KMS key 50 alias/aws/ reserved
Grants per KMS key 50,000 EBS: one grant per attached volume
Key policy size 32 KB One policy per key
Automatic rotation period 90–2,560 days, default 365 ⚠️ Customer managed symmetric keys
On-demand rotations per key 25, not adjustable ⚠️ RotateKeyOnDemand
AWS managed key rotation Every year ⚠️ Older material: every 3 years
Key deletion waiting period 7–30 days, default 30 Up to 24 h later in practice
KMS key price $1 per key-month 1st and 2nd rotations +$1 each ⚠️
KMS request price and free tier $0.03 per 10,000 symmetric requests; 20,000 free per month Asymmetric and GenerateDataKeyPair requests excluded from the free tier
S3 Bucket Keys saving Up to 99 % fewer KMS requests New objects; old ones via UpdateObjectEncryption or CopyObject ⚠️
Encryption SDK cache, max messages per data key Up to 2^32 (default) Max age is required
Parameter Store standard tier 10,000 parameters, 4 KB Free storage
Parameter Store advanced tier 100,000 parameters, 8 KB $0.05 per parameter-month
Parameter policies per advanced parameter 10
Parameter versions retained 100
Parameter hierarchy depth 15 levels
Parameter Store default throughput 40 TPS shared Get APIs
Parameter Store higher throughput, GetParameter 10,000 TPS $0.05 per 10,000 interactions
GetParameters names / GetParametersByPath page 10 / 10
Secrets Manager secret value 65,536 bytes
Secrets Manager price $0.40 per secret-month + $0.05 per 10,000 calls
GetSecretValue quota 10,000/s per Region BatchGetSecretValue: 20 secrets per call
Secret recovery window 7–30 days, default 30 Or ForceDeleteWithoutRecovery
Rotation minimum interval 4 hours ⚠️ Window at least 1 hour
RDS-managed secret rotation Every 7 days by default ManageMasterUserPassword
Lambda extension port / cache TTL 2773 / 300 s (default and maximum) Header X-Aws-Parameters-Secrets-Token
Dynamic references per template 60
CloudWatch Logs key association delay Up to 5 minutes
Nitro enclaves per parent instance 4

Decision rules

Memory hooks