AWS Builder Center
Implementing Data Encryption in AWS: KMS, S3, DynamoDB, and Attribute-Based Access Control

Implementing Data Encryption in AWS: KMS, S3, DynamoDB, and Attribute-Based Access Control

Data encryption is one of the foundations of cloud security, but implementing it effectively involves more than simply enabling encryption on a storage service. Organizations also need to manage encryption keys, control who can decrypt sensitive information, and understand when encryption should happen on the server or before data reaches the cloud.

Data encryption is one of the foundations of cloud security, but implementing it effectively involves more than simply enabling encryption on a storage service. Organizations also need to manage encryption keys, control who can decrypt sensitive information, and understand when encryption should happen on the server or before data reaches the cloud.
In a recent AWS Builder Lab, Using Data Encryption in AWS, I explored several approaches to protecting data across AWS services. The exercises covered AWS Key Management Service (AWS KMS), Amazon S3 server-side encryption, attribute-based access control (ABAC), client-side encryption for Amazon DynamoDB, and the AWS Encryption SDK.
The lab used a healthcare scenario involving medical images, along with a sales analytics workload and local files. Each exercise demonstrated a different aspect of data protection and highlighted the relationship between encryption, identity, permissions, and key management.

1. Creating and managing encryption keys with AWS KMS

I started with AWS Key Management Service (AWS KMS), which provides a managed way to create and control cryptographic keys used to protect data across AWS services.
For the medical imaging scenario, I created a symmetric, single-Region customer-managed key named ImageAccessKey. I also added an ImageType tag with the value MRI.
During configuration, I assigned key administration permissions to the lab user and key usage permissions to the viewerInstanceRoleForMedicalImages IAM role. I then enabled automatic key rotation.
This exercise highlighted an important distinction: key administration and key usage are separate responsibilities. A principal that manages a key does not automatically need to be the same principal that uses it to encrypt or decrypt data.
The key's tag also became important later when I configured access based on attributes rather than changing the underlying IAM role assignment.

2. Enabling server-side encryption in Amazon S3

The next task involved protecting medical images stored in an Amazon S3 bucket whose name began with corp-image-store-.
I configured the bucket's default encryption to use server-side encryption with AWS KMS keys (SSE-KMS), selecting the ARN of the customer-managed key I had created. I also enabled the S3 Bucket Key option.
The purpose was to ensure that new objects uploaded under the configured default encryption settings would be encrypted using the selected KMS key.
To test the configuration, I used a Windows Server EC2 instance and the lab's image transfer utility to upload additional medical images to the bucket. I then inspected an uploaded image's properties and confirmed that its encryption settings showed SSE-KMS, the expected key ARN, and Bucket Key enabled.
One detail stood out: changing a bucket's default encryption settings does not automatically re-encrypt objects already stored in the bucket. The existing children's coloring-contest images and the newly uploaded medical images could therefore have different encryption states.
This is an important consideration when securing existing storage. Organizations should assess their existing objects and apply a separate remediation process where encryption requirements are not already met.

3. Using attribute-based access control to manage decryption

Encryption protects stored data, but access controls determine which identities can use the relevant keys to decrypt it.
In the lab, the image-viewing application could access the unencrypted coloring-contest images but initially received an Access Denied response when attempting to view the newly encrypted X-ray images.
I investigated the IAM role attached to the instance and examined its permissions policy. The policy included conditions that evaluated the ImageType tag on the KMS key when determining whether decryption was permitted.
At that point, the key's tag value was MRI, while the policy expected the value XRAY for the medical imaging access scenario.
Rather than modifying the IAM policy or replacing the role attached to the EC2 instance, I updated the key's ImageType tag from MRI to XRAY. I then tested the image-viewing application again and confirmed that the X-ray images could be viewed.
This demonstrated attribute-based access control (ABAC): permissions can be evaluated using attributes such as resource tags, allowing access decisions to change when those attributes change.
The practical lesson is that access can sometimes be managed centrally through well-designed attributes and policies instead of repeatedly creating or modifying individual permissions.
However, tags must be governed carefully. If a principal can change security-sensitive tags without appropriate controls, it may be able to influence access decisions. Tag permissions, IAM policies, and KMS key policies must therefore be designed together.

4. Understanding server-side encryption in Amazon DynamoDB

The lab then moved from object storage to Amazon DynamoDB.
I worked with a Python application that loaded sales records from a CSV file into a DynamoDB table named Table1. The program successfully inserted 1,033 sales records, which I verified in the DynamoDB console.
When I inspected the table items, the attributes were readable. This demonstrated the normal experience provided by DynamoDB server-side encryption: DynamoDB manages encryption at rest and transparently decrypts data for authorized requests.
For many workloads, server-side encryption provides a practical baseline because the application does not need to implement its own encryption and decryption logic for every database operation.
However, it is important to distinguish encryption at rest from client-side encryption. With server-side encryption, the service handles the cryptographic operations behind the scenes. With client-side encryption, the application encrypts data before sending it to the service.
That difference affects what a database administrator or someone with direct access to stored table items can see.

5. Implementing client-side encryption with the DynamoDB Encryption SDK

To explore client-side encryption, I created a second table, Table2, and modified the Python application to use the DynamoDB Encryption SDK.
I created another KMS key named DynamoDB_Direct_CMP_Key and configured the application to use its ARN with an AWS KMS cryptographic materials provider.
The application selected sales records where the region was North America and the number of units sold was below 1,000. It then used the SDK's EncryptedTable interface to encrypt the records before storing them in DynamoDB.
The program successfully inserted 93 records into Table2.
When I inspected the table, most of the business attributes were no longer human-readable. The primary key attributes remained available so DynamoDB could locate records, while the SDK also added metadata attributes used to manage encryption.
This was a useful demonstration of the additional protection client-side encryption can provide. Someone examining the stored items directly cannot simply read the protected business attributes in the same way as the records in Table1.
There is a trade-off, though. Client-side encryption introduces more application complexity, and the application must have access to the correct cryptographic materials to decrypt protected data. Developers must also account for which attributes need to remain available for database operations.

6. Exploring wrapped cryptographic materials

The next exercise introduced a third table, Table3, and a wrapped cryptographic materials provider.
Unlike the previous configuration, which used AWS KMS through a direct provider, this exercise simulated retrieving wrapping and signing keys from an on-premises key management system.
The lab explicitly simulated this behavior: the Python functions generated keys locally rather than connecting to an actual external key management system.
I configured the application to encrypt selected vegetable-sales records with total revenue below 500,000. The script successfully inserted 1,345 records into Table3.
As with Table2, most of the attributes were encrypted, while the primary key fields remained readable. The SDK also added metadata attributes to support the encryption process.
This exercise illustrated a different key-management pattern, but the simulation is important to keep in mind. It demonstrated how an application can be structured around externally managed cryptographic materials; it did not establish a production-ready connection to an on-premises key management system.
In a real environment, key retrieval, storage, rotation, availability, and recovery would all need to be designed and tested carefully.

7. Encrypting local files with the AWS Encryption SDK

The final exercise explored the AWS Encryption SDK, which can be used to encrypt application data beyond the specific storage operations covered by S3 and DynamoDB.
The scenario involved a directory containing plain-text recipe files. I updated the Python application to read each file, encrypt its contents using the AWS Encryption SDK and a KMS key, and write the encrypted output to a new file prefixed with [ENCRYPTED]-.
For this exercise, I created a symmetric KMS key named AWS_Encryption_SDK_Key and configured the application to use its ARN.
The program processed the recipe files successfully, and the generated files contained encrypted binary data rather than the original readable text.
This demonstrated how encryption can be applied at the application level before data is stored or shared.
It also highlighted a critical responsibility: encrypted data is only useful if the organization can securely retain and recover the keys needed to decrypt it. Losing access to the required key can make the encrypted data permanently inaccessible.
A production implementation should therefore include appropriate key permissions, backup and recovery planning, monitoring, and clear ownership of the encryption process.

Key lessons from the lab

The exercises reinforced several important principles for cloud security.
AreaWhat I learned
AWS KMSCentralized key management includes permissions, rotation, and key usage controls.
Amazon S3Default encryption protects new objects according to the configured settings, but existing objects require separate consideration.
ABACResource tags can influence access decisions when IAM and key policies are designed to evaluate them.
DynamoDB server-side encryptionEncryption at rest can be managed transparently by the service for authorized requests.
DynamoDB client-side encryptionEncrypting selected attributes before storage adds another layer of protection but increases application complexity.
Wrapped cryptographic materialsAlternative key-management patterns require careful handling of key retrieval, protection, and recovery.
AWS Encryption SDKApplications can encrypt arbitrary data, including local files, before storage.

Server-side vs. client-side encryption

One of the most valuable takeaways was understanding when these two approaches differ.
Server-side encryption is generally simpler to operate because the AWS service handles encryption at rest. It is a strong starting point for many storage workloads.
Client-side encryption gives the application more control over what is encrypted and when encryption happens. It can help protect sensitive attributes from being exposed through direct access to stored data, but it requires more careful application and key-management design.
Neither approach removes the need for authorization. Encryption, IAM policies, KMS key policies, application permissions, logging, and key recovery should be considered together.

Conclusion

This AWS Builder Lab provided practical experience with several approaches to protecting data in the cloud. I created and configured KMS keys, enabled S3 server-side encryption, used resource tags to demonstrate attribute-based access control, and explored both server-side and client-side encryption in DynamoDB. I also used the AWS Encryption SDK to encrypt local files programmatically.
The biggest lesson for me was that effective encryption is not just about making data unreadable. It also requires controlling who can decrypt it, understanding how keys are managed, and ensuring that authorized applications can access protected information when needed.
These concepts are particularly relevant to workloads that handle sensitive information, including healthcare systems, financial applications, analytics platforms, and other environments where confidentiality and access control are essential.

Services and technologies covered

  • AWS Key Management Service (AWS KMS)
  • Amazon Simple Storage Service (Amazon S3)
  • Amazon Elastic Compute Cloud (Amazon EC2)
  • AWS Identity and Access Management (IAM)
  • Amazon DynamoDB
  • DynamoDB Encryption SDK
  • AWS Encryption SDK
  • Python
Tags: AWS, Cloud Security, Data Encryption, AWS KMS, Amazon S3, Amazon DynamoDB, IAM, ABAC, Client-Side Encryption, AWS Encryption SDK, Cybersecurity
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article