Enforcing Compliance with AWS KMS Automatic Key Rotation: A Practical Guide
Learn how to use AWS KMS customer‑managed key rotation to meet GDPR and PCI‑DSS requirements, with a step‑by‑step example, trade‑offs, and an actionable checklist.
24 Oct 2026, 09:29 UTC

Static Keys and Compliance Risk
Regulations such as GDPR and PCI‑DSS require that encryption keys are rotated on a regular basis. A static key that never changes exposes data to a higher risk of compromise and makes audit trails more complex. AWS KMS customer‑managed keys (CMKs) provide an out‑of‑the‑box solution: you can enable automatic rotation that creates a new key version each year while keeping the same key ARN.
How Automatic Rotation Works
Key Versioning
When you enable rotation, KMS generates a new KeyVersionId every 365 days. The key ARN stays the same, so applications that reference the ARN do not need to change. New data is encrypted with the latest version; older data remains encrypted with the previous version until you re‑encrypt it.
Rotation Flow
1. Schedule – KMS schedules a rotation event at the start of the next year.
2. Generate – KMS creates a new key material and assigns it a new version ID.
3. Mark – The old version is marked as inactive; it can still decrypt data but cannot be used for new encryption.
4. Notify – A ScheduleKeyRotation event is logged in CloudTrail.
Step‑by‑Step Example
Create a CMK
Use the console or CLI to create a key. Replace my-key with a name of your choice.
aws kms create-key \
--description "Key for S3 encryption" \
--key-usage ENCRYPT_DECRYPT \
--origin AWS_KMS \
--tags Key=Purpose,Value=S3Encryption \
--query KeyMetadata.KeyId \
--output text
Store the returned KeyId (e.g., arn:aws:kms:us-east-1:123456789012:key/abcd1234-5678-90ef-1234-567890abcdef) for later use.
Encrypt an S3 Object with the CMK
Below is a Python snippet using boto3. It encrypts a local file and uploads the encrypted payload to S3.
import boto3
s3 = boto3.client('s3')
kms = boto3.client('kms')
# Replace with your values
CMK_ARN = 'arn:aws:kms:us-east-1:123456789012:key/abcd1234-5678-90ef-1234-567890abcdef'
BUCKET = 'my-bucket'
OBJECT_KEY = 'encrypted.txt'
LOCAL_FILE = 'plain.txt'
# Read plaintext
with open(LOCAL_FILE, 'rb') as f:
plaintext = f.read()
# Encrypt with KMS
ciphertext_blob = kms.encrypt(KeyId=CMK_ARN, Plaintext=plaintext)['CiphertextBlob']
# Upload encrypted data
s3.put_object(Bucket=BUCKET, Key=OBJECT_KEY, Body=ciphertext_blob)
print('Upload complete')
After upload, the object is stored in S3 in an encrypted form that can only be decrypted by the CMK.
Enable Automatic Rotation
Run the following CLI command. You need kms:EnableKeyRotation permission on the key.
aws kms enable-key-rotation --key-id
Check the status:
aws kms describe-key --key-id \
--query "KeyMetadata.KeyRotationEnabled"
Expected output: true. If it returns false, rotation is not enabled.
Verify Rotation via CloudTrail
In the next year, CloudTrail will log a ScheduleKeyRotation event. You can query it with the console or CLI:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=ScheduleKeyRotation \
--query "Events[*].{EventTime:EventTime,KeyId:CloudTrailEvent}" \
--output table
Look for a new KeyVersionId in the CloudTrailEvent JSON. That confirms the rotation occurred.
Trade‑offs & Limitations
Latency During Re‑Encryption
When a key version changes, any data that needs to be re‑encrypted (e.g., during a bulk migration or when you decide to re‑encrypt existing objects) will incur KMS API latency. For large objects, this can add seconds to the upload time. Schedule re‑encryption during low‑traffic windows.
Cost Impact
Each Encrypt or Decrypt request costs $0.03 per 10,000 requests (pricing may vary by region). Automatic rotation itself does not add cost, but re‑encrypting existing objects will. Estimate the number of objects and size to budget for this.
Application Cache of Key ARN
If your code caches the CMK ARN, it will remain valid after rotation. However, if you cache the KeyVersionId or the key material, you must refresh those values. A common pitfall is to hard‑code the version ID, causing decryption failures after rotation.
Actionable Checklist
- Enable key rotation on all customer‑managed CMKs that encrypt regulated data.
- Set up a CloudWatch alarm on CloudTrail for
ScheduleKeyRotationevents to receive a notification each year. - Schedule a nightly or weekly job to re‑encrypt existing S3 objects with the latest key version. Use
aws s3 cp --recursive --sse aws:kmsfor simple cases. - Update any code that caches key material or version IDs to use the key ARN only.
- Review KMS request logs to monitor for unexpected spikes in encryption/decryption calls.
- Document the rotation policy and include it in your compliance audit trail.
Closing Thoughts
Automatic key rotation in AWS KMS is a lightweight, low‑maintenance way to satisfy many regulatory requirements. By combining it with a disciplined re‑encryption schedule and vigilant monitoring, you can keep your data secure, reduce audit risk, and maintain the performance you expect from AWS services.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.