Exam Guide: Developer - Associate
ποΈ Domain 2: Security
π Task 2: Implement Encryption By Using AWS Services.
Encryption shows up everywhere, especially on this exam. S3, DynamoDB, SQS, Lambda environment variables, RDS, and more. You need to know the difference between client-side and server-side encryption, how KMS works, and when to use each approach.
πConcepts
Encryption at Rest vs Encryption In Transit
Encryption At Rest
Data stored on disk: S3 Objects, DynamoDB tables, EBS volumes, RDS databases.
Encryption In Transit
Data moving between services or between client and server: HTTPS, TLS, VPN.
| Where | At Rest | In Transit |
|---|---|---|
| S3 | SSE-S3, SSE-KMS, SSE-C | HTTPS (enforced via bucket policy) |
| DynamoDB | Encrypted by default (AWS owned or KMS) | HTTPS (always) |
| RDS | KMS encryption | SSL/TLS connections |
| SQS | SSE-KMS | HTTPS |
| Lambda env vars | KMS (default + optional CMK) | HTTPS |
KMS Key Types
| Type | Managed By | Cost | Use Case |
|---|---|---|---|
| AWS owned keys | AWS | Free | Default encryption (DynamoDB, S3 SSE-S3) |
| AWS managed keys | AWS (in your account) | Free (per-use charges) | aws/s3, aws/dynamodb (you can't manage them) |
| Customer managed keys (CMK) | You | Monthly + per-use | Full control: rotation, policies, cross-account |
Envelope Encryption
KMS can only directly encrypt up to 4 KB. For larger data, it uses envelope encryption:
1. KMS generates a data key (plaintext + encrypted copy)
2. You encrypt your data with the plaintext data key
3. You store the encrypted data key alongside the encrypted data
4. You discard the plaintext data key from memory
5. To decrypt: KMS decrypts the data key β you decrypt the data
The AWS Encryption SDK handles this automatically.
Server-Side Encryption Options for S3
| Option | Key Management | Use Case |
|---|---|---|
| SSE-S3 | AWS manages everything | Simplest, no KMS costs |
| SSE-KMS | You control the KMS key | Audit trail via CloudTrail, key policies |
| SSE-C | You provide the key with every request | Full key control, AWS doesn't store the key |
Client-Side vs Server-Side Encryption
| Aspect | Server-Side | Client-Side |
|---|---|---|
| Who encrypts | AWS (after receiving data) | You (before sending to AWS) |
| Data in transit | Encrypted by HTTPS | Encrypted by you + HTTPS |
| Key management | AWS or KMS | You (via KMS or your own keys) |
| Complexity | Simple | More complex |
| Use case | Most workloads | When you can't trust the storage layer |
Key Rotation
- AWS managed keys: Rotated every year automatically (can't change this)
- Customer managed keys: Enable automatic rotation (every year)
- Old key material is kept, existing encrypted data still works
- The key ID doesn't change with automatic rotation
- Manual rotation: Create a new key, update alias to point to it
Certificate Management
| Service | What It Does | Cost |
|---|---|---|
| ACM | Free public SSL/TLS certificates for AWS services | Free |
| AWS Private CA | Issue private certificates for internal services | Paid |
π‘ACM certificates can't be exported. They're bound to AWS services (CloudFront, ALB, API Gateway). They auto-renew.
ποΈ Create A KMS Customer Managed Key
Now let's put these concepts into practice:
- Create a KMS customer managed key
- Encrypt and decrypt data using KMS
- Upload objects to S3 with different encryption options (SSE-S3, SSE-KMS)
- Enable automatic key rotation
- Encrypt Lambda environment variables with a custom KMS key
Prerequisites
- An AWS account
- An S3 bucket (we'll create one)
Part I
Create a KMS Customer Managed Key
Step 01: Open the KMS console
Click Create key
Step 02: Configure key
-
Key type:
Symmetric -
Key usage:
Encrypt and decrypt
Click Next
Step 03: Add labels
-
Alias:
app-encryption-key -
Description:
Customer managed key for application data
Click Next
Step 04: Define key administrative permissions - optional
-
Key administrators:
Select your IAM user
Click Next
Step 05: Define key usage permissions - optional
-
Key administrators:
Select your IAM user
Click Next
Step 06: Edit key policy - optional
Click Next
Step 07: Review
Click Finish
β
Green banner: Success
Your AWS KMS key was created with alias app-encryption-key and key ID 17fx7cex-17ae-419x-x816-de16fx50x928.
π‘ You now have a customer managed KMS key. Note the Key ID and ARN.
Enable Automatic Key Rotation
Step 08: Click on your key (app-encryption-key)
Step 09: Go to the Key material rotations tab
Click Edit
Step 10: Edit automatic key rotation
-
Key rotation:
Enable -
Rotation period in days:
365
Click Save
β Green banner: Successfully enabled automatic key rotation
π‘ With automatic rotation, KMS keeps old key material so existing ciphertext can still be decrypted. The key ID and ARN don't change. With manual rotation (creating a new key), you get a new key ID. Use aliases to abstract this.
Part II
Encrypt and Decrypt Data with KMS
Using the Console
π‘ In the KMS console, you can't directly encrypt/decrypt from the UI
Step 01: Create a Lambda function to demonstrate
Lambda β Create function:
-
Name:
KMSEncryptionDemo -
Runtime:
Python 3.12 -
Deploy:
Code:
import json
import boto3
import base64
kms = boto3.client('kms')
KEY_ID = 'alias/app-encryption-key'
def lambda_handler(event, context):
"""
Demonstrates KMS encrypt/decrypt operations.
Key concepts:
- KMS can directly encrypt up to 4 KB
- For larger data, use GenerateDataKey (envelope encryption)
- The AWS Encryption SDK handles envelope encryption automatically
"""
action = event.get('action', 'encrypt')
plaintext = event.get('data', 'Hello, this is sensitive data!')
if action == 'encrypt':
# Encrypt data (up to 4 KB)
response = kms.encrypt(
KeyId=KEY_ID,
Plaintext=plaintext.encode('utf-8')
)
ciphertext_b64 = base64.b64encode(response['CiphertextBlob']).decode('utf-8')
return {
'statusCode': 200,
'body': json.dumps({
'message': 'Data encrypted successfully',
'ciphertext': ciphertext_b64,
'keyId': response['KeyId']
})
}
elif action == 'decrypt':
# Decrypt data
ciphertext = base64.b64decode(event['ciphertext'])
response = kms.decrypt(CiphertextBlob=ciphertext)
return {
'statusCode': 200,
'body': json.dumps({
'message': 'Data decrypted successfully',
'plaintext': response['Plaintext'].decode('utf-8')
})
}
elif action == 'generate_data_key':
# Generate a data key for envelope encryption
response = kms.generate_data_key(
KeyId=KEY_ID,
KeySpec='AES_256'
)
return {
'statusCode': 200,
'body': json.dumps({
'message': 'Data key generated (envelope encryption)',
'plaintextKey': '*** exists in memory only β use it to encrypt, then discard ***',
'encryptedKey': base64.b64encode(response['CiphertextBlob']).decode('utf-8'),
'note': 'Store the encrypted key alongside your encrypted data'
})
}
Step 02: Add KMS permissions to the Lambda role:
Configuration β Permissions β click role name
Add permissions β Attach policies β AWSKeyManagementServicePowerUser
Step 03: Test events
Encrypt:
{"action": "encrypt", "data": "My secret credit card number"}
Generate data key:
{"action": "generate_data_key"}
Part III
S3 Encryption Options
Create an S3 Bucket
Step 01: Open the S3 console β Create bucket
Step 02: General configuration
-
Bucket type:
General purpose -
Bucket namespace:
Account Regional namespace (recommended) -
Bucket name prefix:
dva-encryption-demo -
Encryption type:
Server-side encryption with Amazon S3 managed keys (SSE-S3)
Step 03: Upload with SSE-S3 (Default)
- Click Upload
- Click Add files
- Add a
file(any text file) - Click Upload
π‘
SSE-S3is applied automatically
Step 04: Upload with SSE-KMS
- Click Upload
- Click Add files
- Expand βΆ Properties
-
Server side encryption:
Specify an encryption key -
Encryption settings:
Override bucket settings for default encryption -
Encryption type:
Server-side encryption with AWS Key Management Service keys (SSE-KMS) -
AWS KMS Key:
Choose from your AWS KMS keys -
Available AWS KMS Key:
app-encryption-key - Click Upload
Step 05: Verify Encryption
Click on each uploaded file
Step 06: Go to the Properties tab β Server-side encryption settings
You'll see which encryption method was used
π‘
SSE-KMSgives you an audit trail in CloudTrail (every encrypt/decrypt call is logged).SSE-S3 does not. If a question mentions "audit" or "compliance,"SSE-KMSis usually the answer.
Part IV
Encrypt Lambda Environment Variables
Using a Custom KMS Key
Step 01: Open your KMSEncryptionDemo function
Step 02: Configuration β Environment variables β Edit
Step 03: Edit environment variables
Click Add environment variable
-
Key:
DB_PASSWORD -
Value:
super-secret-password
Step 04: Expand βΆ Encryption configuration
-
Encryption in transit:
β CheckEnable helpers for encryption in transit -
AWS KMS key to encrypt at rest:
Use a customer managed key - Select
app-encryption-key - Click the Encrypt button next to
DB_PASSWORD
Click Save
The value is now encrypted.
In your code, you'd decrypt it:
import boto3
import base64
import os
kms = boto3.client('kms')
# Decrypt at cold start, cache the result
ENCRYPTED = os.environ['DB_PASSWORD']
DECRYPTED = kms.decrypt(
CiphertextBlob=base64.b64decode(ENCRYPTED)
)['Plaintext'].decode('utf-8')
def lambda_handler(event, context):
# Use DECRYPTED: already decrypted at cold start
print(f"Password length: {len(DECRYPTED)}") # Don't log the actual password!
ποΈ What You Built | π Exam Concepts Recap
| What You Built | Exam Concept |
|---|---|
| Created a Customer Managed KMS key | Key types: AWS owned vs AWS managed vs customer managed |
| *Assigned key administrators and key users * | KMS key policies: separate admin and usage permissions |
| Enabled automatic key rotation | Old key material preserved, key ID unchanged, seamless decryption |
Encrypted data directly with kms.encrypt() |
KMS direct encryption: limited to 4 KB |
Called generate_data_key for AES-256 |
Envelope encryption: encrypt large data locally, protect the key with KMS |
| Discarded the plaintext data key after use | Security best practice: plaintext key lives only in memory |
| Uploaded S3 objects with SSE-S3 | Default encryption: AWS manages everything, no audit trail |
| Uploaded S3 objects with SSE-KMS | Audit trail in CloudTrail, key policy control, cross-account possible |
| Encrypted Lambda environment variables with a CMK | Protecting secrets at rest in Lambda configuration |
| Decrypted env vars at cold start and cached the result | Performance pattern: avoid decrypting on every invocation |
β οΈ Clean Up Protocol
- S3 β Empty and delete the bucket
-
Lambda β Delete
KMSEncryptionDemo - KMS β Schedule key deletion (7-day minimum waiting period)
- IAM β Delete Lambda execution roles
- CloudWatch β Delete log groups
Key Takeaways
- KMS encrypts up to 4 KB directly: use envelope encryption (GenerateDataKey) for larger data
- SSE-S3: simplest. SSE-KMS: audit trail + key control. SSE-C: you provide the key.
- Client-side encryption: you encrypt before sending to AWS
- Automatic key rotation keeps old key material and existing data ia still decryptable
- Use aliases for seamless manual key rotation
- Cross-account KMS requires both a key policy AND an IAM policy
- ACM = free public certs (can't export). Private CA = private certs (costs money).
- Envelope encryption: the AWS Encryption SDK handles this for you
Additional Resources
- AWS KMS concepts
- Protecting data using server-side encryption in S3
- Key policies in AWS KMS
- What is the AWS Encryption SDK?
- Rotate AWS KMS keys
- Working with Lambda environment variables
Top comments (0)