Lab: Implementing Secure Data at Rest Controls with AWS KMS and S3
Design and implement controls for data at rest
Lab: Implementing Secure Data at Rest Controls with AWS KMS and S3
This hands-on lab guides you through designing and implementing robust security controls for data at rest using AWS Key Management Service (KMS) and Amazon S3. You will configure encryption, data integrity (Object Lock), and automated lifecycle management.
[!WARNING] This lab involves creating resources that may incur costs if not deleted. Remember to run the teardown commands at the end to avoid ongoing charges.
Prerequisites
- An active AWS Account.
- IAM User/Role with
AdministratorAccessor permissions for S3, KMS, and IAM. - AWS CLI installed and configured (run
aws configureto set your credentials). - Basic familiarity with the AWS Command Line Interface.
Learning Objectives
- Create and manage a Customer Managed Key (CMK) in AWS KMS.
- Provision an S3 Bucket with hardware-enforced Object Lock and Versioning.
- Implement Default Encryption using a CMK to ensure all data is encrypted at rest.
- Configure S3 Lifecycle Policies for automated data retention and transition.
Architecture Overview
Logic Flow for Encryption at Rest
Step-by-Step Instructions
Step 1: Create a KMS Customer Managed Key (CMK)
We will create a symmetric key that will serve as our root of trust for S3 encryption.
aws kms create-key --description "Key for Data at Rest Lab" --region <YOUR_REGION>[!NOTE] Note the
KeyIdorArnfrom the output. You will need it for the next steps.
▶Console alternative
Navigate to KMS > Customer managed keys > Create key. Select Symmetric, give it an alias (e.g., lab-cmk), and finish the wizard with default settings.
Step 2: Create a Secure S3 Bucket
We must enable Object Lock at creation time. Object Lock automatically enables Versioning.
aws s3api create-bucket \
--bucket brainybee-lab-data-<YOUR_ACCOUNT_ID> \
--region <YOUR_REGION> \
--object-lock-enabled-for-bucket \
--create-bucket-configuration LocationConstraint=<YOUR_REGION>[!TIP] If you are in
us-east-1, remove the--create-bucket-configurationflag.
▶Console alternative
Navigate to S3 > Create bucket. Provide a unique name. Under Advanced settings, toggle S3 Object Lock to On. You must also acknowledge that versioning will be enabled.
Step 3: Configure Default Bucket Encryption
Enforce that every object uploaded to this bucket is encrypted using the CMK created in Step 1.
aws s3api put-bucket-encryption \
--bucket brainybee-lab-data-<YOUR_ACCOUNT_ID> \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "<YOUR_KMS_KEY_ID>"
}
}
]
}'▶Console alternative
In the S3 bucket Properties tab, find Default encryption. Click Edit, choose Server-side encryption with AWS Key Management Service keys (SSE-KMS), and select your CMK.
Step 4: Implement Lifecycle Management
Configure a policy to transition objects to S3 Glacier Flexible Retrieval after 90 days to save costs while maintaining data for compliance.
aws s3api put-bucket-lifecycle-configuration \
--bucket brainybee-lab-data-<YOUR_ACCOUNT_ID> \
--lifecycle-configuration '{
"Rules": [
{
"ID": "ArchiveOldData",
"Status": "Enabled",
"Filter": {"Prefix": ""},
"Transitions": [
{
"Days": 90,
"StorageClass": "GLACIER"
}
]
}
]
}'Checkpoints
| Checkpoint | Action | Expected Result |
|---|---|---|
| KMS Key | aws kms describe-key --key-id <KEY_ID> | Key state should be Enabled. |
| Encryption | aws s3api get-bucket-encryption --bucket <BUCKET_NAME> | Output should show aws:kms and your Key ARN. |
| Data Integrity | aws s3api get-object-lock-configuration --bucket <BUCKET_NAME> | Should show ObjectLockEnabled: Enabled. |
Troubleshooting
| Issue | Possible Cause | Fix |
|---|---|---|
Access Denied during upload | KMS Key Policy | Ensure your IAM user has kms:Encrypt and kms:GenerateDataKey permissions on the key policy. |
InvalidBucketState | Object Lock | Object Lock cannot be enabled on an existing bucket; it must be set at creation. |
BucketAlreadyExists | Naming Conflict | S3 bucket names are globally unique. Add a random suffix to your bucket name. |
Clean-Up / Teardown
[!IMPORTANT] KMS keys cannot be deleted immediately. They are scheduled for deletion after a waiting period (7-30 days).
- Empty the S3 Bucket (Required before deletion):
bash
aws s3 rm s3://brainybee-lab-data-<YOUR_ACCOUNT_ID> --recursive - Delete the S3 Bucket:
bash
aws s3 rb s3://brainybee-lab-data-<YOUR_ACCOUNT_ID> - Schedule KMS Key Deletion:
bash
aws kms schedule-key-deletion --key-id <YOUR_KMS_KEY_ID> --pending-window-in-days 7
Cost Estimate
- AWS KMS: $1/month per CMK (prorated). $0.03 per 10,000 requests.
- Amazon S3: Minimal for this lab (standard storage rates apply, ~$0.023/GB).
- Total: Likely less than $0.10 if deleted immediately.