Data Protection Day 1
SCS-C03 · Domain 5 · Data Protection (18%) · Day 1 of 5

AWS KMS foundations: keys, envelopes and key policies

Almost every data protection question ends in KMS. Today: the three kinds of KMS key, how envelope encryption really works, why the key policy is the master control, grants, encryption context, and the key lifecycle from rotation to deletion. Day 2 covers where key material comes from (imported, CloudHSM, external key stores), multi-Region keys and certificates.

Skill 5.2.1 choose KMS and encryption typeSkill 5.3.5 create and manage KMS keys~90 min read + 30 min lab
01

AWS KMS keys and key types

AWS Key Management Service (KMS) creates and guards cryptographic keys inside hardware security modules (FIPS 140-3 validated) and uses them for you. You never see the key material; you only ask KMS to encrypt, decrypt, sign or generate data keys, and every request is checked against policies and logged in CloudTrail. The first choice the exam tests is which kind of key: customer managed, AWS managed or AWS owned.

Concept profile

Customer managed key

often confused with AWS managed key
?What is it?

A KMS key you create, own and fully control: its key policy, grants, rotation, enable/disable state, tags, aliases and deletion.

⚙How does it work?
  • Create it (aws kms create-key), choose key spec and usage.
  • Give it an alias such as alias/payments.
  • Write its key policy: who administers it, who uses it.
  • Point services (S3, EBS, RDS…) or your code at it. Every use appears in CloudTrail.
{ }Structure
Key specUsed for
Symmetric (SYMMETRIC_DEFAULT, AES-256-GCM)Encrypt/decrypt, data keys. What AWS services use. Default.
Asymmetric RSA / ECCEncrypt/decrypt or sign/verify; public key can be downloaded and used outside AWS
HMACGenerateMac / VerifyMac (message integrity, tokens)
Customer managedYou create and own itYou write the key policyRotation: optional, 90–2560 dYou can delete itMonthly fee + per callAWS managedAlias aws/s3, aws/ebs…Policy fixed by AWSRotates every yearOnly that service uses itNo monthly feeAWS ownedLives in an AWS accountYou can't see or audit itNot in your CloudTrailDefault for some servicesFreeMore control (left) ↔ less effort (right). Cross-account sharing needs customer managed.
Pick by how much control you need.
⇄Customer managed key vs AWS managed key
Customer managedAWS managed
AliasYours, e.g. alias/paymentsaws/<service>, e.g. aws/s3
Key policyYou write and change itFixed by AWS; can't edit
Cross-account useYes (key policy + IAM)No
RotationOptional automatic (90–2560 days) or on-demandAutomatic every year
Delete / disableYesNo
CostMonthly fee + requestsNo monthly fee
!Common mistakes the exam tests
  • Choosing an AWS managed key (aws/s3) when another account must decrypt the data: its policy can't be changed, so cross-account access is impossible.
  • Thinking AWS owned keys appear in your CloudTrail. They don't.
  • Using an asymmetric key for S3/EBS encryption: AWS services need symmetric keys.
  • Expecting to export a symmetric key's material. It never leaves KMS.
✓Benefits and use cases
  • Separation of duties: key admins vs key users.
  • Audit every use of sensitive data in CloudTrail.
  • Ability to disable a key to cut off access to data instantly (crypto-shredding by deletion).
Think of it like · a bank vault

KMS is a bank that keeps master keys in a vault and never lets them out.

AWS conceptFamiliar thing
AWS KMS≈The bank with a vault
Customer managed key≈Your own safe in the vault: you set the rules
AWS managed key≈The bank's house safe for one service; you can use it, not change its rules
AWS owned key≈The bank's internal key you never see
CloudTrail≈The vault's visitor log
Real AWS example · create a customer managed key with an alias

Two CLI calls. The key ID in the output is a UUID; the alias is the friendly name your apps use.

$ aws kms create-key --description "Payments data" \
      --key-spec SYMMETRIC_DEFAULT --key-usage ENCRYPT_DECRYPT
{ "KeyMetadata": { "KeyId": "1234abcd-12ab-34cd-56ef-1234567890ab",
    "Arn": "arn:aws:kms:eu-west-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
    "KeyManager": "CUSTOMER", "Origin": "AWS_KMS", "KeyState": "Enabled" } }

$ aws kms create-alias --alias-name alias/payments \
      --target-key-id 1234abcd-12ab-34cd-56ef-1234567890ab

Origin: AWS_KMS means KMS generated the key material. Day 2 covers the other origins (imported, CloudHSM, external key store).

Exam-style scenario

Account A stores reports in S3 encrypted with SSE-KMS using the aws/s3 key. A partner in account B is given access in the bucket policy but gets AccessDenied on GetObject. What should the engineer do?

  1. A. Add account B to the aws/s3 key policy.
  2. B. Re-encrypt the objects with a customer managed key whose key policy allows account B, and give B's role kms:Decrypt on that key ARN.
  3. C. Make the bucket public.
  4. D. Give account B s3:* in the bucket policy.
Show the worked answer

Answer: B

AWS managed keys have fixed key policies that only allow use through the service in the owning account. Cross-account decryption needs a customer managed key that both the key policy and B's IAM policy allow.

Why not the others

  • A: You can't edit an AWS managed key's policy.
  • C: Never; and decryption would still fail.
  • D: S3 permission isn't the problem; KMS is.
How the exam tests this
  • “Another account must decrypt”→ Customer managed key (never aws/…).
  • “Need to audit every key use”→ Customer or AWS managed (not AWS owned).
  • “Sign code / verify outside AWS”→ Asymmetric key.
  • “Encrypt S3/EBS/RDS”→ Symmetric key.
Must remember
  • Three types: customer managed · AWS managed · AWS owned.
  • AWS managed: alias aws/…, fixed policy, yearly rotation, no cross-account.
  • AWS services need symmetric keys.
  • Key material never leaves KMS in plaintext.
02

Envelope encryption and data keys

KMS can encrypt at most 4 KB directly, and sending gigabytes to KMS would be slow. So AWS uses envelope encryption: KMS gives you a fresh data key, you encrypt the data locally with it, and you keep only the encrypted copy of the data key next to the data. To read, you ask KMS to decrypt the small data key. Every AWS service that encrypts with KMS (S3, EBS, RDS, DynamoDB…) works this way behind the scenes.

Concept profile

Envelope encryption

often confused with direct KMS Encrypt
?What is it?

Encrypting data with a data key, then encrypting (wrapping) the data key with a KMS key. The KMS key never touches the bulk data.

⚙How does it work?
  • Call GenerateDataKey: KMS returns the data key in plaintext and encrypted under your KMS key.
  • Encrypt the data locally with the plaintext key, then erase it from memory.
  • Store the encrypted data key with the ciphertext.
  • To decrypt: Decrypt the encrypted data key, then decrypt the data locally.
  • The AWS Encryption SDK does all of this for you.
{ }Structure
KMS key never leaves the KMS HSMs GenerateDataKey Plaintext data key Encrypted data key (CiphertextBlob) Your app encrypts data locally (AES-256-GCM), then throws the plaintext key away Stored together encrypted data + encrypted data key (the "envelope") To read: send the encrypted data key to KMS Decrypt → plaintext key → decrypt locally. Encrypt directly with KMS only for tiny data: up to 4 KB.
Big data stays with you; only the small data key goes to KMS.
⇄Envelope encryption vs direct KMS Encrypt
Envelope encryptionDirect Encrypt
Data sizeAny sizeUp to 4 KB
Where data is encryptedLocally, in your app or the serviceInside KMS
KMS callsOne per data key (can be cached)One per item
Typical useFiles, volumes, databases, S3 objectsSmall secrets, passwords, other keys
APIsGenerateDataKey, DecryptEncrypt, Decrypt
!Common mistakes the exam tests
  • Trying kms:Encrypt on a 10 MB file: fails, over 4 KB.
  • Storing the plaintext data key next to the data instead of the encrypted one.
  • Forgetting that decrypting needs kms:Decrypt on the KMS key, even though you call it with only the encrypted data key (the key ID is embedded in it for symmetric keys).
  • Mixing up GenerateDataKeyWithoutPlaintext (returns only the encrypted key, for later use) with GenerateDataKey.
✓Benefits and use cases
  • Fast: bulk encryption is local and parallel.
  • Fewer KMS calls and lower cost.
  • Re-keying only needs re-encrypting small data keys (ReEncrypt).
Think of it like · a safe-deposit box

The bank doesn't carry your jewellery into the vault; it locks the small box key instead.

AWS conceptFamiliar thing
Data≈Your jewellery
Data key≈The key to your safe-deposit box
Encrypt locally≈Locking the box yourself
Encrypted data key≈The box key sealed in an envelope only the bank's master key opens
KMS Decrypt≈Asking the bank to open the envelope
4 KB limit≈The vault door slot only fits small items
Real AWS example · envelope encryption with the AWS Encryption SDK (Python)

The SDK calls GenerateDataKey, encrypts locally, and stores the encrypted data key inside the output message.

import aws_encryption_sdk
from aws_encryption_sdk import CommitmentPolicy

client = aws_encryption_sdk.EncryptionSDKClient(
    commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
    key_ids=["arn:aws:kms:eu-west-1:111122223333:key/1234abcd-..."])

ciphertext, header = client.encrypt(
    source=open("payroll.csv", "rb").read(),
    key_provider=provider,
    encryption_context={"dept": "hr", "file": "payroll.csv"})
plaintext, _ = client.decrypt(source=ciphertext, key_provider=provider)

Client-side encryption: the data is encrypted before it ever reaches S3 or any other store.

Exam-style scenario

An application must encrypt 200 MB video files with a KMS key before uploading them, and the security team wants the fewest possible KMS calls. What should the developer do?

  1. A. Call kms:Encrypt on each file.
  2. B. Call GenerateDataKey once per file, encrypt the file locally with the plaintext data key, store the encrypted data key with the file, and discard the plaintext key.
  3. C. Split each file into 4 KB chunks and call Encrypt for each.
  4. D. Use an asymmetric key so files can be encrypted locally with the public key.
Show the worked answer

Answer: B

Envelope encryption: one KMS call per file and the bulk encryption happens locally.

Why not the others

  • A: Encrypt only handles up to 4 KB.
  • C: Works in theory but needs ~50,000 calls per file.
  • D: RSA can only encrypt small payloads too; you'd still need a data key.
How the exam tests this
  • “Encrypt data larger than 4 KB with KMS”→ Envelope encryption (GenerateDataKey).
  • “Create a data key now, use later”→ GenerateDataKeyWithoutPlaintext.
  • “Encrypt on the client before upload”→ AWS Encryption SDK / client-side encryption.
  • “Move ciphertext to a new KMS key without exposing plaintext”→ ReEncrypt.
Must remember
  • Direct Encrypt: 4 KB max.
  • GenerateDataKey → plaintext + encrypted data key.
  • Store the encrypted data key with the data.
  • All KMS-integrated services use envelope encryption.
03

Key policies: the master control

KMS is the one place where IAM is not automatically in charge. Every KMS key has exactly one key policy, and nobody, not even the root user, can use the key unless a policy explicitly allows it. IAM policies only count if the key policy lets them, through the well-known statement that trusts the account principal (arn:aws:iam::111122223333:root).

Concept profile

Key policy

often confused with IAM policy
?What is it?

The resource-based policy attached to a KMS key. It is required, and it decides who can manage and use the key, either directly or by enabling IAM policies.

⚙How does it work?
  • The default key policy contains “Enable IAM User Permissions”: Principal = account root, Action = kms:*. This lets IAM policies in that account grant access.
  • Add statements for key administrators (kms:Create*, Put*, Enable*, ScheduleKeyDeletion…) and key users (Encrypt, Decrypt, GenerateDataKey*, ReEncrypt*, DescribeKey).
  • Add kms:CreateGrant with kms:GrantIsForAWSResource so services like EBS can create grants.
  • For cross-account use, allow the other account (or its role) here and give its principals an IAM policy on the key ARN.
{ }Structure
Same account Key policy: Principal = account root "Enable IAM policies" statement IAM policy on the role allows kms:Decrypt now it counts (without the root statement it wouldn't) Cross account (B uses A's key) Account A key policy allows account B (or a role in B) AND Account B IAM policy allows the key ARN aliases don't work across accounts: use the ARN The key policy is the master. IAM can only add permissions if the key policy lets it.
The key policy is the gate. IAM only matters if the gate trusts the account.
⇄Key policy vs IAM policy
Key policyIAM policy
Required?Yes, exactly one per keyNo
Can allow alone?YesOnly if the key policy enables IAM
Can deny?YesYes, even without key policy support
Cross-accountMust name the other account/roleOther account's IAM must also allow the key ARN
ScopeOne key, one RegionMany keys
!Common mistakes the exam tests
  • Removing the account-root statement and leaving no admin: the key becomes unmanageable and needs AWS Support.
  • Giving cross-account access in the key policy only, forgetting the IAM policy in the other account (or vice versa).
  • Using an alias in a cross-account IAM policy or API call: use the full key ARN.
  • Granting kms:* to users. Key users rarely need PutKeyPolicy or ScheduleKeyDeletion.
  • Assuming the root statement means only the root user gets access. It means “this account's IAM decides”.
✓Benefits and use cases
  • Separation of duties between people who manage keys and people who use them.
  • Central control of sensitive data access.
  • Restrict use to specific services with kms:ViaService.
Think of it like · a nightclub with its own door policy

The club's door list overrules what your company badge says.

AWS conceptFamiliar thing
Key policy≈The club's guest list at the door: required
Root (account) statement≈“Anyone the company HR approves may enter”
IAM policy≈Your company HR approval
Cross-account≈A guest from another company: needs the club's list AND their own HR
Unmanageable key≈The club threw away the list and locked the owner out
Real AWS example · key policy with admins, users and service-only use

Admins manage, the app role uses the key only through S3, and IAM stays enabled.

{ "Version": "2012-10-17", "Statement": [
  { "Sid": "EnableIAM", "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::111122223333:root" },
    "Action": "kms:*", "Resource": "*" },
  { "Sid": "KeyAdmins", "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::111122223333:role/KeyAdmin" },
    "Action": ["kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*",
               "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*",
               "kms:TagResource", "kms:UntagResource",
               "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion"],
    "Resource": "*" },
  { "Sid": "AppUsesViaS3Only", "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::111122223333:role/ReportsApp" },
    "Action": ["kms:Decrypt", "kms:GenerateDataKey*"], "Resource": "*",
    "Condition": { "StringEquals": { "kms:ViaService": "s3.eu-west-1.amazonaws.com" } } } ] }

Resource: "*" in a key policy means “this key”. The ViaService condition stops the app role from calling KMS directly to decrypt objects it downloaded some other way.

Exam-style scenario

A new key policy was applied that lists only the DevOps role as administrator. The DevOps role was later deleted. Nobody can now change the key policy or use the key. What does this situation describe, and how is it fixed?

  1. A. Wait 7 days for the policy to reset.
  2. B. The key is unmanageable because no principal is allowed to manage it; contact AWS Support. Prevent this by keeping the account-root statement.
  3. C. The root user can always edit any key policy.
  4. D. Recreate the DevOps role with the same name; it will work automatically.
Show the worked answer

Answer: B

Without the account principal in the key policy and with the only admin gone, no one can manage the key. AWS Support can restore access. (A recreated role has a new principal ID, so it won't match automatically.)

Why not the others

  • A: There is no reset.
  • C: Root has no implicit KMS access.
  • D: Policies store the unique principal ID; the new role doesn't match.
How the exam tests this
  • “IAM policy allows kms:Decrypt but still AccessDenied”→ Key policy lacks the account-root statement (or a Deny).
  • “Cross-account KMS”→ Key policy in A + IAM policy in B, use the key ARN.
  • “Allow use only through one service”→ kms:ViaService.
  • “Key can't be managed by anyone”→ Unmanageable key → AWS Support.
Must remember
  • Every key: exactly one key policy.
  • Root statement = enable IAM policies, not “root user only”.
  • Cross-account = both sides allow; use the ARN.
  • Separate admins from users.
04

Grants and service integration

A grant is a small, temporary permission on one KMS key for one grantee. AWS services use grants all the time: when you attach an encrypted EBS volume, EBS creates a grant so EC2 can decrypt the volume's data key, and retires it later. You can create grants too, for short-lived or very fine-grained access, without editing the key policy.

Concept profile

KMS grant

often confused with key policy statement
?What is it?

A permission object on one KMS key that allows one grantee (a principal or service principal) to perform a listed set of operations, optionally with encryption-context or SourceArn constraints.

⚙How does it work?
  • A principal with kms:CreateGrant creates the grant (operations, grantee, optional retiring principal and constraints).
  • The grantee can use it after it spreads (seconds); a grant token lets it be used immediately.
  • When done, the grant is retired (by the retiring principal) or revoked (by an admin).
  • Grants can only allow; they can't deny.
{ }Structure
1User attaches anencrypted EBS volume2EBS creates agrant: EC2 may Decrypt3Service uses thegrant (no policy edit)4Grant retiredwhen doneGrants: allow only (never deny), one key, one grantee, may take a few seconds to spread (use the grant token).
Services create, use and retire grants for you.
⇄KMS grant vs key policy statement
GrantKey policy statement
LifetimeShort-lived, created/retired by APILong-lived document
Can deny?NoYes
Edits key policy?NoYes
SpreadEventually consistent; grant tokenImmediate
Typical userAWS services (EBS, RDS…), temporary accessAdmins and standing access
!Common mistakes the exam tests
  • Giving kms:CreateGrant broadly: anyone with it can grant any grant operation on the key to anyone (as powerful as PutKeyPolicy).
  • Fix: allow CreateGrant only with kms:GrantIsForAWSResource = true, so only integrated services can create grants for you.
  • Expecting a revoked grant to be usable for a short time: revoke ends it (allow for propagation delay).
  • Trying to grant CreateKey or PutKeyPolicy through a grant: not a grant operation.
✓Benefits and use cases
  • Lets AWS services work with your keys without broad policies.
  • Temporary access that cleans itself up.
  • Fine-grained limits with encryption-context constraints.
Think of it like · a valet ticket

You hand the valet a ticket that lets them drive your car for one job.

AWS conceptFamiliar thing
Grant≈The valet ticket
Grantee≈The valet (the AWS service)
Grant operations≈What the ticket allows: drive, not sell
Grant token≈Showing the ticket stub before the system updates
Retire≈The valet hands the ticket back when finished
Revoke≈You cancel the ticket
Real AWS example · create a grant with an encryption context constraint

The Lambda role may decrypt only data whose context says tenant=acme.

$ aws kms create-grant \
    --key-id arn:aws:kms:eu-west-1:111122223333:key/1234abcd-... \
    --grantee-principal arn:aws:iam::111122223333:role/AcmeExporter \
    --operations Decrypt \
    --constraints EncryptionContextSubset={tenant=acme} \
    --retiring-principal arn:aws:iam::111122223333:role/KeyAdmin
{ "GrantToken": "AQpAM2Rh...", "GrantId": "0c237476b39f8bc4..." }

Use the returned GrantToken in calls made right away; later calls don't need it.

Exam-style scenario

A company wants developers to be able to attach encrypted EBS volumes to EC2 instances, but not to create KMS grants for arbitrary principals. Which key policy statement BEST meets this?

  1. A. Allow kms:CreateGrant to developers with no conditions.
  2. B. Allow kms:CreateGrant to developers with condition kms:GrantIsForAWSResource = true.
  3. C. Deny kms:CreateGrant to everyone.
  4. D. Allow kms:PutKeyPolicy to developers.
Show the worked answer

Answer: B

EBS needs CreateGrant on the user's behalf. The GrantIsForAWSResource condition allows it only when an integrated AWS service makes the call.

Why not the others

  • A: Developers could grant decrypt to anyone.
  • C: EBS attachment would fail.
  • D: Far too powerful.
How the exam tests this
  • “Service needs temporary use of a key”→ Grant (created by the service).
  • “Restrict CreateGrant to AWS services”→ kms:GrantIsForAWSResource.
  • “New grant must work immediately”→ Grant token.
  • “Remove grant access”→ RevokeGrant (admin) / RetireGrant (retiring principal).
Must remember
  • Grant = allow-only, one key, one grantee.
  • CreateGrant is as powerful as PutKeyPolicy.
  • Use GrantIsForAWSResource.
  • Eventual consistency → grant token.
05

Encryption context and KMS condition keys

An encryption context is a set of non-secret key–value pairs you pass when encrypting with a symmetric KMS key. KMS binds it to the ciphertext as additional authenticated data: decrypting needs the exact same context, or it fails. Because the context is written in plain text to CloudTrail, it also tells auditors what was decrypted. Policies can require it.

Concept profile

Encryption context

often confused with secret / password
?What is it?

Key–value pairs (for example {"dept":"hr"}) cryptographically bound to the ciphertext. Must be supplied again to decrypt. Never secret.

⚙How does it work?
  • Your app passes EncryptionContext on Encrypt or GenerateDataKey.
  • KMS binds it to the ciphertext (AAD).
  • Decrypt must pass the same pairs; otherwise InvalidCiphertextException.
  • CloudTrail logs the context; key policies can check it with kms:EncryptionContext:<key> or kms:EncryptionContextKeys.
  • Many AWS services set one automatically (e.g. S3 uses the bucket/object ARN, EBS the volume ID).
{ }Structure
Encrypt context: {"dept":"hr","file":"pay.csv"} Decrypt, same context ✓ works Decrypt, other context ✗ InvalidCiphertextException Not secret: it is written in plain text in CloudTrail, so it tells auditors what was decrypted. Policies can require it: kms:EncryptionContext:dept = hr
Bound to the ciphertext, visible in logs, checkable in policies.
⇄Encryption context vs secret / password
Encryption contextA secret
Confidential?No; logged in plain textYes
PurposeIntegrity + audit + access conditionAuthentication
Must match to decrypt?Yes, exactlyn/a
Put sensitive data in it?NeverYes
!Common mistakes the exam tests
  • Putting personal data or passwords in the context: it appears in CloudTrail.
  • Assuming context works with asymmetric keys: it's for symmetric encryption keys.
  • Using kms:EncryptionContext: conditions without considering that AWS services set their own context.
  • Thinking the context encrypts anything by itself.
✓Benefits and use cases
  • Multi-tenant isolation: tenant ID in the context + policy condition.
  • Clear audit trail of which record was decrypted.
  • Stop ciphertext from one record being swapped into another.

Other KMS condition keys the exam likes

Condition keyUse it to…
kms:ViaServiceAllow use only when the request comes through a service, e.g. s3.eu-west-1.amazonaws.com
kms:CallerAccountAllow every principal in an account (often with ViaService, as AWS managed keys do)
kms:EncryptionContext:<key> / kms:EncryptionContextKeysRequire a context key–value pair or key
kms:GrantIsForAWSResourceOnly integrated services may create grants
kms:ResourceAliases / aws:ResourceTagABAC for KMS: control access by alias or tag
kms:RotationPeriodInDaysForce a rotation period (90–2560 days allowed)
Think of it like · a labelled sealed envelope

The label isn't secret, but the envelope only opens if you read the label back correctly.

AWS conceptFamiliar thing
Encryption context≈The label on the sealed envelope: “HR – payroll”
AAD binding≈The seal is made with the label, so changing the label breaks it
Decrypt with same context≈Reading the label back exactly
CloudTrail≈The mailroom log showing which labelled envelope was opened
Policy condition≈“HR staff may only open envelopes labelled HR”
Real AWS example · require a tenant context per role

Each tenant's role can only decrypt data encrypted with its own tenant ID in the context.

{ "Sid": "TenantIsolation", "Effect": "Allow",
  "Principal": { "AWS": "arn:aws:iam::111122223333:role/TenantWorker" },
  "Action": ["kms:Decrypt", "kms:GenerateDataKey"],
  "Resource": "*",
  "Condition": { "StringEquals": {
     "kms:EncryptionContext:tenant": "${aws:PrincipalTag/tenant}" } } }

ABAC (IAM Day 5) meets KMS: the session tag decides which context the worker may use.

Exam-style scenario

Auditors need CloudTrail to show which customer record was decrypted each time the application calls KMS, without logging any personal data. What should the developer do?

  1. A. Log the plaintext in CloudWatch.
  2. B. Pass an encryption context containing a non-sensitive record ID (for example {"recordId":"r-8812"}) on encrypt and decrypt.
  3. C. Use a different KMS key per record.
  4. D. Enable S3 server access logging.
Show the worked answer

Answer: B

The encryption context is logged in CloudTrail for every KMS request, giving per-record audit without exposing personal data.

Why not the others

  • A: Leaks data.
  • C: Unmanageable and costly.
  • D: Unrelated to KMS calls.
How the exam tests this
  • “Decrypt fails with InvalidCiphertextException”→ Wrong or missing encryption context (or wrong key).
  • “Audit which item was decrypted”→ Encryption context in CloudTrail.
  • “Key usable only from S3”→ kms:ViaService.
  • “Force minimum rotation period”→ kms:RotationPeriodInDays.
Must remember
  • Encryption context = AAD, must match on decrypt.
  • Logged in plain text: never secret data.
  • Condition keys: EncryptionContext:, ViaService, CallerAccount.
  • Symmetric keys only.
06

Key rotation, disabling and deletion

Keys have a life. Rotation replaces the key material while the key ID, ARN, aliases and policies stay the same, and KMS keeps the old material so old data still decrypts. Disabling instantly stops all use and can be undone. Deletion is final: after a 7–30 day waiting period, the key and everything encrypted only under it is gone forever.

Concept profile

Automatic key rotation

often confused with manual rotation (new key + alias)
?What is it?

KMS generates new key material for a symmetric customer managed key on a schedule (default 365 days, configurable 90–2560 days) and keeps all older material for decryption.

⚙How does it work?
  • Enable with aws kms enable-key-rotation --rotation-period-in-days 180.
  • New encryptions use the newest material; decrypt automatically picks the right one.
  • Key ID, ARN, aliases, policy and grants stay the same: no app changes.
  • Existing data and data keys are not re-encrypted.
  • On-demand rotation (RotateKeyOnDemand) is also available, including for imported material.
{ }Structure
KeyAutomatic rotation
Symmetric customer managed (AWS_KMS origin)Optional, 90–2560 days (default 365)
AWS managedAlways, about every year
Imported material (EXTERNAL)No automatic; on-demand yes
Asymmetric, HMAC, custom key storeNo: rotate manually (new key + move alias)
EnabledusableDisablednot usable, reversiblePendingDeletion7–30 days (default 30)Deleteddata unrecoverableCancelKeyDeletion during the waiting period (key returns as Disabled)Before deleting: disable, watch CloudTrail + a CloudWatch alarm for usage, then schedule deletion.
Disable is a pause button. Delete is a shredder with a waiting period.
⇄Automatic key rotation vs manual rotation (new key + alias)
Automatic rotationManual rotation
What changesKey material onlyA whole new KMS key
Key ID / ARNSameNew (point the alias at it)
App changesNoneNone if apps use the alias; else update
Old dataDecrypts automaticallyKeep the old key to decrypt old data
Works forSymmetric, KMS-generated materialAny key type
!Common mistakes the exam tests
  • Thinking rotation re-encrypts existing data. It doesn't.
  • Deleting the old key after a manual rotation: old data becomes unreadable.
  • Scheduling deletion when you only need to stop use: disable instead.
  • Expecting to recover a deleted key. After the waiting period, it's gone (multi-Region replicas aside).
  • Forgetting a key in PendingDeletion can't be used: apps break during the waiting period too.
✓Benefits and use cases
  • Meet compliance rotation rules with zero downtime.
  • Emergency stop: disable a key to block access to data immediately.
  • Crypto-shredding: deleting the key makes the data unreadable.
Think of it like · changing the locks on an office

You can re-key, lock up, or demolish.

AWS conceptFamiliar thing
Automatic rotation≈The locksmith re-pins the lock; old keys still open old cabinets
Manual rotation≈A brand-new door, with the room-number sign (alias) moved to it
Disable≈Locking the building for the weekend
PendingDeletion≈Demolition scheduled: 7–30 days to change your mind
Deleted≈The building is gone, and so is everything inside
Real AWS example · safe retirement of a key

Disable first, watch for use, then schedule deletion with the longest window.

aws kms disable-key --key-id alias/old-payments
# CloudWatch metric filter on CloudTrail: any KMS call with
#   errorCode = "DisabledException" and the key ARN → alarm
aws kms schedule-key-deletion --key-id 1234abcd-... --pending-window-in-days 30
# If the alarm fires:
aws kms cancel-key-deletion --key-id 1234abcd-...
aws kms enable-key --key-id 1234abcd-...

After cancelling, the key returns in the Disabled state; enable it to use it again.

Exam-style scenario

Compliance requires that a customer managed key protecting RDS snapshots have its key material changed every 180 days, with no application changes and old snapshots still readable. What should the engineer do?

  1. A. Create a new key every 180 days and re-encrypt all snapshots.
  2. B. Enable automatic key rotation on the key with a rotation period of 180 days.
  3. C. Disable and re-enable the key every 180 days.
  4. D. Import new key material every 180 days.
Show the worked answer

Answer: B

Automatic rotation supports custom periods (90–2560 days). The key ID stays the same and older material remains available to decrypt old snapshots.

Why not the others

  • A: Works but much more effort and downtime risk.
  • C: Doesn't change the material.
  • D: Only applies to EXTERNAL-origin keys and adds burden.
How the exam tests this
  • “Rotate yearly with no app change”→ Automatic rotation.
  • “Rotate an asymmetric key”→ Manual: new key + alias.
  • “Stop all use now, reversibly”→ DisableKey.
  • “Key scheduled for deletion by mistake”→ CancelKeyDeletion within 7–30 days.
Must remember
  • Rotation: same key ID, old material kept, data not re-encrypted.
  • Custom period 90–2560 days (default 365).
  • Deletion waiting period 7–30 days (default 30).
  • Unsure? Disable, don't delete.
07

Cheatsheet extras: guarding and watching your keys

Your cheat sheet adds a few KMS best practices that the sections above only touched: asking for MFA before dangerous key operations, keeping key admins and key users apart, why aliases are risky inside policies, and how to react automatically when someone disables or schedules deletion of a key. It also uses older names, so first a quick translation.

Older material says “CMK” (customer master key). Today AWS just says KMS key. Two other facts changed: AWS managed keys now rotate every year (the cheat sheet says every 3 years, which was true before 2022), and customer managed keys can rotate on a period you choose from 90 to 2,560 days, or on demand (the cheat sheet says “once a year”). If an exam option says “every 3 years”, it is out of date.

Concept profile

Key policy guardrails: MFA and separation of duties

often confused with an SCP that denies KMS actions
?What is it?

Extra statements in a key policy that protect the dangerous KMS actions (PutKeyPolicy, ScheduleKeyDeletion, DisableKey, DeleteImportedKeyMaterial, DeleteAlias) and keep the people who manage a key separate from the people who use it.

⚙How does it work?
  • MFA: allow the critical actions only when aws:MultiFactorAuthAge is small (for example under 300 seconds), so a stolen access key alone can’t delete a key.
  • Separation of duties: key administrators get kms:Create*, Describe*, Enable*, Put*, ScheduleKeyDeletion… but not Encrypt/Decrypt; key users get Encrypt/Decrypt/GenerateDataKey but not PutKeyPolicy.
  • Never give people kms:*: whoever has kms:PutKeyPolicy can replace the whole policy and lock everyone else out.
  • Avoid "Effect":"Deny" with NotPrincipal: it denies everyone except the listed ARNs, and session ARNs of roles often don’t match, so you lock yourself out.
{ }Structure
Key administratorsCreate*, Describe*, Enable*Put*, Update*, TagResourceScheduleKeyDeletion (with MFA)no Encrypt / DecryptKey usersEncrypt, Decrypt, ReEncrypt*GenerateDataKey*DescribeKeyno PutKeyPolicy / DeleteCritical actionsPutKeyPolicyScheduleKeyDeletionDeleteImportedKeyMaterialonly if MultiFactorAuthAge < 300Two separate jobs, two separate statements, and an MFA lock on the actions that can’t be undone.
Who manages the key is not who uses the key.
⇄Key policy guardrails vs an SCP that denies KMS actions
Key policy guardrailsSCP deny
ScopeOne keyEvery key in the accounts under the OU
Can require MFA per actionYes (condition in the statement)Yes, but for everyone in the account
Who can still actThe admins you listNobody in the account (except what you exempt)
Good for“Only the security team may delete this key, with MFA”“Nobody in production may ever schedule key deletion”
!Common mistakes the exam tests
  • Granting kms:* to a developer role “to make it work”: it includes PutKeyPolicy and ScheduleKeyDeletion.
  • Using an alias as the Resource of a policy to limit which key is used: aliases can be moved to another key. Use the key ARN, or the kms:ResourceAliases / kms:RequestAlias condition keys.
  • Writing Deny + NotPrincipal in a key policy and locking out every role session.
  • Expecting MFA conditions to work for AWS services calling KMS for you: services don’t send MFA context, so put MFA only on human admin actions.
✓Benefits and use cases
  • A stolen access key can’t delete your keys.
  • Auditors see clear separation of duties (PCI DSS, SOC 2).
  • Developers keep working while key lifecycle stays with the security team.

React automatically when a key is disabled or scheduled for deletion

The cheat sheet shows an “event-driven security” pattern. Today it works like this: every KMS call is logged by CloudTrail; an EventBridge rule matches DisableKey or ScheduleKeyDeletion (event type “AWS API Call via CloudTrail”, source aws.kms); the target is a Lambda function that calls CancelKeyDeletion / EnableKey and an SNS topic that tells the security team. For a continuous check, the AWS Config managed rule kms-cmk-not-scheduled-for-deletion flags keys that are pending deletion. Older material calls EventBridge “CloudWatch Events”; it is the same service.

Think of it like · the keys to a bank vault

A bank keeps vault keys safe with rules and alarms.

AWS conceptFamiliar thing
Key administrator≈The security manager who can change the locks but can’t open the vault alone
Key user≈The teller who opens the vault every day but can’t change the locks
MFA condition≈A second signature needed before anyone destroys a key
Alias in a policy≈A name tag on a key ring: anyone can move the tag to another ring
EventBridge + Lambda≈An alarm that re-locks the vault the moment someone tampers with it
Real AWS example · MFA for critical KMS calls, and an EventBridge pattern

Key policy statement for the security admins, then the event pattern that catches deletion attempts.

{
  "Sid": "CriticalActionsNeedFreshMFA",
  "Effect": "Allow",
  "Principal": { "AWS": "arn:aws:iam::111122223333:role/KeyAdmins" },
  "Action": [ "kms:PutKeyPolicy", "kms:ScheduleKeyDeletion",
              "kms:DeleteImportedKeyMaterial", "kms:DeleteAlias" ],
  "Resource": "*",
  "Condition": { "NumericLessThan": { "aws:MultiFactorAuthAge": "300" } }
}

EventBridge rule pattern:
{ "source": ["aws.kms"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": { "eventName": ["ScheduleKeyDeletion", "DisableKey"] } }
→ targets: Lambda (CancelKeyDeletion / EnableKey) + SNS topic

The role session must have signed in with MFA in the last 5 minutes. The rule reacts within seconds of the API call.

Exam-style scenario

A security team wants to make sure that if anyone schedules deletion of a production KMS key, the deletion is cancelled automatically and the team is alerted, with the least custom infrastructure. What should they build?

  1. A. A daily Lambda function that lists all keys and checks their state.
  2. B. An EventBridge rule on the CloudTrail event ScheduleKeyDeletion from aws.kms, targeting a Lambda function that calls CancelKeyDeletion and an SNS topic.
  3. C. A CloudWatch alarm on the KMS SecondsUntilKeyMaterialExpiration metric.
  4. D. Amazon Inspector findings for KMS.
Show the worked answer

Answer: B

EventBridge receives the CloudTrail event in near real time and can trigger both the fix and the alert.

Why not the others

  • A: Up to a day late and more code to run.
  • C: That metric is for imported key material expiry, not deletion.
  • D: Inspector scans workloads for vulnerabilities, not KMS API calls.
How the exam tests this
  • “Require MFA before a key can be deleted”→ Key policy condition aws:MultiFactorAuthAge (or MultiFactorAuthPresent).
  • “Admins must not be able to decrypt data”→ Separate admin and user statements.
  • “Auto-cancel key deletion and alert”→ EventBridge + Lambda + SNS.
  • “Continuously flag keys pending deletion”→ Config rule kms-cmk-not-scheduled-for-deletion.
  • “AWS managed key rotation period”→ Every year (not 3 years any more).
Must remember
  • CMK (old name) = KMS key.
  • No kms:* for people; PutKeyPolicy = full control.
  • Don’t trust aliases in policies; use ARNs or alias condition keys.
  • Avoid Deny + NotPrincipal.
  • Delete/disable attempts → EventBridge → Lambda + SNS.
08

Lecture summary map

Day 1 of Data Protection on one screen.

1. Mind map

① Key typesCustomer / AWS managedAWS owned: no auditSymmetric for services② EnvelopeDirect Encrypt ≤ 4 KBGenerateDataKeyStore encrypted key③ Key policyExactly one per keyRoot stmt enables IAMCross-acct: both sides④ GrantsAllow-only, temporaryGrantIsForAWSResourceGrant token⑤ Encryption contextMust match on decryptLogged, not secretViaService, CallerAcct⑥ LifecycleRotate 90–2560 daysDisable = reversibleDelete after 7–30 dData Protection 1AWS KMS foundations
Tap a branch to jump back to that part of the lecture. Try redrawing this map from memory on paper.

2. KMS is a bank vault

KMS keyThe bank's master key, locked in the vaultData keyA small key for one safe-deposit boxEnvelopeThe box key, sealed in an envelope only the bank can openKey policyThe bank's rulebook: who may ask for the master keyGrantA signed slip: 'this courier may open box 12 today'Encryption contextThe label on the envelope; must match to open
Tell the story of the bank vault out loud and every KMS term falls into place.

3. “If the question says… pick…”

Another account must decrypt the dataCustomer managed key: key policy + IAM in B, key ARN
No audit trail needed, zero managementAWS owned key
Encrypt more than 4 KBEnvelope encryption: GenerateDataKey
Encrypt on the client before uploadAWS Encryption SDK
IAM allows kms:Decrypt but still deniedKey policy doesn't enable IAM (root statement)
Nobody can manage the keyUnmanageable key → AWS Support
Let EBS use the key but not arbitrary grantskms:GrantIsForAWSResource
Key usable only through S3kms:ViaService
Audit which record was decryptedEncryption context (logged in CloudTrail)
Change key material every 180 days, no app changeAutomatic rotation, period 180
Rotate an asymmetric keyNew key + repoint alias
Stop use now, maybe undo laterDisable the key
Day 1 in one sentence

The master key stays in the vault, small data keys do the heavy lifting, and the key policy decides who may ask the vault for anything.

09

Must-remember cheat sheet

1. Key types: customer managed · AWS managed · AWS owned.
2. AWS managed (aws/…): fixed policy, yearly rotation, no cross-account.
3. AWS services need symmetric keys.
4. Direct Encrypt ≤ 4 KB; bigger → envelope.
5. GenerateDataKey → plaintext + encrypted data key.
6. Every key has exactly one key policy.
7. Root statement = IAM policies enabled.
8. Cross-account = key policy and IAM; use ARN, not alias.
9. No admin left → unmanageable → Support.
10. Grants: allow-only; grant token for immediate use.
11. GrantIsForAWSResource limits CreateGrant to services.
12. Encryption context: must match, logged, not secret.
13. ViaService = only through this service.
14. Rotation: 90–2560 d, same key ID, old material kept.
15. Asymmetric / HMAC / custom store: manual rotation.
16. Delete: 7–30 days wait; disable if unsure.
17. “CMK” is the old name for a KMS key; AWS managed keys now rotate every year.
18. Critical KMS actions: MFA condition in the key policy + EventBridge → Lambda/SNS auto-response.
10

Core quiz

Check the basics first. Pick an answer, then press Check.

11

Hard quiz

Harder than most real exam questions on purpose, with one ordering question. Aim for 9 out of 12 before Day 2.

12

Practice test questions (from your mock exams)

These 9 questions match today’s topics. 8 come from your own mock exams (the “practice tests” folder); the wording was tidied, and where a mock answer was out of date or wrong, the explanation says so, with the mock and question number at the end. The last one is a new exam-style question (marked “New question”) written in October 2026 from the SCS-C03 exam guide and current AWS documentation, to cover recent changes.

13

Hands-on lab (30 minutes)

  1. Create a symmetric customer managed key with alias alias/lab-dp1. Open its default key policy and find the account-root statement.
  2. Run aws kms encrypt --key-id alias/lab-dp1 --plaintext fileb://small.txt --encryption-context dept=hr, then decrypt once with the same context and once without it. Read the error.
  3. Try encrypt with a 5 KB file and read the error. Then run aws kms generate-data-key --key-id alias/lab-dp1 --key-spec AES_256 and look at the two outputs.
  4. In CloudTrail Event history, find your Decrypt event and spot the encryption context.
  5. Enable rotation with --rotation-period-in-days 90, then check get-key-rotation-status.
  6. Disable the key, try encrypt again, then schedule deletion with a 7-day window and cancel it.