diff --git a/README.md b/README.md
index b6eba6c0..0e4e2ef8 100644
--- a/README.md
+++ b/README.md
@@ -172,6 +172,7 @@ No modules.
| [aws_iam_policy_document.deny_incorrect_encryption_headers](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.deny_incorrect_kms_key_sse](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.deny_insecure_transport](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.deny_ssec_encrypted_object_uploads](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.deny_unencrypted_object_uploads](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.elb_log_delivery](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.inventory_and_analytics_destination_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
@@ -198,6 +199,7 @@ No modules.
| [attach\_deny\_incorrect\_encryption\_headers](#input\_attach\_deny\_incorrect\_encryption\_headers) | Controls if S3 bucket should deny incorrect encryption headers policy attached. | `bool` | `false` | no |
| [attach\_deny\_incorrect\_kms\_key\_sse](#input\_attach\_deny\_incorrect\_kms\_key\_sse) | Controls if S3 bucket policy should deny usage of incorrect KMS key SSE. | `bool` | `false` | no |
| [attach\_deny\_insecure\_transport\_policy](#input\_attach\_deny\_insecure\_transport\_policy) | Controls if S3 bucket should have deny non-SSL transport policy attached | `bool` | `false` | no |
+| [attach\_deny\_ssec\_encrypted\_object\_uploads](#input\_attach\_deny\_ssec\_encrypted\_object\_uploads) | Controls if S3 bucket should deny SSEC encrypted object uploads. | `bool` | `false` | no |
| [attach\_deny\_unencrypted\_object\_uploads](#input\_attach\_deny\_unencrypted\_object\_uploads) | Controls if S3 bucket should deny unencrypted object uploads policy attached. | `bool` | `false` | no |
| [attach\_elb\_log\_delivery\_policy](#input\_attach\_elb\_log\_delivery\_policy) | Controls if S3 bucket should have ELB log delivery policy attached | `bool` | `false` | no |
| [attach\_inventory\_destination\_policy](#input\_attach\_inventory\_destination\_policy) | Controls if S3 bucket should have bucket inventory destination policy attached. | `bool` | `false` | no |
diff --git a/examples/complete/main.tf b/examples/complete/main.tf
index 1f2538b7..59c8ee0e 100644
--- a/examples/complete/main.tf
+++ b/examples/complete/main.tf
@@ -139,14 +139,15 @@ module "s3_bucket" {
}
# Bucket policies
- attach_policy = true
- policy = data.aws_iam_policy_document.bucket_policy.json
- attach_deny_insecure_transport_policy = true
- attach_require_latest_tls_policy = true
- attach_deny_incorrect_encryption_headers = true
- attach_deny_incorrect_kms_key_sse = true
- allowed_kms_key_arn = aws_kms_key.objects.arn
- attach_deny_unencrypted_object_uploads = true
+ attach_policy = true
+ policy = data.aws_iam_policy_document.bucket_policy.json
+ attach_deny_insecure_transport_policy = true
+ attach_require_latest_tls_policy = true
+ attach_deny_incorrect_encryption_headers = true
+ attach_deny_incorrect_kms_key_sse = true
+ allowed_kms_key_arn = aws_kms_key.objects.arn
+ attach_deny_unencrypted_object_uploads = true
+ attach_deny_ssec_encrypted_object_uploads = true
# S3 bucket-level Public Access Block configuration (by default now AWS has made this default as true for S3 bucket-level block public access)
# block_public_acls = true
diff --git a/main.tf b/main.tf
index 6554c26c..ce49ab09 100644
--- a/main.tf
+++ b/main.tf
@@ -12,7 +12,7 @@ locals {
create_bucket_acl = (var.acl != null && var.acl != "null") || length(local.grants) > 0
- attach_policy = var.attach_require_latest_tls_policy || var.attach_access_log_delivery_policy || var.attach_elb_log_delivery_policy || var.attach_lb_log_delivery_policy || var.attach_deny_insecure_transport_policy || var.attach_inventory_destination_policy || var.attach_deny_incorrect_encryption_headers || var.attach_deny_incorrect_kms_key_sse || var.attach_deny_unencrypted_object_uploads || var.attach_policy
+ attach_policy = var.attach_require_latest_tls_policy || var.attach_access_log_delivery_policy || var.attach_elb_log_delivery_policy || var.attach_lb_log_delivery_policy || var.attach_deny_insecure_transport_policy || var.attach_inventory_destination_policy || var.attach_deny_incorrect_encryption_headers || var.attach_deny_incorrect_kms_key_sse || var.attach_deny_unencrypted_object_uploads || var.attach_deny_ssec_encrypted_object_uploads || var.attach_policy
# Variables with type `any` should be jsonencode()'d when value is coming from Terragrunt
grants = try(jsondecode(var.grant), var.grant)
@@ -558,6 +558,7 @@ data "aws_iam_policy_document" "combined" {
var.attach_require_latest_tls_policy ? data.aws_iam_policy_document.require_latest_tls[0].json : "",
var.attach_deny_insecure_transport_policy ? data.aws_iam_policy_document.deny_insecure_transport[0].json : "",
var.attach_deny_unencrypted_object_uploads ? data.aws_iam_policy_document.deny_unencrypted_object_uploads[0].json : "",
+ var.attach_deny_ssec_encrypted_object_uploads ? data.aws_iam_policy_document.deny_ssec_encrypted_object_uploads[0].json : "",
var.attach_deny_incorrect_kms_key_sse ? data.aws_iam_policy_document.deny_incorrect_kms_key_sse[0].json : "",
var.attach_deny_incorrect_encryption_headers ? data.aws_iam_policy_document.deny_incorrect_encryption_headers[0].json : "",
var.attach_inventory_destination_policy || var.attach_analytics_destination_policy ? data.aws_iam_policy_document.inventory_and_analytics_destination_policy[0].json : "",
@@ -908,6 +909,34 @@ data "aws_iam_policy_document" "deny_unencrypted_object_uploads" {
}
}
+data "aws_iam_policy_document" "deny_ssec_encrypted_object_uploads" {
+ count = local.create_bucket && var.attach_deny_ssec_encrypted_object_uploads ? 1 : 0
+
+ statement {
+ sid = "denySSECEncryptedObjectUploads"
+ effect = "Deny"
+
+ actions = [
+ "s3:PutObject"
+ ]
+
+ resources = [
+ "${aws_s3_bucket.this[0].arn}/*"
+ ]
+
+ principals {
+ identifiers = ["*"]
+ type = "*"
+ }
+
+ condition {
+ test = "Null"
+ variable = "s3:x-amz-server-side-encryption-customer-algorithm"
+ values = [false]
+ }
+ }
+}
+
resource "aws_s3_bucket_public_access_block" "this" {
count = local.create_bucket && var.attach_public_policy ? 1 : 0
diff --git a/variables.tf b/variables.tf
index 92feec90..4d3aa95c 100644
--- a/variables.tf
+++ b/variables.tf
@@ -82,6 +82,12 @@ variable "attach_deny_unencrypted_object_uploads" {
default = false
}
+variable "attach_deny_ssec_encrypted_object_uploads" {
+ description = "Controls if S3 bucket should deny SSEC encrypted object uploads."
+ type = bool
+ default = false
+}
+
variable "bucket" {
description = "(Optional, Forces new resource) The name of the bucket. If omitted, Terraform will assign a random, unique name."
type = string
diff --git a/wrappers/main.tf b/wrappers/main.tf
index 5b3d0c72..d207d50e 100644
--- a/wrappers/main.tf
+++ b/wrappers/main.tf
@@ -17,6 +17,7 @@ module "wrapper" {
attach_deny_incorrect_encryption_headers = try(each.value.attach_deny_incorrect_encryption_headers, var.defaults.attach_deny_incorrect_encryption_headers, false)
attach_deny_incorrect_kms_key_sse = try(each.value.attach_deny_incorrect_kms_key_sse, var.defaults.attach_deny_incorrect_kms_key_sse, false)
attach_deny_insecure_transport_policy = try(each.value.attach_deny_insecure_transport_policy, var.defaults.attach_deny_insecure_transport_policy, false)
+ attach_deny_ssec_encrypted_object_uploads = try(each.value.attach_deny_ssec_encrypted_object_uploads, var.defaults.attach_deny_ssec_encrypted_object_uploads, false)
attach_deny_unencrypted_object_uploads = try(each.value.attach_deny_unencrypted_object_uploads, var.defaults.attach_deny_unencrypted_object_uploads, false)
attach_elb_log_delivery_policy = try(each.value.attach_elb_log_delivery_policy, var.defaults.attach_elb_log_delivery_policy, false)
attach_inventory_destination_policy = try(each.value.attach_inventory_destination_policy, var.defaults.attach_inventory_destination_policy, false)