KMS
dpl.KMS(
alias: str = None, # e.g. "alias/my-app" or "my-app"
description: str = None,
key_usage: str = "ENCRYPT_DECRYPT", # "ENCRYPT_DECRYPT" | "SIGN_VERIFY" | "GENERATE_VERIFY_MAC"
key_spec: str = "SYMMETRIC_DEFAULT", # "SYMMETRIC_DEFAULT" | "RSA_2048/3072/4096"
# | "ECC_NIST_P256/P384/P521" | "ECC_SECG_P256K1"
# | "HMAC_224/256/384/512"
enable_rotation: bool = None, # None → auto: True for SYMMETRIC_DEFAULT, False otherwise
deletion_policy: str = "Retain", # KMS uses Retain by default (security)
existing_key_id: str = None, # ID or ARN of an existing key (does not create resource)
env_var: str = None, # Forces the name of the generated env var
)
Auto-generated environment variable
| Configuration | Variable |
|---|---|
env_var="MY_KEY" | MY_KEY (takes priority) |
alias="myapp/encryption" | MYAPP_ENCRYPTION_KEY_ID |
| No alias or env_var | KMS_KEY_ID |
Generated CloudFormation resources
AWS::KMS::Key— withEnabled: True,KeyUsage,KeySpec, and a basic key policyAWS::KMS::Alias— optional alias to identify the key by nameEnableKeyRotationis only added whenkey_spec="SYMMETRIC_DEFAULT"(asymmetric keys do not support automatic rotation)
Compile-time validations (E00)
aliascan only contain alphanumeric characters,-,_,/key_usagemust be one of the valid valueskey_specmust be one of the valid valuesenable_rotation=Trueis not valid for asymmetric keys (RSA, ECC, HMAC)- ECC
key_specis not compatible withkey_usage="ENCRYPT_DECRYPT" key_spec="SYMMETRIC_DEFAULT"is not compatible withkey_usage="SIGN_VERIFY"
Examples
Basic (auto-detected)
app/features/tenant/routes.py
import deployless as dpl
kms_key = dpl.KMS(
alias="my-app/data",
description="Encryption key for sensitive data",
enable_rotation=True,
deletion_policy="Retain",
)
# No need to declare resources= or policies= — kms_key is auto-detected
# with "crud" permissions (Encrypt, Decrypt, GenerateDataKey, DescribeKey)
dpl.configure(description="Tenant Service")
Restricting permissions
# This feature only needs to decrypt
dpl.configure(
resources={"data_key": (kms_key, "decrypt")},
)
Using the key in app code
The environment variable is automatically injected:
app/features/tenant/services/kms_service.py
import boto3
import base64
import os
kms_client = boto3.client('kms')
def encrypt_with_kms(plaintext: str) -> str:
response = kms_client.encrypt(
KeyId=os.getenv('KMS_KEY_ID'),
Plaintext=plaintext.encode('utf-8'),
)
return base64.b64encode(response['CiphertextBlob']).decode('utf-8')
def decrypt_with_kms(ciphertext_b64: str) -> str:
ciphertext_blob = base64.b64decode(ciphertext_b64)
response = kms_client.decrypt(CiphertextBlob=ciphertext_blob)
return response['Plaintext'].decode('utf-8')
note
kms:Decrypt does not need to specify KeyId because the ciphertext already embeds the ID of the key that encrypted it.
Cross-feature key sharing
A real pattern: the tenant feature encrypts the RSA private key, and the auth feature decrypts it on each login.
app/features/tenant/routes.py
import deployless as dpl
tenant_key = dpl.KMS(
alias="ums/tenant-keys",
description="Encryption of RSA private keys per tenant",
enable_rotation=True,
deletion_policy="Retain",
)
tenants_table = dpl.DynamoDB("ums-tenants", pk="tenant_id", deletion_policy="Retain")
# Restrict tenant_key to "encrypt" only (this feature doesn't need decrypt)
dpl.configure(
resources={"tenant_key": (tenant_key, "encrypt")},
)
app/features/auth/routes.py
import deployless as dpl
from app.shared.services.kms_service import tenant_key
# Restrict to "decrypt" only
dpl.configure(
resources={"tenant_key": (tenant_key, "decrypt")},
)
Asymmetric key for digital signing
signing_key = dpl.KMS(
alias="my-app/signing",
description="RSA key for signing JWTs or documents",
key_usage="SIGN_VERIFY",
key_spec="RSA_2048",
)
# For SIGN_VERIFY keys, add additional actions via policies=
dpl.configure(
policies=[
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["kms:Sign", "kms:Verify", "kms:GetPublicKey"],
"Resource": dpl.Ref(signing_key),
}
],
}
],
)
Existing key
dpl.KMS(existing_key_id="arn:aws:kms:us-east-1:123456789:key/abc-123")
# Does not generate a CloudFormation resource
# KMS_KEY_ID = "arn:aws:kms:us-east-1:123456789:key/abc-123"
Permission levels
| Level | IAM actions granted |
|---|---|
"crud" (default) | kms:Encrypt, kms:Decrypt, kms:GenerateDataKey, kms:DescribeKey |
"encrypt" | kms:Encrypt |
"decrypt" | kms:Decrypt |