For AI agents: llms.txt is a short guide that sends you to the rules your problem needs, and rules.json holds every rule of this playbook as JSON.
Recommended
Keep encryption keys in a key service
Encrypt stored data with keys held in a key management service that never hands out the key itself. Rotate each key automatically, and keep the people who manage keys apart from the roles that use them.
How to do it
Use the cloud's key service, such as AWS KMS, Google Cloud KMS or Azure Key Vault, or a self-hosted one such as OpenBao. Create each key and its policy in code. Give the app's role encrypt and decrypt rights on its own key only. Give the key admin role rights to manage keys but not to decrypt. Turn on automatic rotation every 365 days at most. Rotation keeps the old key versions, so old data still decrypts. A deleted key makes its data unreadable for good. Set the longest waiting period the service allows, 30 days on AWS, and alert on every scheduled deletion. Encrypt single fields in the app with the same keys, as Encrypt the most sensitive fields describes. Disks, databases and backups take their keys from here, as Encrypt data on the wire and on disk requires.
Examples
Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.
Terraform example
resource "aws_kms_key" "orders" {
description = "Encrypts the orders database"
enable_key_rotation = true
rotation_period_in_days = 365
deletion_window_in_days = 30
}
resource "aws_cloudwatch_event_rule" "key_deletion" {
name = "kms-key-scheduled-for-deletion"
event_pattern = jsonencode({
source = ["aws.kms"]
detail = { eventName = ["ScheduleKeyDeletion", "DisableKey"] }
})
}
Python example
import boto3
kms = boto3.client("kms")
def keys_without_rotation():
for page in kms.get_paginator("list_keys").paginate():
for key in page["Keys"]:
meta = kms.describe_key(KeyId=key["KeyId"])["KeyMetadata"]
if meta["KeyManager"] != "CUSTOMER" or meta["KeyState"] != "Enabled":
continue
if meta.get("KeySpec") == "SYMMETRIC_DEFAULT" and not kms.get_key_rotation_status(KeyId=key["KeyId"])["KeyRotationEnabled"]:
yield key["KeyId"]
for key_id in keys_without_rotation():
print(key_id)
TypeScript example
import { KMSClient, paginateListKeys, DescribeKeyCommand, GetKeyRotationStatusCommand } from '@aws-sdk/client-kms';
const kms = new KMSClient({});
for await (const page of paginateListKeys({ client: kms }, {})) {
for (const { KeyId } of page.Keys ?? []) {
const { KeyMetadata: meta } = await kms.send(new DescribeKeyCommand({ KeyId }));
const isRotatableCustomerKey = meta.KeyManager === 'CUSTOMER' && meta.KeyState === 'Enabled' && meta.KeySpec === 'SYMMETRIC_DEFAULT';
if (!isRotatableCustomerKey) continue;
const { KeyRotationEnabled } = await kms.send(new GetKeyRotationStatusCommand({ KeyId }));
if (!KeyRotationEnabled) console.log(KeyId);
}
}
How to check
The script below lists no customer-managed key without automatic rotation. No key policy grants every key action to a role other than the key admin role. Schedule the deletion of a test key in a sandbox account, and the alert arrives within 15 minutes.
Sources
- NIST SP 800-57 Part 1 Rev. 5 Recommendation for Key Management
- AWS Well-Architected SEC08-BP01 Implement secure key management
Related rules
- Erase retired databases and every copy in Data
- Encrypt the most sensitive fields in Data
- Encrypt data on the wire and on disk in Security testing
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/infrastructure/configuration-and-secrets/key-management">Agent Wranglers infrastructure playbook</a>. In code you write, add a comment next to it with the same link.