S3 Replication Terraform Apply Error For Encryption

I am trying to run s3 replication in terraform which will be cross-regional.

Part of my main s3.tf is

resource "aws_kms_key" "s3_replica-us-west-2-key" {
  description             = "S3 master key replica us-west-2"
  deletion_window_in_days = 30
  enable_key_rotation     = "true"
}

module "s3_replica" {
  source = "git@github.com:xxx"

  providers = {
    aws     = "aws.us-west-2"
  }

  name                  = "s3_replica"
  logging_bucket_prefix = "s3_replica"
  versioning            = var.versioning
  bucket_logging        = var.bucket_logging
  logging_bucket_name   = var.logging_bucket_name

  kms_key_id    = aws_kms_key.s3_replica-us-west-2-key.key_id
  sse_algorithm = var.sse_algorithm
}

module "s3" {
  source                = "git@github.com:xxxx"
  name                  = "s3"
  logging_bucket_prefix = "s3"
  versioning            = var.versioning
  bucket_logging        = var.bucket_logging
  logging_bucket_name   = var.logging_bucket_name

  kms_key_id    = aws_kms_key.s3.key_id
  sse_algorithm = var.sse_algorithm

 replication_configuration = {
    role = aws_iam_role.s3_replication.arn

      rules = [
        {
          prefix = ""
          status = "Enabled"

        destination = {
          bucket = module.s3_replica.bucket_arn
          replica_kms_key_id = aws_kms_alias.s3_replica-us-west-2-key.arn
          storage_class = "STANDARD_IA"
          }
        }
      ]  

      source_selection_criteria = {
          sse_kms_encrypted_objects = {
            enabled = true
          }
        }
  }
}  

and the part of my replication configuration block in the module I use is:

dynamic "replication_configuration" {
    for_each = length(keys(var.replication_configuration)) == 0 ? [] : [var.replication_configuration]

    content {
      role = replication_configuration.value.role

      dynamic "rules" {
        for_each = replication_configuration.value.rules

        content {
          id       = lookup(replication_configuration.value.rules, "id", null)
          priority = lookup(replication_configuration.value.rules, "priority", null)
          prefix   = lookup(replication_configuration.value.rules, "prefix", null)
          status   = lookup(replication_configuration.value.rules, "status", null)

          dynamic "destination" {
            for_each = length(keys(lookup(rules.value, "destination", {}))) == 0 ? [] : [lookup(rules.value, "destination", {})]

            content {
              bucket             = lookup(destination.value, "bucket", null)
              storage_class      = lookup(destination.value, "storage_class", null)
              replica_kms_key_id = lookup(destination.value, "replica_kms_key_id", null)
              account_id         = lookup(destination.value, "account_id", null)
            }
          }

          dynamic "source_selection_criteria" {
            for_each = length(keys(lookup(rules.value, "source_selection_criteria", {}))) == 0 ? [] : [lookup(rules.value, "source_selection_criteria", {})]

            content {

              dynamic "sse_kms_encrypted_objects" {
                for_each = length(keys(lookup(source_selection_criteria.value, "sse_kms_encrypted_objects", {}))) == 0 ? [] : [lookup(source_selection_criteria.value, "sse_kms_encrypted_objects", {})]

                content {

                  enabled = sse_kms_encrypted_objects.value.enabled
                }
              }
            }
        }
      }
    }
    }
}
}

Now when I run terraform init… it works.
But when I run terraform plan it works.

  • this is the apply:
# module.s3.aws_s3_bucket.s3_bucket will be updated in-place
  ~ resource "aws_s3_bucket" "s3_bucket" {
        acl                         = "bucket-owner-full-control"
        arn                         = "arn:aws:s3:::xxx"
        bucket                      = "xxxxx"
        id                          = "xxxxx"
        region                      = "us-east-1"
        request_payer               = "BucketOwner"
        }

        cors_rule {
            allowed_headers = [
                "*",
            ]
            allowed_methods = [
                "GET",
                "PUT",
            ]
            allowed_origins = [
                "*",
            ]
            expose_headers  = [
                "Accept-Ranges",
                "Content-Range",
                "Content-Encoding",
                "Content-Length",
            ]
            max_age_seconds = 0
        }

        logging {
            target_bucket = "xxx-us-east-1-s3-logging"
            target_prefix = "xx"
        }

      + replication_configuration {
          + role = "arn:aws:iam::xxx:role/s3-bucket-replication"

          + rules {
              + status = "Enabled"

              + destination {
                  + bucket             = "arn:aws:s3:::xxx-replica-us-west-2"
                  + replica_kms_key_id = "arn:aws:kms:us-west-2:xxxs3_replica_us_west_2_key"
                  + storage_class      = "STANDARD_IA"
                }
            }
        }

        server_side_encryption_configuration {
            rule {
                apply_server_side_encryption_by_default {
                    kms_master_key_id = "xxxx"
                    sse_algorithm     = "aws:kms"
                }
            }
        }

        versioning {
            enabled    = true
            mfa_delete = false
        }
    }

Plan: 0 to add, 1 to change, 0 to destroy.

But when I run terraform apply it gives me the following error:

Error: Error putting S3 replication configuration: InvalidRequest: SseKmsEncryptedObjects must be specified if EncryptionConfiguration is present.
        status code: 400

  on .terraform/modules/s3/main.tf line 210, in resource "aws_s3_bucket" "s3_bucket":
 210: resource "aws_s3_bucket" "s3_bucket" {
  • how do I fix this? what does it mean?