DEV Community

harsh patel
harsh patel

Posted on

Mastering AWS Key Management Service (KMS): A Practical Guide to Data Encryption

Getting Started with AWS Key Management Service (KMS) — Python Edition

We live in a digital world where protecting sensitive information is more critical than ever. One of the most effective ways to safeguard data is encryption. But encryption is only as strong as your key management. That’s where AWS Key Management Service (KMS) shines.

In this hands-on lab, you’ll create and use a customer-managed KMS key, generate data keys, encrypt/decrypt data in Python, and integrate KMS with DynamoDB. You’ll also see how key policy adds a security layer beyond IAM permissions.


What You’ll Learn

  • Create a customer-managed KMS key
  • Generate data keys with KMS (Python + boto3)
  • Encrypt & decrypt data locally with the plaintext data key
  • Integrate KMS with DynamoDB (SSE-KMS)
  • Use key policy to control access beyond IAM

Getting Started

AWS KMS is a fully managed service to create and manage cryptographic keys for encrypting data inside and outside AWS. It integrates with services like S3, EBS, RDS, and DynamoDB, helping you meet compliance while keeping data secure.


Lab Setup (Pre-built Resources)

This lab includes a pre-created IAM user that can list DynamoDB tables and read from a specific table Books. We’ll use this user later to show how KMS encryption prevents access until the key policy allows it.


KMS Key Basics

A KMS key (a.k.a. CMK) is the root key used to:

  • Generate & encrypt data keys
  • Encrypt small payloads (≤ 4 KB)
  • Integrate with AWS services’ encryption

Types of keys:

  • AWS-managed keys: Created/managed by AWS (limited control)
  • Customer-managed keys: Created/managed by you (full control, symmetric or asymmetric)

We’ll use a symmetric customer-managed key.


Create a Customer-Managed Key

AWS Console → KMSCustomer managed keysCreate key

  • Key type: Symmetric
  • Key usage: Encrypt and decrypt
  • Key material origin: KMS (recommended)
  • Regionality: Single-region
  • Alias: myKey
  • Grant admin and usage permissions to your main user (e.g., ed-user) Finish the wizard.

Generate a Data Key (Python)

KMS keys don’t encrypt large blobs directly; instead, they generate data keys. You use the plaintext data key locally for encryption, discard it, and store only the encrypted data key (which you can decrypt later via KMS).

Prereqs

pip install boto3 cryptography
aws configure
Enter fullscreen mode Exit fullscreen mode

Fetch your key ARN

Console → KMS → Customer managed keys → myKey → copy ARN.

Generate the key

import boto3, binascii

kms = boto3.client("kms", region_name="us-east-1")
cmk_arn = "<your-kms-key-arn>"

resp = kms.generate_data_key(KeyId=cmk_arn, KeySpec="AES_256")

plaintext_key = resp["Plaintext"]
encrypted_data_key = resp["CiphertextBlob"]

print("Plaintext Data Key (hex):", binascii.hexlify(plaintext_key).decode())
print("Encrypted Data Key (hex):", binascii.hexlify(encrypted_data_key).decode())
Enter fullscreen mode Exit fullscreen mode

Encrypt Data Using the Data Key (Python)

import base64, binascii
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

plaintext_key_hex = "<your-plaintext-data-key-hex>"
key = binascii.unhexlify(plaintext_key_hex)

data = "Hello, this is my sensitive data.".encode()

padder = padding.PKCS7(128).padder()
padded = padder.update(data) + padder.finalize()

cipher = Cipher(algorithms.AES(key), modes.ECB())
encryptor = cipher.encryptor()
ct = encryptor.update(padded) + encryptor.finalize()

encrypted_b64 = base64.b64encode(ct).decode()
print("Encrypted Data (base64):", encrypted_b64)
Enter fullscreen mode Exit fullscreen mode

Decrypt the Data Key (Python)

import boto3, binascii

kms = boto3.client("kms", region_name="us-east-1")

encrypted_data_key_hex = "<your-encrypted-data-key-hex>"
encrypted_data_key = binascii.unhexlify(encrypted_data_key_hex)

resp = kms.decrypt(CiphertextBlob=encrypted_data_key)
recovered_key = resp["Plaintext"]

print("Recovered Plaintext Key (hex):", binascii.hexlify(recovered_key).decode())
Enter fullscreen mode Exit fullscreen mode

Decrypt the Data (Python)

import base64, binascii
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

plaintext_key_hex = "<your-plaintext-data-key-hex>"
key = binascii.unhexlify(plaintext_key_hex)

encrypted_b64 = "<your-encrypted-data-base64>"
ct = base64.b64decode(encrypted_b64)

cipher = Cipher(algorithms.AES(key), modes.ECB())
decryptor = cipher.decryptor()
padded_plain = decryptor.update(ct) + decryptor.finalize()

unpadder = padding.PKCS7(128).unpadder()
plain = unpadder.update(padded_plain) + unpadder.finalize()

print("Decrypted Data:", plain.decode())
Enter fullscreen mode Exit fullscreen mode

Integrate KMS with DynamoDB (SSE-KMS)

Now we’ll integrate KMS with DynamoDB to encrypt table data at rest.

Create an encrypted table

Console → DynamoDB → Create table

  • Table name: Books
  • Partition key: Author (String)
  • Sort key: Book_Title (String)
  • Table settings: Customize → Encryption at rest: Customer managed key → pick myKey Create and wait until status is Active.

Add an item

Explore table items → Create item

  • Author: Seth Godin
  • Book_Title: The Dip

Test Access with a Different IAM User

Even with read permissions, the user can’t read the table yet because the table is encrypted with your customer-managed key, and the key policy doesn’t permit this user to use the key.


Modify the Key Policy to Grant Access

Get the user’s ARN

Console → IAM → Users → IAMLabUser → copy ARN.

Edit the KMS key policy

Console → KMS → Customer managed keys → myKey → Switch to policy view → Edit

Add this statement (replace <IAM_ARN>):

{
  "Sid": "Allow use of the key",
  "Effect": "Allow",
  "Principal": { "AWS": "<IAM_ARN>" },
  "Action": ["kms:Encrypt", "kms:Decrypt"],
  "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

Save changes.

Verify as IAM user

Sign back in as IAMLabUser and Scan the Books table.

Now it works — because the user is allowed to use the KMS key.


Wrap-Up

You just built a practical, secure workflow with AWS KMS — end to end and fully in Python:

  • Created a customer-managed KMS key
  • Generated, stored, and recovered data keys
  • Encrypted/decrypted data locally with AES-256
  • Secured DynamoDB with SSE-KMS
  • Used key policy to gate access beyond IAM

Top comments (0)