Skip to main content

S3 Bucket Default Encryption

Overview

This check verifies that your Amazon S3 buckets have default server-side encryption enabled. When enabled, any new object uploaded to the bucket is automatically encrypted without requiring the uploader to specify encryption settings.

Risk

Without default encryption:

  • New objects may be stored unencrypted if uploaders forget to specify encryption
  • Sensitive data could be exposed if the bucket is misconfigured or accessed improperly
  • You lose audit capabilities and key rotation controls that come with KMS encryption
  • Compliance requirements (HIPAA, PCI-DSS, etc.) may not be met

Remediation Steps

Prerequisites

You need permission to modify S3 bucket settings. Typically, this means having the s3:PutEncryptionConfiguration permission or being a bucket owner.

Required IAM permissions

To enable bucket encryption, your IAM user or role needs:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutEncryptionConfiguration",
"s3:GetEncryptionConfiguration"
],
"Resource": "arn:aws:s3:::<your-bucket-name>"
}
]
}

If using SSE-KMS, you also need KMS permissions:

{
"Effect": "Allow",
"Action": [
"kms:GenerateDataKey",
"kms:Decrypt"
],
"Resource": "<your-kms-key-arn>"
}

AWS Console Method

  1. Open the Amazon S3 console
  2. Click on the bucket you want to encrypt
  3. Go to the Properties tab
  4. Scroll down to Default encryption and click Edit
  5. Under Encryption type, select one of:
    • Server-side encryption with Amazon S3 managed keys (SSE-S3) - simplest option
    • Server-side encryption with AWS KMS keys (SSE-KMS) - better for compliance and auditing
  6. If you chose SSE-KMS, select a KMS key (or use the default aws/s3 key)
  7. Click Save changes

Which encryption type should I choose?

  • SSE-S3 (AES-256): Simple, no additional cost, good for most use cases
  • SSE-KMS: Better for sensitive data - provides audit trails, key rotation, and fine-grained access control
AWS CLI (optional)

Enable SSE-S3 encryption (AES-256):

aws s3api put-bucket-encryption \
--bucket <your-bucket-name> \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}]
}' \
--region us-east-1

Enable SSE-KMS encryption:

aws s3api put-bucket-encryption \
--bucket <your-bucket-name> \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "<your-kms-key-id-or-arn>"
},
"BucketKeyEnabled": true
}]
}' \
--region us-east-1

Note: Setting BucketKeyEnabled to true reduces KMS request costs by using a bucket-level key.

Replace:

  • <your-bucket-name> with your actual bucket name
  • <your-kms-key-id-or-arn> with your KMS key ID or full ARN
CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: S3 bucket with default server-side encryption enabled

Parameters:
BucketName:
Type: String
Description: Name of the S3 bucket
EncryptionType:
Type: String
Default: AES256
AllowedValues:
- AES256
- aws:kms
Description: Server-side encryption algorithm (AES256 for SSE-S3, aws:kms for SSE-KMS)
KMSKeyId:
Type: String
Default: ''
Description: KMS Key ID or ARN (required only if EncryptionType is aws:kms)

Conditions:
UseKMS: !Equals [!Ref EncryptionType, 'aws:kms']

Resources:
EncryptedS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: !Ref EncryptionType
KMSMasterKeyID: !If [UseKMS, !Ref KMSKeyId, !Ref 'AWS::NoValue']
BucketKeyEnabled: !If [UseKMS, true, !Ref 'AWS::NoValue']

Outputs:
BucketArn:
Description: ARN of the encrypted S3 bucket
Value: !GetAtt EncryptedS3Bucket.Arn

Deploy with SSE-S3:

aws cloudformation deploy \
--template-file template.yaml \
--stack-name my-encrypted-bucket \
--parameter-overrides BucketName=my-bucket-name \
--region us-east-1

Deploy with SSE-KMS:

aws cloudformation deploy \
--template-file template.yaml \
--stack-name my-encrypted-bucket \
--parameter-overrides \
BucketName=my-bucket-name \
EncryptionType=aws:kms \
KMSKeyId=arn:aws:kms:us-east-1:123456789012:key/your-key-id \
--region us-east-1
Terraform (optional)
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}

variable "bucket_name" {
description = "Name of the S3 bucket"
type = string
}

variable "use_kms" {
description = "Use SSE-KMS instead of SSE-S3"
type = bool
default = false
}

variable "kms_key_arn" {
description = "KMS key ARN (required if use_kms is true)"
type = string
default = null
}

# For existing buckets, use aws_s3_bucket_server_side_encryption_configuration
resource "aws_s3_bucket_server_side_encryption_configuration" "encryption" {
bucket = var.bucket_name

rule {
apply_server_side_encryption_by_default {
sse_algorithm = var.use_kms ? "aws:kms" : "AES256"
kms_master_key_id = var.use_kms ? var.kms_key_arn : null
}
bucket_key_enabled = var.use_kms ? true : false
}
}

output "bucket_name" {
description = "Name of the bucket with encryption configured"
value = var.bucket_name
}

Apply with SSE-S3:

terraform apply -var="bucket_name=my-bucket-name"

Apply with SSE-KMS:

terraform apply \
-var="bucket_name=my-bucket-name" \
-var="use_kms=true" \
-var="kms_key_arn=arn:aws:kms:us-east-1:123456789012:key/your-key-id"

Verification

After enabling encryption, verify it's working:

  1. Go to your bucket in the S3 console
  2. Click the Properties tab
  3. Under Default encryption, confirm it shows your chosen encryption type
CLI verification commands

Check current encryption settings:

aws s3api get-bucket-encryption \
--bucket <your-bucket-name> \
--region us-east-1

Expected output for SSE-S3:

{
"ServerSideEncryptionConfiguration": {
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
}
}

Expected output for SSE-KMS:

{
"ServerSideEncryptionConfiguration": {
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/your-key-id"
},
"BucketKeyEnabled": true
}
]
}
}

Re-run the Prowler check:

prowler aws --check s3_bucket_default_encryption --region us-east-1

Additional Resources

Notes

  • Existing objects are not automatically encrypted. Default encryption only applies to new objects uploaded after it's enabled. To encrypt existing objects, you must copy them in place or use S3 Batch Operations.

  • SSE-KMS has costs. Each request using a KMS key incurs a small charge. Enable "Bucket Key" to significantly reduce these costs.

  • For stronger enforcement, consider adding a bucket policy that denies uploads without encryption:

Bucket policy to deny unencrypted uploads
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnencryptedUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<your-bucket-name>/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": ["AES256", "aws:kms"]
}
}
}
]
}

This policy denies any upload that doesn't explicitly specify server-side encryption.