GenerateDataKey or Decrypt for the data key only. Secret plaintext never goes to KMS. The AWS SDK is imported inside tooling-vault-aws-kms, and the backend loader imports that package only when provider is aws_kms.
Why
Production keys should live in a CMK with automatic rotation. The app still holds only a wrapped data key plus the AES-GCM ciphertext.Setup
-
Add
tooling-vault-aws-kmstoapps/backend(already a workspace dependency). - Set environment on the deployed service:
VAULT_KMS_CAPABILITY=decrypt and a principal that can kms:Decrypt only. Omit VAULT_PROVIDER to leave vault disabled. local throws at boot outside development and test.
- Key policy: require encryption context
org_id, split GenerateDataKey from Decrypt, rotation on. The repo does not provision the key. See Vault.
Local observability
KMS exceptions are stripped ofPlaintext, CiphertextBlob, and secret-like strings before they leave the package. Domain metrics: vault.operation tags action and outcome only.
Adding a new command
Do not addEncrypt or Decrypt of the secret itself. New KMS calls stay inside this package and must map failures to the closed VaultError codes.
Gotchas
capability_mismatchis raised before the SDK call.access_deniedmeans KMS was called and denied.- Encryption context on
GenerateDataKeyandDecryptis{org_id, name, secret_id}. A moved blob fails closed. - CloudTrail should alarm on
Decryptvolume andAccessDeniedfor this key ARN.
