AWS KMS (Key Management Service)

Prerequisites: IAM roles and least privilege and the response model.

KMS manages cryptographic keys and authorized cryptographic operations. Current terminology is KMS key, not the older customer master key/CMK. Encryption does not replace access control or backups.

Key and permission model

Symmetric encryption keys are the usual integration choice. Asymmetric keys have algorithm-specific encryption or signing uses; not every RSA/ECC key supports every operation. HMAC keys generate/verify MACs. CloudHSM is a separate service with a different ownership/cost model.

A key policy is central to authorization; the account principal statement can enable delegation to IAM policies, not merely allow the root user’s interactive use. Grants authorize scoped operations, often for service integrations. Cross-account usage needs appropriate key and caller policies. See policy evaluation.

Envelope encryption uses GenerateDataKey to obtain a plaintext data key and encrypted copy. Encrypt data locally, erase the plaintext key, and retain only the encrypted data key with ciphertext. Never log plaintext keys or secrets.

Reversible cryptographic lab

Use a sandbox Region and a role authorized for CreateKey, scoped Encrypt/Decrypt, DescribeKey and ScheduleKeyDeletion. Creating a customer-managed key incurs charges. The create-key policy flag is —policy, not —key-policy; the CLI default policy delegates permissions as documented.

aws kms create-key --description "Disposable wiki lab" --key-usage ENCRYPT_DECRYPT

Record KeyMetadata.KeyId. Save non-sensitive plaintext to a local file using your editor. Use aws kms encrypt --key-id KEY_ID --plaintext fileb://fixture.txt --encryption-context Purpose=wiki-lab. The response CiphertextBlob is base64 text; decode it to a binary ciphertext file before passing fileb:// to decrypt.

Decrypt with the same encryption context. Expected: the original plaintext after decoding the response. Try a different Purpose context and expect failure; encryption context is authenticated metadata, not confidential storage.

Rotation, deletion and cost

Rotation eligibility and schedules depend on key type/origin; do not promise automatic rotation for imported/asymmetric keys. Rotation preserves decryptability of older ciphertext. Multi-Region keys are related regional resources, not a universal single global key or automatic replication of all policies.

Schedule deletion only for the lab key, with the documented minimum waiting period; deletion after that window is irreversible and can make dependent ciphertext unrecoverable. Check aliases/grants/service dependencies first and cancel deletion if mistaken.

Estimate key-months and operation-specific request charges. At a purely illustrative $0.03/10,000 requests, one million encrypts plus one million decrypts per day over thirty days is sixty million requests and $180 before allowances/key charges—not $6. Verify current regional operation pricing before using this assumption.

Key catalogue and envelope architecture

KindTypical useCompatibility/ownership
Symmetric encryptionSupported service at-rest integrationSelected key origin/store and operation constraints
Asymmetric encryption/signingOutside-service encryption or signaturesAlgorithm/usage must match; not every integration accepts it
HMACMessage authentication codesGenerateMac/VerifyMac, not Encrypt/Decrypt
AWS-managed keyService-managed usePolicy/lifecycle controls differ from customer-managed keys
Customer-managed keyExplicit policy/grants/lifecycleKey-months and applicable request costs
CloudHSM/custom storeSpecific control/compliance needsAdditional service/availability/operator responsibilities
GenerateDataKey → plaintext data key ── local authenticated encryption → ciphertext
       └─────── encrypted data key ─────────── stored with ciphertext
decrypt encrypted data key → authorized local decrypt → plaintext application data

KMS Encrypt has input/algorithm size limits; it is not a bulk-file encryption upload API. The data key encrypts the object locally. Authentication context belongs to the cryptographic request; never put confidential values in it because audit evidence may expose it.

Complete teaching key policy and grants

Substitute the sandbox account and application role before creating a disposable symmetric key with —policy file://key-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EnableAccountIAMDelegation",
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::111122223333:root" },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "ApplicationUseForLabContext",
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::111122223333:role/WikiApplication" },
      "Action": ["kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey"],
      "Resource": "*",
      "Condition": {
        "StringEquals": { "kms:EncryptionContext:Purpose": "wiki-lab" }
      }
    }
  ]
}

In a key policy, Resource * refers to the attached key; this is not an identity policy granting every key. The account statement enables IAM delegation; caller identity policies/guardrails still matter. Production administration, separation of duties and cross-account policies require a reviewed design.

A grant is delegated authorization to a grantee principal, not an implicit Lambda auto-discovery feature:

aws kms create-grant --key-id KMS_LAB_KEY_ID \
  --grantee-principal APPLICATION_ROLE_ARN --operations Encrypt Decrypt \
  --constraints '{"EncryptionContextEquals":{"Purpose":"wiki-lab"}}'
aws kms list-grants --key-id KMS_LAB_KEY_ID

Record GrantId/GrantToken without exposing credentials. Eventual consistency can require the returned token for immediately authorized calls. Retire/revoke only the lab grant using the documented role-dependent operation; do not remove service grants blindly.

SDK encryption-context walkthrough

This complete small-payload example uses a pre-existing lab key and verified SDK credentials; it prints no plaintext/ciphertext:

import os
import boto3
 
kms = boto3.client("kms")
key_id = os.environ["KMS_LAB_KEY_ID"]
context = {"Purpose": "wiki-lab"}
encrypted = kms.encrypt(
    KeyId=key_id,
    Plaintext=b"synthetic-fixture",
    EncryptionContext=context,
)["CiphertextBlob"]
decrypted = kms.decrypt(
    KeyId=key_id,
    CiphertextBlob=encrypted,
    EncryptionContext=context,
)["Plaintext"]
assert decrypted == b"synthetic-fixture"

For bulk encryption use a maintained AWS Encryption SDK/authenticated-encryption workflow that manages framing, data keys and integrity. Python deletion of a variable is not guaranteed cryptographic memory erasure.

Service integration, rotation and troubleshooting

SSE-S3 and SSE-KMS are distinct choices. Select a supported customer-managed key and service resource policy/role permissions; uploading to S3 does not automatically grant another account decrypt. EBS encryption defaults are regional configuration; RDS encryption and restore/migration have engine/resource lifecycle constraints.

Automatic rotation eligibility, configurable periods and on-demand/manual alternatives depend on key origin/type. Rotation preserves old-material decryptability; replacing a key/alias requires data migration/access planning and does not rewrite every ciphertext.

Inspect key state, policy/grants, encryption context, Region/partition, algorithm and throttling before broadening permissions. Preserve CloudTrail KMS evidence; metadata/key usage is not confidential payload access. Before deletion inventory all dependent encrypted resources and test restore with the intended key identity; deletion after the waiting period is irreversible.

References: grants, encryption context, key rotation, Encrypt contract.

Cross-wiki comparisons

References

Across the wiki