Securing Amazon S3: Implementing Encryption (SSE) with Terraform
Mastering S3 Encryption with Terraform
Why Encryption at Rest is Non-Negotiable
Data security is a core pillar of the AWS Shared Responsibility Model. For an S3 bucket, encryption ensures that even if the physical disks in the data center were compromised, your data would remain unreadable.
There are two primary approaches to protecting your data:
- Server-Side Encryption (SSE): Amazon S3 encrypts the object before saving it to disk and decrypts it when you read it. This is the most transparent and commonly used method.
- Client-Side Encryption: You encrypt the data locally before sending it to AWS. While providing higher control, it adds significant complexity to key management and application logic.
Comparison: SSE-S3 vs. SSE-KMS
Choosing the right server-side encryption method depends on your compliance requirements and your FinOps strategy.
| Feature | SSE-S3 (AES-256) | SSE-KMS |
|---|---|---|
| Key Management | Fully managed by AWS | Managed by you via AWS KMS |
| Cost | Free (included with S3) | KMS Key cost + Per-request fees |
| Audit Trail | Limited | Full logging via AWS CloudTrail |
| Complexity | Zero configuration | Requires specific IAM permissions |
FinOps Tip: For buckets with millions of frequently accessed objects, KMS request costs can spike. Enable S3 Bucket Keys to reduce KMS call volume and save up to 99% on encryption costs.
Implementation with Terraform (Version >= 1.0)
In recent versions of the AWS Terraform provider, encryption configuration has been moved from the aws_s3_bucket resource into a dedicated resource: aws_s3_bucket_server_side_encryption_configuration.
Method 1: SSE-S3 Configuration (The Standard)
This is the most cost-effective and simplest method for most use cases.
resource "aws_s3_bucket" "my_secure_bucket" {
bucket = "my-company-production-data"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "default" {
bucket = aws_s3_bucket.my_secure_bucket.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
Method 2: SSE-KMS Configuration (For Compliance)
Use this if you need to audit every single access to your data via CloudTrail.
resource "aws_s3_bucket_server_side_encryption_configuration" "kms_config" {
bucket = aws_s3_bucket.my_secure_bucket.id
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = aws_kms_key.my_storage_key.arn
sse_algorithm = "aws:kms"
}
bucket_key_enabled = true # Crucial for reducing KMS costs
}
}
Important: Handling Existing Objects
Activating encryption on an existing bucket is not retroactive. Files already stored in the bucket will remain unencrypted.
To fix this, you must “copy the objects over themselves.” The easiest way to encrypt existing objects in bulk using the AWS CLI is:
aws s3 cp s3://my-bucket/ s3://my-bucket/ --recursive --sse AES256
Conclusion
Encrypting your S3 buckets with Terraform is an essential best practice, often required by compliance frameworks like SOC2 or GDPR. By using modern Terraform resources and considering the FinOps impact of KMS, you ensure your infrastructure is both secure and cost-efficient from day one.
Actuellement ingénieur DevOps/Architecte Cloud, j’étais initialement interessé par l’administration système et grâce aux entreprises dans lesquelles j’ai pu travailler Oxalide et maintenant Claranet j’ai eu la chance de découvrir l’univers du Cloud et de l’automatisation.
Je me suis décidé a publier ce blog pour vous faire partager ma passion mais également pour enrichir avec modestie tout ce que l’on peut trouver sur internet. Bonne lecture !