From 982a1f94151073b8203ef1ab6f290c90d3410e1b Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 23 Mar 2022 01:59:32 -0400 Subject: [PATCH 1/2] r/s3_bucket: make 'server_side_encryption_configuration' configurable --- internal/service/s3/bucket.go | 100 +++++++-- ...rver_side_encryption_configuration_test.go | 92 +++++++++ internal/service/s3/bucket_test.go | 189 ++++++++++++++++++ website/docs/r/s3_bucket.html.markdown | 55 ++++- 4 files changed, 413 insertions(+), 23 deletions(-) diff --git a/internal/service/s3/bucket.go b/internal/service/s3/bucket.go index e7b985231d7..ee28aa9ff68 100644 --- a/internal/service/s3/bucket.go +++ b/internal/service/s3/bucket.go @@ -571,39 +571,39 @@ func ResourceBucket() *schema.Resource { "server_side_encryption_configuration": { Type: schema.TypeList, + MaxItems: 1, + Optional: true, Computed: true, Deprecated: "Use the aws_s3_bucket_server_side_encryption_configuration resource instead", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "rule": { - Type: schema.TypeList, - Computed: true, - Deprecated: "Use the aws_s3_bucket_server_side_encryption_configuration resource instead", + Type: schema.TypeList, + MaxItems: 1, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "apply_server_side_encryption_by_default": { - Type: schema.TypeList, - Computed: true, - Deprecated: "Use the aws_s3_bucket_server_side_encryption_configuration resource instead", + Type: schema.TypeList, + MaxItems: 1, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "kms_master_key_id": { - Type: schema.TypeString, - Computed: true, - Deprecated: "Use the aws_s3_bucket_server_side_encryption_configuration resource instead", + Type: schema.TypeString, + Optional: true, }, "sse_algorithm": { - Type: schema.TypeString, - Computed: true, - Deprecated: "Use the aws_s3_bucket_server_side_encryption_configuration resource instead", + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(s3.ServerSideEncryption_Values(), false), }, }, }, }, "bucket_key_enabled": { - Type: schema.TypeBool, - Computed: true, - Deprecated: "Use the aws_s3_bucket_server_side_encryption_configuration resource instead", + Type: schema.TypeBool, + Optional: true, }, }, }, @@ -816,6 +816,12 @@ func resourceBucketUpdate(d *schema.ResourceData, meta interface{}) error { } } + if d.HasChange("server_side_encryption_configuration") { + if err := resourceBucketInternalServerSideEncryptionConfigurationUpdate(conn, d); err != nil { + return fmt.Errorf("error updating S3 Bucket (%s) Server-side Encryption configuration: %w", d.Id(), err) + } + } + if d.HasChange("versioning") { v := d.Get("versioning").([]interface{}) @@ -1851,6 +1857,70 @@ func resourceBucketInternalObjectLockConfigurationUpdate(conn *s3.S3, d *schema. return err } +func resourceBucketInternalServerSideEncryptionConfigurationUpdate(conn *s3.S3, d *schema.ResourceData) error { + serverSideEncryptionConfiguration := d.Get("server_side_encryption_configuration").([]interface{}) + + if len(serverSideEncryptionConfiguration) == 0 { + input := &s3.DeleteBucketEncryptionInput{ + Bucket: aws.String(d.Id()), + } + + _, err := conn.DeleteBucketEncryption(input) + + if err != nil { + return fmt.Errorf("error removing S3 Bucket (%s) Server-side Encryption: %w", d.Id(), err) + } + + return nil + } + + c := serverSideEncryptionConfiguration[0].(map[string]interface{}) + + rc := &s3.ServerSideEncryptionConfiguration{} + + rcRules := c["rule"].([]interface{}) + var rules []*s3.ServerSideEncryptionRule + for _, v := range rcRules { + rr := v.(map[string]interface{}) + rrDefault := rr["apply_server_side_encryption_by_default"].([]interface{}) + sseAlgorithm := rrDefault[0].(map[string]interface{})["sse_algorithm"].(string) + kmsMasterKeyId := rrDefault[0].(map[string]interface{})["kms_master_key_id"].(string) + rcDefaultRule := &s3.ServerSideEncryptionByDefault{ + SSEAlgorithm: aws.String(sseAlgorithm), + } + if kmsMasterKeyId != "" { + rcDefaultRule.KMSMasterKeyID = aws.String(kmsMasterKeyId) + } + rcRule := &s3.ServerSideEncryptionRule{ + ApplyServerSideEncryptionByDefault: rcDefaultRule, + } + + if val, ok := rr["bucket_key_enabled"].(bool); ok { + rcRule.BucketKeyEnabled = aws.Bool(val) + } + + rules = append(rules, rcRule) + } + + rc.Rules = rules + + input := &s3.PutBucketEncryptionInput{ + Bucket: aws.String(d.Id()), + ServerSideEncryptionConfiguration: rc, + } + + _, err := tfresource.RetryWhenAWSErrCodeEquals( + propagationTimeout, + func() (interface{}, error) { + return conn.PutBucketEncryption(input) + }, + s3.ErrCodeNoSuchBucket, + ErrCodeOperationAborted, + ) + + return err +} + func resourceBucketInternalVersioningUpdate(conn *s3.S3, bucket string, versioningConfig *s3.VersioningConfiguration) error { input := &s3.PutBucketVersioningInput{ Bucket: aws.String(bucket), diff --git a/internal/service/s3/bucket_server_side_encryption_configuration_test.go b/internal/service/s3/bucket_server_side_encryption_configuration_test.go index a3636e4472b..a0fb844f8e1 100644 --- a/internal/service/s3/bucket_server_side_encryption_configuration_test.go +++ b/internal/service/s3/bucket_server_side_encryption_configuration_test.go @@ -314,6 +314,80 @@ func TestAccS3BucketServerSideEncryptionConfiguration_ApplySSEByDefault_BucketKe }) } +func TestAccS3BucketServerSideEncryptionConfiguration_migrate_noChange(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.test" + bucketResourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckBucketServerSideEncryptionConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withDefaultEncryption_defaultKey(rName, s3.ServerSideEncryptionAwsKms), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckBucketExists(bucketResourceName), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.0.rule.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.0.sse_algorithm", s3.ServerSideEncryptionAwsKms), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.0.rule.0.bucket_key_enabled", "false"), + ), + }, + { + Config: testAccBucketServerSideEncryptionConfigurationConfig_migrate_noChange(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", bucketResourceName, "bucket"), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.apply_server_side_encryption_by_default.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.apply_server_side_encryption_by_default.0.sse_algorithm", s3.ServerSideEncryptionAwsKms), + resource.TestCheckNoResourceAttr(resourceName, "rule.0.bucket_key_enabled"), + ), + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_migrate_withChange(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.test" + bucketResourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckBucketServerSideEncryptionConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withDefaultEncryption_defaultKey(rName, s3.ServerSideEncryptionAwsKms), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckBucketExists(bucketResourceName), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.0.rule.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.0.sse_algorithm", s3.ServerSideEncryptionAwsKms), + resource.TestCheckResourceAttr(bucketResourceName, "server_side_encryption_configuration.0.rule.0.bucket_key_enabled", "false"), + ), + }, + { + Config: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_SSEAlgorithm(rName, s3.ServerSideEncryptionAes256), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", bucketResourceName, "bucket"), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.apply_server_side_encryption_by_default.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.apply_server_side_encryption_by_default.0.sse_algorithm", s3.ServerSideEncryptionAes256), + resource.TestCheckNoResourceAttr(resourceName, "rule.0.bucket_key_enabled"), + ), + }, + }, + }) +} + func testAccCheckBucketServerSideEncryptionConfigurationDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).S3Conn @@ -513,3 +587,21 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "test" { } `, rName, enabled) } + +func testAccBucketServerSideEncryptionConfigurationConfig_migrate_noChange(rName string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "test" { + bucket = aws_s3_bucket.test.id + + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "aws:kms" + } + } +} +`, rName) +} diff --git a/internal/service/s3/bucket_test.go b/internal/service/s3/bucket_test.go index 10f89f58665..28d0bb9127b 100644 --- a/internal/service/s3/bucket_test.go +++ b/internal/service/s3/bucket_test.go @@ -263,6 +263,38 @@ func TestAccS3Bucket_Basic_acceleration(t *testing.T) { }) } +func TestAccS3Bucket_Basic_keyEnabled(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix("tf-test-bucket") + resourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withDefaultEncryptionAndBucketKeyEnabled_KmsMasterKey(bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.0.sse_algorithm", "aws:kms"), + resource.TestMatchResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", regexp.MustCompile("^arn")), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.bucket_key_enabled", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + }, + }) +} + // Test TestAccS3Bucket_disappears is designed to fail with a "plan // not empty" error in Terraform, to check against regressions. // See https://github.com/hashicorp/terraform/pull/2925 @@ -1351,6 +1383,102 @@ func TestAccS3Bucket_Security_logging(t *testing.T) { }, }) } +func TestAccS3Bucket_Security_enableDefaultEncryptionWhenTypical(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix("tf-test-bucket") + resourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withDefaultEncryption_KmsMasterKey(bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.0.sse_algorithm", s3.ServerSideEncryptionAwsKms), + resource.TestMatchResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", regexp.MustCompile("^arn")), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + }, + }) +} + +func TestAccS3Bucket_Security_enableDefaultEncryptionWhenAES256IsUsed(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix("tf-test-bucket") + resourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withDefaultEncryption_defaultKey(bucketName, s3.ServerSideEncryptionAes256), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.#", "1"), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.0.sse_algorithm", s3.ServerSideEncryptionAes256), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.0.rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + }, + }) +} + +func TestAccS3Bucket_Security_disableDefaultEncryptionWhenDefaultEncryptionIsEnabled(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix("tf-test-bucket") + resourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withDefaultEncryption_defaultKey(bucketName, s3.ServerSideEncryptionAwsKms), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckBucketExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + { + // As ServerSide Encryption Configuration is a Computed field, removing them from terraform will not + // trigger an update to remove it from the S3 bucket. + Config: testAccBucketConfig_Basic(bucketName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "server_side_encryption_configuration.#", "1"), + ), + }, + }, + }) +} func TestAccS3Bucket_Web_simple(t *testing.T) { bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -2086,6 +2214,67 @@ resource "aws_s3_bucket" "test" { `, bucketName) } +func testAccBucketConfig_withDefaultEncryption_defaultKey(bucketName, sseAlgorithm string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + sse_algorithm = %[2]q + } + } + } +} +`, bucketName, sseAlgorithm) +} + +func testAccBucketConfig_withDefaultEncryption_KmsMasterKey(bucketName string) string { + return fmt.Sprintf(` +resource "aws_kms_key" "test" { + description = "KMS Key for Bucket %[1]s" + deletion_window_in_days = 10 +} + +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.test.arn + sse_algorithm = "aws:kms" + } + } + } +} +`, bucketName) +} + +func testAccBucketConfig_withDefaultEncryptionAndBucketKeyEnabled_KmsMasterKey(bucketName string) string { + return fmt.Sprintf(` +resource "aws_kms_key" "test" { + description = "KMS Key for Bucket %[1]s" + deletion_window_in_days = 7 +} + +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.test.arn + sse_algorithm = "aws:kms" + } + bucket_key_enabled = true + } + } +} +`, bucketName) +} + func testAccBucketConfig_withGrants(bucketName string) string { return fmt.Sprintf(` data "aws_canonical_user_id" "current" {} diff --git a/website/docs/r/s3_bucket.html.markdown b/website/docs/r/s3_bucket.html.markdown index 540d361a760..98fba183ff5 100644 --- a/website/docs/r/s3_bucket.html.markdown +++ b/website/docs/r/s3_bucket.html.markdown @@ -36,6 +36,10 @@ Configuring with both will cause inconsistencies and may overwrite configuration or with the deprecated parameter `logging` in the resource `aws_s3_bucket`. Configuring with both will cause inconsistencies and may overwrite configuration. +~> **NOTE on S3 Bucket Server Side Encryption Configuration:** S3 Bucket Server Side Encryption can be configured in either the standalone resource [`aws_s3_bucket_server_side_encryption_configuration`](s3_bucket_server_side_encryption_configuration.html) +or with the deprecated parameter `server_side_encryption_configuration` in the resource `aws_s3_bucket`. +Configuring with both will cause inconsistencies and may overwrite configuration. + ~> **NOTE on S3 Bucket Versioning Configuration:** S3 Bucket versioning can be configured in either the standalone resource [`aws_s3_bucket_versioning`](s3_bucket_versioning.html.markdown) or with the deprecated parameter `versioning` in the resource `aws_s3_bucket`. Configuring with both will cause inconsistencies and may overwrite configuration. @@ -241,8 +245,28 @@ See the [`aws_s3_bucket_replication_configuration` resource](s3_bucket_replicati ### Enable Default Server Side Encryption -The `server_side_encryption_configuration` argument is read-only as of version 4.0 of the Terraform AWS Provider. -See the [`aws_s3_bucket_server_side_encryption_configuration` resource](s3_bucket_server_side_encryption_configuration.html.markdown) for configuration details. +-> **NOTE:** The parameter `server_side_encryption_configuration` is deprecated. +Use the resource [`aws_s3_bucket_server_side_encryption_configuration`](s3_bucket_server_side_encryption_configuration.html) instead. + +```terraform +resource "aws_kms_key" "mykey" { + description = "This key is used to encrypt bucket objects" + deletion_window_in_days = 10 +} + +resource "aws_s3_bucket" "mybucket" { + bucket = "mybucket" + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.mykey.arn + sse_algorithm = "aws:kms" + } + } + } +} +``` ### Using ACL policy grants @@ -287,6 +311,9 @@ The following arguments are supported: Use the resource [`aws_s3_bucket_logging`](s3_bucket_logging.html.markdown) instead. * `object_lock_enabled` - (Optional, Default:`false`, Forces new resource) Indicates whether this bucket has an Object Lock configuration enabled. * `object_lock_configuration` - (Optional) A configuration of [S3 object locking](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html). See [Object Lock Configuration](#object-lock-configuration) below. +* `server_side_encryption_configuration` - (Optional, **Deprecated**) A configuration of [server-side encryption configuration](http://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html). See [Server Side Encryption Configuration](#server-side-encryption-configuration) below for details. + Terraform will only perform drift detection if a configuration value is provided. + Use the resource [`aws_s3_bucket_server_side_encryption_configuration`](s3_bucket_server_side_encryption_configuration.html) instead. * `versioning` - (Optional, **Deprecated**) A configuration of the [S3 bucket versioning state](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html). See [Versioning](#versioning) below for details. Terraform will only perform drift detection if a configuration value is provided. Use the resource [`aws_s3_bucket_versioning`](s3_bucket_versioning.html.markdown) instead. * `website` - (Optional, **Deprecated**) A configuration of the [S3 bucket website](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html). See [Website](#website) below for details. Terraform will only perform drift detection if a configuration value is provided. Use the resource [`aws_s3_bucket_website_configuration`](s3_bucket_website_configuration.html.markdown) instead. @@ -382,6 +409,24 @@ The `object_lock_configuration` configuration block supports the following argum * `object_lock_enabled` - (Optional, **Deprecated**) Indicates whether this bucket has an Object Lock configuration enabled. Valid value is `Enabled`. Use the top-level argument `object_lock_enabled` instead. +### Server Side Encryption Configuration + +~> **NOTE:** Currently, changes to the `server_side_encryption_configuration` configuration of _existing_ resources cannot be automatically detected by Terraform. To manage changes in encryption of an S3 bucket, use the `aws_s3_bucket_server_side_encryption_configuration` resource instead. If you use `server_side_encryption_configuration` on an `aws_s3_bucket`, Terraform will assume management over the encryption configuration for the S3 bucket, treating additional encryption changes as drift. For this reason, `server_side_encryption_configuration` cannot be mixed with the external `aws_s3_bucket_server_side_encryption_configuration` resource for a given S3 bucket. + +The `server_side_encryption_configuration` configuration block supports the following argument: + +* `rule` - (Required) A single object for server-side encryption by default configuration. (documented below) + +The `rule` configuration block supports the following arguments: + +* `apply_server_side_encryption_by_default` - (Required) A single object for setting server-side encryption by default. (documented below) +* `bucket_key_enabled` - (Optional) Whether or not to use [Amazon S3 Bucket Keys](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-key.html) for SSE-KMS. + +The `apply_server_side_encryption_by_default` configuration block supports the following arguments: + +* `sse_algorithm` - (Required) The server-side encryption algorithm to use. Valid values are `AES256` and `aws:kms` +* `kms_master_key_id` - (Optional) The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of `sse_algorithm` as `aws:kms`. The default `aws/s3` AWS KMS master key is used if this element is absent while the `sse_algorithm` is `aws:kms`. + ### Versioning ~> **NOTE:** Currently, changes to the `versioning` configuration of _existing_ resources cannot be automatically detected by Terraform. To manage changes of versioning state to an S3 bucket, use the `aws_s3_bucket_versioning` resource instead. If you use `versioning` on an `aws_s3_bucket`, Terraform will assume management over the versioning state of the S3 bucket, treating additional versioning state changes as drift. For this reason, `versioning` cannot be mixed with the external `aws_s3_bucket_versioning` resource for a given S3 bucket. @@ -448,12 +493,6 @@ In addition to all arguments above, the following attributes are exported: * `enabled` - Whether this criteria is enabled. * `status` - The status of the rule. * `request_payer` - Either `BucketOwner` or `Requester` that pays for the download and request fees. -* `server_side_encryption_configuration` - The [server-side encryption configuration](http://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html). - * `rule` - (required) Information about a particular server-side encryption configuration rule. - * `apply_server_side_encryption_by_default` - The default server-side encryption applied to new objects in the bucket. - * `kms_master_key_id` - (optional) The AWS KMS master key ID used for the SSE-KMS encryption. - * `sse_algorithm` - (required) The server-side encryption algorithm used. - * `bucket_key_enabled` - (Optional) Whether an [Amazon S3 Bucket Key](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-key.html) is used for SSE-KMS. * `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). * `website_endpoint` - The website endpoint, if the bucket is configured with a website. If not, this will be an empty string. * `website_domain` - The domain of the website endpoint, if the bucket is configured with a website. If not, this will be an empty string. This is used to create Route 53 alias records. From bd5e9b29f43d40bc5aa751800ffcc2bb8fddc9cc Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 23 Mar 2022 02:01:08 -0400 Subject: [PATCH 2/2] Update CHANGELOG for #23822 --- .changelog/23822.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/23822.txt diff --git a/.changelog/23822.txt b/.changelog/23822.txt new file mode 100644 index 00000000000..aeadeacdf08 --- /dev/null +++ b/.changelog/23822.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_s3_bucket: Update `server_side_encryption_configuration` parameter to be configurable. Please refer to the documentation for details on drift detection and potential conflicts when configuring this parameter with the standalone `aws_s3_bucket_server_side_encryption_configuration` resource. +``` \ No newline at end of file