Skip to content

Commit

Permalink
Merge pull request #23822 from hashicorp/s3-sse-config
Browse files Browse the repository at this point in the history
r/s3_bucket: make `server_side_encryption_configuration` configurable
  • Loading branch information
anGie44 committed Apr 1, 2022
2 parents a5f8a1b + bd5e9b2 commit e9c95ee
Show file tree
Hide file tree
Showing 5 changed files with 416 additions and 23 deletions.
3 changes: 3 additions & 0 deletions .changelog/23822.txt
Original file line number Diff line number Diff line change
@@ -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.
```
100 changes: 85 additions & 15 deletions internal/service/s3/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
},
Expand Down Expand Up @@ -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{})

Expand Down Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
}
Loading

0 comments on commit e9c95ee

Please sign in to comment.