AWS KMS (Key Management Service)¶
1. What is AWS KMS?¶
AWS KMS is a managed cryptographic key service — it creates, stores, rotates, and controls access to encryption keys used across virtually every AWS service. KMS never exposes the raw key material; all cryptographic operations happen inside FIPS 140-2 validated Hardware Security Modules (HSMs).
Without KMS:
Generate key yourself → store in env var or config file →
key visible to anyone with file access → no audit trail → manual rotation
With KMS:
Key lives in HSM → never leaves AWS → you never see raw key material
Every API call: who used which key, when, on what → CloudTrail audit trail
Automatic or on-demand rotation
IAM + Key Policy = fine-grained access control per key
2. KMS Key Types ⭐¶
By Who Manages the Key¶
| Type | Who Creates | Who Manages | Cost | Key Rotation |
|---|---|---|---|---|
| AWS Managed Key | AWS | AWS (auto) | Free | Every 3 years (auto) |
| Customer Managed Key (CMK) | You | You | $1/month | Yearly (configurable) or on-demand |
| AWS Owned Key | AWS | AWS | Free | AWS-managed internally |
AWS Managed Key:
Created automatically when you enable encryption on an AWS service
Example: aws/s3, aws/ebs, aws/rds, aws/secretsmanager
You CANNOT:
→ use it in your own application code
→ set key policy
→ rotate manually
→ share cross-account
Identified by alias: aws/<service>
Customer Managed Key (CMK): ← what the exam focuses on
YOU create and control
Full key policy control
Can use in your application code via API
Can share cross-account
Can import your own key material (BYOK)
Cost: $1/month/key + $0.03/10,000 API calls
AWS Owned Key:
Completely internal to AWS
Multiple accounts share same AWS-owned keys (you can't see them)
Example: some DynamoDB encryption uses AWS-owned keys
Not visible in your account
By Cryptographic Algorithm¶
| Key Type | Algorithms | Use Cases |
|---|---|---|
| Symmetric (default) | AES-256-GCM | Encrypt/decrypt data, envelope encryption, most AWS integrations |
| Asymmetric RSA | RSA 2048/3072/4096 | Encryption (OAEP-SHA1/256), digital signing |
| Asymmetric ECC | P-256, P-384, P-521, secp256k1 | Digital signing, key agreement (no encryption) |
| HMAC | HMAC-SHA-224/256/384/512 | Message authentication codes (MAC) |
Symmetric key (most common):
Same key encrypts AND decrypts
Private — never leaves KMS, never transmitted
All AWS service integrations use symmetric keys
Can only be used for: Encrypt, Decrypt, GenerateDataKey
Asymmetric key:
Public key: downloadable (you can share it freely)
Private key: stays in KMS (never exported)
Use: external party encrypts with your public key → you decrypt with private key in KMS
OR: you sign data with private key → anyone verifies with public key
Can be used for: Encrypt/Decrypt OR Sign/Verify (not both on same key)
HMAC key: [docs.aws.amazon](https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html)
Symmetric but only for MAC generation and verification
Never used for data encryption
3. Key Material Origin¶
Where the cryptographic material actually comes from:
AWS_KMS (default):
KMS generates key material inside its HSMs
Most secure — never leaves HSM boundary
Supports automatic rotation
EXTERNAL (Bring Your Own Key — BYOK):
You generate key material outside AWS → import into KMS
Use case: compliance requiring you retain original key material outside AWS
Automatic rotation NOT supported (you manually import new material)
On-demand rotation: YES (from April 2026 release) [docs.aws.amazon](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)
Deletion: you can delete key material from AWS → key becomes unusable
Responsibility: you manage source key material security
AWS_CLOUDHSM:
Key material generated in YOUR dedicated CloudHSM cluster
For highest compliance requirements (FIPS 140-3 Level 3)
You own and manage the HSM cluster
EXTERNAL_KEY_STORE (XKS):
Key material lives in YOUR on-premises HSM or third-party key manager
KMS proxies to your external key store for cryptographic operations
For air-gapped environments where key material must never touch AWS
4. Key Rotation ⭐¶
Automatic rotation (symmetric CMKs with AWS_KMS origin only): [docs.aws.amazon](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)
Default: ENABLED, rotates yearly (365 days)
Configurable: 90–2,560 days
What rotates: the backing key material (cryptographic secret)
What stays the SAME: key ID, key ARN, alias, key policy
→ Applications need ZERO changes after rotation
How decryption works after rotation: [docs.aws.amazon](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)
Old data encrypted with key material version 1
→ KMS tracks which version encrypted what (via encrypted ciphertext metadata)
→ Automatically uses correct version to decrypt — transparent to caller
Key ID/ARN unchanged → your application just calls Decrypt() as normal
On-demand rotation: [docs.aws.amazon](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)
Available for:
Symmetric CMKs (AWS_KMS origin)
Symmetric CMKs with EXTERNAL origin (BYOK) ← NEW
Symmetric multi-region keys (EXTERNAL origin) ← NEW
Trigger immediately regardless of schedule:
aws kms rotate-key-on-demand --key-id alias/my-key
Automatic rotation NOT supported for: [tocconsulting](https://tocconsulting.fr/best-practices/kms-security)
Asymmetric keys (RSA, ECC) ← manual only
HMAC keys ← manual only
Keys with imported material ← on-demand only (no auto schedule)
AWS managed keys ← AWS rotates these every 3 years
Manual rotation workaround (for unsupported types):
Create a NEW key → update the alias to point to new key
→ Applications using alias: alias/my-key see no change
Old key: kept for decrypting old ciphertext → disable but don't delete
5. Envelope Encryption ⭐¶
The standard pattern for encrypting large data with KMS:
Problem: KMS Encrypt API only accepts up to 4 KB of plaintext
Solution: encrypt the data with a local data key → encrypt the data key with KMS
Envelope Encryption flow:
1. Call KMS GenerateDataKey(KeyId=my-cmk)
→ Returns: PlaintextDataKey (in memory) + EncryptedDataKey (by CMK)
2. Encrypt your data (any size) using PlaintextDataKey locally (AES-256)
3. Store: EncryptedData + EncryptedDataKey together (e.g., in S3 object)
4. IMMEDIATELY discard PlaintextDataKey from memory
To decrypt:
1. Read EncryptedData + EncryptedDataKey from storage
2. Call KMS Decrypt(CiphertextBlob=EncryptedDataKey)
→ Returns: PlaintextDataKey (requires IAM permission + key policy)
3. Decrypt your data locally using PlaintextDataKey
4. IMMEDIATELY discard PlaintextDataKey from memory
Why envelope encryption:
Data never sent to KMS (only the small data key is)
Network transfer of large data avoided
KMS only handles small key material (fast, cheap)
Offline decryption possible (if you already have the data key)
This is exactly what AWS SDK Encryption Client and S3 CSE use
AWS services that use envelope encryption internally:
S3 SSE-KMS: S3 generates data key → encrypts object locally → stores encrypted key in S3
EBS encryption: KMS generates data key → EC2 uses it locally → EBS stores encrypted key
Secrets Manager: KMS-generated data key encrypts the secret value
Lambda env vars: KMS CMK encrypts environment variables
6. Key Policies ⭐¶
Key policies are the primary access control mechanism for KMS keys — IAM policies alone are NOT sufficient; the key policy must also allow access:
# Minimal key policy (every KMS key must have this or similar):
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root" # account root
},
"Action": "kms:*",
"Resource": "*"
}
# This allows IAM policies in this account to control access to this key
# Without this: IAM policies CANNOT grant access to this key, even for account root
# Grant specific IAM role permission to use key:
{
"Sid": "AllowAppEncryption",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/MyAppRole"
},
"Action": ["kms:GenerateDataKey", "kms:Decrypt"],
"Resource": "*"
}
# Grant another AWS account access (cross-account):
{
"Sid": "AllowCrossAccountUse",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-B:root"
},
"Action": ["kms:Decrypt", "kms:GenerateDataKey"],
"Resource": "*"
}
# Account B must ALSO have IAM policy allowing kms:Decrypt — both needed
Key Policy Separation of Duties¶
Key Administrator:
kms:Create*, kms:Describe*, kms:Enable*, kms:List*, kms:Put*,
kms:Update*, kms:Revoke*, kms:Disable*, kms:Delete*, kms:ScheduleKeyDeletion
→ Can manage but typically NOT decrypt data
Key User:
kms:Encrypt, kms:Decrypt, kms:ReEncrypt*, kms:GenerateDataKey*
→ Can use key for crypto but cannot modify key settings
Best practice: different IAM roles for key management vs key usage
7. KMS Key Aliases¶
Human-readable name for a key:
alias/my-production-database-key
alias/my-s3-encryption-key
Benefits:
Application uses alias → key can be rotated (alias updated to new key)
→ No ARN change needed in application config
Commands:
aws kms create-alias --alias-name alias/my-key --target-key-id <key-id>
aws kms update-alias --alias-name alias/my-key --target-key-id <new-key-id>
aws kms delete-alias --alias-name alias/my-key
8. Multi-Region Keys¶
Problem: data encrypted in us-east-1 → want to decrypt in eu-west-1
Standard key: impossible — KMS keys are regional
Multi-region key:
Primary key: us-east-1 (mrk-abc123...)
Replica keys: eu-west-1, ap-southeast-1 (same key ID prefix: mrk-)
→ All replicas are cryptographically identical
→ Ciphertext encrypted in us-east-1 can be decrypted in eu-west-1
→ No need to re-encrypt data when accessing from another region
Use cases:
Global DynamoDB tables: encrypt/decrypt in any region
Disaster recovery: primary fails → decrypt data in DR region
Multi-region active-active: same data served and encrypted across regions
Rotation for multi-region keys: [docs.aws.amazon](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)
Primary key rotated → replicas automatically updated
On-demand rotation propagates to all replica keys
9. AWS KMS + Services Integration¶
S3 (SSE-KMS):
PutObject: S3 generates data key from CMK → encrypts object → stores encrypted key
GetObject: S3 calls KMS Decrypt → gets data key → decrypts object
Bucket key: enable to reduce KMS API calls by 99% (bucket-level data key)
EBS:
Volume encryption at creation: kms:GenerateDataKey → data key → encrypts volume
Snapshot: encrypted with same CMK (or re-encrypt with new CMK)
Cross-account snapshot share: share snapshot → re-encrypt with target account's CMK
RDS:
Enable at database creation (CANNOT encrypt existing unencrypted RDS) [mindmeshacademy](https://www.mindmeshacademy.com/certifications/aws/aws-certified-cloudops-engineer-associate/study-guide/5-2-1-encryption-at-rest-kms-key-types-and-policies)
Workaround: create encrypted snapshot → restore to new encrypted instance
Read replicas: encrypted with same CMK as primary
Cross-region replica: must encrypt with key in destination region
Lambda:
Environment variable encryption: uses aws/lambda or your CMK
Client-side encryption: use KMS to encrypt env vars before upload
Secrets Manager:
Encrypted with aws/secretsmanager (AWS managed) by default
Or specify your CMK for additional control
CloudTrail:
Log file encryption: specify CMK → CloudTrail encrypts log files
Only accounts with access to CMK can read log files
10. KMS Pricing¶
Customer Managed Keys:
$1.00/month per CMK (prorated by the hour)
Free: AWS managed keys (aws/<service>)
API Requests:
Symmetric encrypt/decrypt: $0.03 per 10,000 requests
Asymmetric operations: $0.03–$0.15 per 10,000 requests (varies by algorithm)
Data key generation: $0.03 per 10,000 requests
HMAC: $0.03 per 10,000 requests
Free tier:
20,000 requests/month free
AWS managed key operations: free
S3 Bucket Keys:
Reduce KMS API calls by ~99% (one data key per bucket per hour)
→ Dramatically reduces KMS cost for S3-heavy workloads
Enable: S3 bucket → Properties → Default encryption → Enable Bucket Key
11. Common Mistakes¶
| ❌ Wrong | ✅ Correct |
|---|---|
| IAM policy alone controls KMS key access | KMS requires both key policy AND IAM policy — key policy must enable IAM permissions first |
| Rotating a CMK changes its ARN/ID | Rotation changes only key material — ARN, ID, alias stay the same |
| Old data must be re-encrypted after rotation | KMS transparently decrypts with the correct version — no re-encryption needed |
| Asymmetric keys support automatic rotation | Asymmetric, HMAC, and imported-material keys cannot auto-rotate — manual only |
| KMS Encrypt works on files of any size | KMS Encrypt max = 4 KB — use envelope encryption for larger data |
| Deleting a CMK is reversible immediately | CMK deletion has a 7–30 day waiting period — schedule deletion, then cancel if needed |
| AWS Managed Keys can be used in your app code | AWS Managed Keys cannot be called directly from your application — use CMKs |
| Existing RDS can be encrypted with KMS | Must encrypt at creation — unencrypted RDS: snapshot → copy with encryption → restore |
| --- |
12. Interview Questions Checklist¶
- Three key management types — who creates/manages each? Cost?
- Symmetric vs Asymmetric — which supports automatic rotation?
- What is key rotation? What stays the same after rotation?
- What is envelope encryption? Why is it needed? Walk through the full flow
- What is the KMS Encrypt API size limit? (4 KB)
- Key policy vs IAM policy — which takes precedence? (both required)
- How do you enable cross-account KMS key access?
- EXTERNAL key material — what is BYOK? Does it support auto-rotation?
- How do you encrypt an existing unencrypted RDS instance?
- What is a multi-region key? When do you need one?