From 1dbfe8ac39394e535cd4ad199ba605d8f29c2451 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 26 Jan 2022 17:24:38 -0500 Subject: [PATCH 1/8] r/s3_bucket_server_side_encryption_configuration: new resource --- internal/service/s3/bucket.go | 4 +- ...et_server_side_encryption_configuration.go | 342 +++++++++++ ...rver_side_encryption_configuration_test.go | 533 ++++++++++++++++++ ...ide_encryption_configuration.html.markdown | 77 +++ 4 files changed, 954 insertions(+), 2 deletions(-) create mode 100644 internal/service/s3/bucket_server_side_encryption_configuration.go create mode 100644 internal/service/s3/bucket_server_side_encryption_configuration_test.go create mode 100644 website/docs/r/s3_bucket_server_side_encryption_configuration.html.markdown diff --git a/internal/service/s3/bucket.go b/internal/service/s3/bucket.go index 96e5a9c701e..1703b68ddd6 100644 --- a/internal/service/s3/bucket.go +++ b/internal/service/s3/bucket.go @@ -836,7 +836,7 @@ func resourceBucketUpdate(d *schema.ResourceData, meta interface{}) error { } if d.HasChange("server_side_encryption_configuration") { - if err := resourceBucketServerSideEncryptionConfigurationUpdate(conn, d); err != nil { + if err := resourceBucketInternalServerSideEncryptionConfigurationUpdate(conn, d); err != nil { return err } } @@ -1947,7 +1947,7 @@ func resourceBucketRequestPayerUpdate(conn *s3.S3, d *schema.ResourceData) error return nil } -func resourceBucketServerSideEncryptionConfigurationUpdate(conn *s3.S3, d *schema.ResourceData) error { +func resourceBucketInternalServerSideEncryptionConfigurationUpdate(conn *s3.S3, d *schema.ResourceData) error { bucket := d.Get("bucket").(string) serverSideEncryptionConfiguration := d.Get("server_side_encryption_configuration").([]interface{}) if len(serverSideEncryptionConfiguration) == 0 { diff --git a/internal/service/s3/bucket_server_side_encryption_configuration.go b/internal/service/s3/bucket_server_side_encryption_configuration.go new file mode 100644 index 00000000000..40aff5d745f --- /dev/null +++ b/internal/service/s3/bucket_server_side_encryption_configuration.go @@ -0,0 +1,342 @@ +package s3 + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/s3" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" +) + +func ResourceBucketServerSideEncryptionConfiguration() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceBucketServerSideEncryptionConfigurationCreate, + ReadContext: resourceBucketServerSideEncryptionConfigurationRead, + UpdateContext: resourceBucketServerSideEncryptionConfigurationUpdate, + DeleteContext: resourceBucketServerSideEncryptionConfigurationDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "bucket": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 63), + }, + "expected_bucket_owner": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidAccountID, + }, + "rule": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "apply_server_side_encryption_by_default": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "kms_master_key_id": { + Type: schema.TypeString, + Optional: true, + }, + "sse_algorithm": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(s3.ServerSideEncryption_Values(), false), + }, + }, + }, + }, + "bucket_key_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + }, + } +} + +func resourceBucketServerSideEncryptionConfigurationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).S3Conn + + bucket := d.Get("bucket").(string) + expectedBucketOwner := d.Get("expected_bucket_owner").(string) + + input := &s3.PutBucketEncryptionInput{ + Bucket: aws.String(bucket), + ServerSideEncryptionConfiguration: &s3.ServerSideEncryptionConfiguration{ + Rules: expandBucketServerSideEncryptionConfigurationRules(d.Get("rule").(*schema.Set).List()), + }, + } + + if expectedBucketOwner != "" { + input.ExpectedBucketOwner = aws.String(expectedBucketOwner) + } + + _, err := tfresource.RetryWhenAWSErrCodeEquals( + propagationTimeout, + func() (interface{}, error) { + return conn.PutBucketEncryptionWithContext(ctx, input) + }, + s3.ErrCodeNoSuchBucket, + ErrCodeOperationAborted, + ) + + if err != nil { + return diag.FromErr(fmt.Errorf("error creating S3 bucket (%s) server-side encryption configuration: %w", bucket, err)) + } + + d.SetId(resourceBucketServerSideEncryptionConfigurationCreateResourceID(bucket, expectedBucketOwner)) + + return resourceBucketServerSideEncryptionConfigurationRead(ctx, d, meta) +} + +func resourceBucketServerSideEncryptionConfigurationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).S3Conn + + bucket, expectedBucketOwner, err := resourceBucketServerSideEncryptionConfigurationParseResourceID(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + input := &s3.GetBucketEncryptionInput{ + Bucket: aws.String(bucket), + } + + if expectedBucketOwner != "" { + input.ExpectedBucketOwner = aws.String(expectedBucketOwner) + } + + resp, err := verify.RetryOnAWSCode(s3.ErrCodeNoSuchBucket, func() (interface{}, error) { + return conn.GetBucketEncryptionWithContext(ctx, input) + }) + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, s3.ErrCodeNoSuchBucket, ErrCodeServerSideEncryptionConfigurationNotFound) { + log.Printf("[WARN] S3 Bucket Server-Side Encryption Configuration (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return diag.FromErr(fmt.Errorf("error reading S3 bucket server-side encryption configuration (%s): %w", d.Id(), err)) + } + + output, ok := resp.(*s3.GetBucketEncryptionOutput) + if !ok || output.ServerSideEncryptionConfiguration == nil { + if d.IsNewResource() { + return diag.FromErr(fmt.Errorf("error reading S3 bucket server-side encryption configuration (%s): empty output", d.Id())) + } + log.Printf("[WARN] S3 Bucket Server-Side Encryption Configuration (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + sse := output.ServerSideEncryptionConfiguration + + d.Set("bucket", bucket) + d.Set("expected_bucket_owner", expectedBucketOwner) + if err := d.Set("rule", flattenBucketServerSideEncryptionConfigurationRules(sse.Rules)); err != nil { + return diag.FromErr(fmt.Errorf("error setting rule: %w", err)) + } + + return nil +} + +func resourceBucketServerSideEncryptionConfigurationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).S3Conn + + bucket, expectedBucketOwner, err := resourceBucketServerSideEncryptionConfigurationParseResourceID(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + input := &s3.PutBucketEncryptionInput{ + Bucket: aws.String(bucket), + ServerSideEncryptionConfiguration: &s3.ServerSideEncryptionConfiguration{ + Rules: expandBucketServerSideEncryptionConfigurationRules(d.Get("rule").(*schema.Set).List()), + }, + } + + if expectedBucketOwner != "" { + input.ExpectedBucketOwner = aws.String(expectedBucketOwner) + } + + _, err = tfresource.RetryWhenAWSErrCodeEquals( + propagationTimeout, + func() (interface{}, error) { + return conn.PutBucketEncryptionWithContext(ctx, input) + }, + s3.ErrCodeNoSuchBucket, + ErrCodeOperationAborted, + ) + + if err != nil { + return diag.FromErr(fmt.Errorf("error updating S3 bucket (%s) server-side encryption configuration: %w", d.Id(), err)) + } + + return resourceBucketServerSideEncryptionConfigurationRead(ctx, d, meta) +} + +func resourceBucketServerSideEncryptionConfigurationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).S3Conn + + bucket, expectedBucketOwner, err := resourceBucketServerSideEncryptionConfigurationParseResourceID(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + input := &s3.DeleteBucketEncryptionInput{ + Bucket: aws.String(bucket), + } + + if expectedBucketOwner != "" { + input.ExpectedBucketOwner = aws.String(expectedBucketOwner) + } + + _, err = conn.DeleteBucketEncryptionWithContext(ctx, input) + + if tfawserr.ErrCodeEquals(err, s3.ErrCodeNoSuchBucket, ErrCodeServerSideEncryptionConfigurationNotFound) { + return nil + } + + if err != nil { + return diag.FromErr(fmt.Errorf("error deleting S3 bucket server-side encryption configuration (%s): %w", d.Id(), err)) + } + + return nil +} + +func resourceBucketServerSideEncryptionConfigurationCreateResourceID(bucket, expectedBucketOwner string) string { + if bucket == "" { + return expectedBucketOwner + } + + if expectedBucketOwner == "" { + return bucket + } + + parts := []string{bucket, expectedBucketOwner} + id := strings.Join(parts, ",") + + return id +} + +func resourceBucketServerSideEncryptionConfigurationParseResourceID(id string) (string, string, error) { + parts := strings.Split(id, ",") + + if len(parts) == 1 && parts[0] != "" { + return parts[0], "", nil + } + + if len(parts) == 2 && parts[0] != "" && parts[1] != "" { + return parts[0], parts[1], nil + } + + return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected BUCKET or BUCKET,EXPECTED_BUCKET_OWNER", id) +} + +func expandBucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefault(l []interface{}) *s3.ServerSideEncryptionByDefault { + if len(l) == 0 || l[0] == nil { + return nil + } + + tfMap, ok := l[0].(map[string]interface{}) + if !ok { + return nil + } + + sse := &s3.ServerSideEncryptionByDefault{} + + if v, ok := tfMap["kms_master_key_id"].(string); ok && v != "" { + sse.KMSMasterKeyID = aws.String(v) + } + + if v, ok := tfMap["sse_algorithm"].(string); ok && v != "" { + sse.SSEAlgorithm = aws.String(v) + } + + return sse +} + +func expandBucketServerSideEncryptionConfigurationRules(l []interface{}) []*s3.ServerSideEncryptionRule { + var rules []*s3.ServerSideEncryptionRule + + for _, tfMapRaw := range l { + tfMap, ok := tfMapRaw.(map[string]interface{}) + if !ok { + continue + } + + rule := &s3.ServerSideEncryptionRule{} + + if v, ok := tfMap["apply_server_side_encryption_by_default"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + rule.ApplyServerSideEncryptionByDefault = expandBucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefault(v) + } + + if v, ok := tfMap["bucket_key_enabled"].(bool); ok { + rule.BucketKeyEnabled = aws.Bool(v) + } + rules = append(rules, rule) + } + + return rules +} + +func flattenBucketServerSideEncryptionConfigurationRules(rules []*s3.ServerSideEncryptionRule) []interface{} { + var results []interface{} + + for _, rule := range rules { + if rule == nil { + continue + } + + m := make(map[string]interface{}) + + if rule.ApplyServerSideEncryptionByDefault != nil { + m["apply_server_side_encryption_by_default"] = flattenBucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefault(rule.ApplyServerSideEncryptionByDefault) + } + if rule.BucketKeyEnabled != nil { + m["bucket_key_enabled"] = aws.BoolValue(rule.BucketKeyEnabled) + } + + results = append(results, m) + } + + return results +} + +func flattenBucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefault(sse *s3.ServerSideEncryptionByDefault) []interface{} { + if sse == nil { + return []interface{}{} + } + + m := make(map[string]interface{}) + + if sse.KMSMasterKeyID != nil { + m["kms_master_key_id"] = aws.StringValue(sse.KMSMasterKeyID) + } + + if sse.SSEAlgorithm != nil { + m["sse_algorithm"] = aws.StringValue(sse.SSEAlgorithm) + } + + return []interface{}{m} +} diff --git a/internal/service/s3/bucket_server_side_encryption_configuration_test.go b/internal/service/s3/bucket_server_side_encryption_configuration_test.go new file mode 100644 index 00000000000..c7fdde7b433 --- /dev/null +++ b/internal/service/s3/bucket_server_side_encryption_configuration_test.go @@ -0,0 +1,533 @@ +package s3_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/s3" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfs3 "github.com/hashicorp/terraform-provider-aws/internal/service/s3" +) + +func TestAccS3BucketServerSideEncryptionConfiguration_basic(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationBasicConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", "aws_s3_bucket.test", "bucket"), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.apply_server_side_encryption_by_default.#", "0"), + resource.TestCheckNoResourceAttr(resourceName, "rule.0.bucket_key_enabled"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_disappears(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationBasicConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + acctest.CheckResourceDisappears(acctest.Provider, tfs3.ResourceBucketServerSideEncryptionConfiguration(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_ApplySEEByDefault_AES256(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_SSEAlgorithm(rName, s3.ServerSideEncryptionAes256), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + 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.TestCheckResourceAttr(resourceName, "rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_ApplySSEByDefault_KMS(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_SSEAlgorithm(rName, s3.ServerSideEncryptionAwsKms), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + 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.TestCheckResourceAttr(resourceName, "rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_ApplySSEByDefault_UpdateSSEAlgorithm(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_SSEAlgorithm(rName, s3.ServerSideEncryptionAwsKms), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + 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), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_SSEAlgorithm(rName, s3.ServerSideEncryptionAes256), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + 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), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_ApplySSEByDefault_KMSWithMasterKeyArn(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_KMSWithMasterKeyArn(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + 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.TestCheckResourceAttrPair(resourceName, "rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", "aws_kms_key.test", "arn"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_ApplySSEByDefault_KMSWithMasterKeyID(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_KMSWithMasterKeyID(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + 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.TestCheckResourceAttrPair(resourceName, "rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", "aws_kms_key.test", "id"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_BucketKeyEnabled(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationConfig_BucketKeyEnabled(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", "aws_s3_bucket.test", "bucket"), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.bucket_key_enabled", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBucketServerSideEncryptionConfigurationConfig_BucketKeyEnabled(rName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", "aws_s3_bucket.test", "bucket"), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.bucket_key_enabled", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccS3BucketServerSideEncryptionConfiguration_ApplySSEByDefault_BucketKeyEnabled(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_server_side_encryption_configuration.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: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_BucketKeyEnabled(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", "aws_s3_bucket.test", "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.TestCheckResourceAttrPair(resourceName, "rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", "aws_kms_key.test", "id"), + resource.TestCheckResourceAttr(resourceName, "rule.0.bucket_key_enabled", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_BucketKeyEnabled(rName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", "aws_s3_bucket.test", "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.TestCheckResourceAttrPair(resourceName, "rule.0.apply_server_side_encryption_by_default.0.kms_master_key_id", "aws_kms_key.test", "id"), + resource.TestCheckResourceAttr(resourceName, "rule.0.bucket_key_enabled", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckBucketServerSideEncryptionConfigurationDestroy(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).S3Conn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_s3_bucket_server_side_encryption_configuration" { + continue + } + + input := &s3.GetBucketEncryptionInput{ + Bucket: aws.String(rs.Primary.ID), + } + + output, err := conn.GetBucketEncryption(input) + + if tfawserr.ErrCodeEquals(err, s3.ErrCodeNoSuchBucket, tfs3.ErrCodeServerSideEncryptionConfigurationNotFound) { + continue + } + + if err != nil { + return fmt.Errorf("error getting S3 Bucket server-side encryption configuration (%s): %w", rs.Primary.ID, err) + } + + if output != nil && output.ServerSideEncryptionConfiguration != nil { + return fmt.Errorf("S3 Bucket server-side encryption configuration (%s) still exists", rs.Primary.ID) + } + } + + return nil +} + +func testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("Resource (%s) ID not set", resourceName) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).S3Conn + + input := &s3.GetBucketEncryptionInput{ + Bucket: aws.String(rs.Primary.ID), + } + + output, err := conn.GetBucketEncryption(input) + + if err != nil { + return fmt.Errorf("error getting S3 Bucket server-side encryption configuration (%s): %w", rs.Primary.ID, err) + } + + if output == nil || output.ServerSideEncryptionConfiguration == nil { + return fmt.Errorf("S3 Bucket server-side encryption configuration (%s) not found", rs.Primary.ID) + } + + return nil + } +} + +func testAccBucketServerSideEncryptionConfigurationBasicConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + lifecycle { + ignore_changes = [ + server_side_encryption_configuration + ] + } +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "test" { + bucket = aws_s3_bucket.test.id + + rule {} +} +`, rName) +} + +func testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_KMSWithMasterKeyArn(rName 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 + + lifecycle { + ignore_changes = [ + server_side_encryption_configuration + ] + } +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "test" { + bucket = aws_s3_bucket.test.id + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.test.arn + sse_algorithm = "aws:kms" + } + } +} +`, rName) +} + +func testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_KMSWithMasterKeyID(rName 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 + + lifecycle { + ignore_changes = [ + server_side_encryption_configuration + ] + } +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "test" { + bucket = aws_s3_bucket.test.id + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.test.id + sse_algorithm = "aws:kms" + } + } +} +`, rName) +} + +func testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_SSEAlgorithm(rName, sseAlgorithm string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + lifecycle { + ignore_changes = [ + server_side_encryption_configuration + ] + } +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "test" { + bucket = aws_s3_bucket.test.id + + rule { + apply_server_side_encryption_by_default { + sse_algorithm = %[2]q + } + } +} +`, rName, sseAlgorithm) +} + +func testAccBucketServerSideEncryptionConfigurationConfig_BucketKeyEnabled(rName string, enabled bool) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + lifecycle { + ignore_changes = [ + server_side_encryption_configuration + ] + } +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "test" { + bucket = aws_s3_bucket.test.id + + rule { + bucket_key_enabled = %[2]t + } +} +`, rName, enabled) +} + +func testAccBucketServerSideEncryptionConfigurationConfig_ApplySSEByDefault_BucketKeyEnabled(rName string, enabled bool) 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 + + lifecycle { + ignore_changes = [ + server_side_encryption_configuration + ] + } +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "test" { + bucket = aws_s3_bucket.test.id + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.test.id + sse_algorithm = "aws:kms" + } + bucket_key_enabled = %[2]t + } +} +`, rName, enabled) +} diff --git a/website/docs/r/s3_bucket_server_side_encryption_configuration.html.markdown b/website/docs/r/s3_bucket_server_side_encryption_configuration.html.markdown new file mode 100644 index 00000000000..554490d7a63 --- /dev/null +++ b/website/docs/r/s3_bucket_server_side_encryption_configuration.html.markdown @@ -0,0 +1,77 @@ +--- +subcategory: "S3" +layout: "aws" +page_title: "AWS: aws_s3_bucket_server_side_encryption configuration" +description: |- + Provides a S3 bucket server-side encryption configuration resource. +--- + +# Resource: aws_s3_bucket_server_side_encryption_configuration + +Provides a S3 bucket server-side encryption configuration resource. + +## Example Usage + +```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" +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "example" { + bucket = aws_s3_bucket.mybucket.bucket + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.mykey.arn + sse_algorithm = "aws:kms" + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `bucket` - (Required, Forces new resource) The name of the bucket. +* `expected_bucket_owner` - (Optional, Forces new resource) The account ID of the expected bucket owner. +* `rule` - (Required) Set of server-side encryption configuration rules. [documented below](#rule). Currently, only a single rule is supported. + +### rule + +The `rule` configuration block supports the following arguments: + +* `apply_server_side_encryption_by_default` - (Optional) A single object for setting server-side encryption by default [documented below](#apply_server_side_encryption_by_default) +* `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. + +### apply_server_side_encryption_by_default + +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`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The `bucket` or `bucket` and `expected_bucket_owner` separated by a comma (`,`) if the latter is provided. + +## Import + +S3 bucket server-side encryption configuration can be imported using the `bucket` e.g., + +``` +$ terraform import aws_s3_bucket_server_side_encryption_configuration.example bucket-name +``` + +In addition, S3 bucket server-side encryption configuration can be imported using the `bucket` and `expected_bucket_owner` separated by a comma (`,`) e.g., + +``` +$ terraform import aws_s3_bucket_server_side_encryption_configuration.example bucket-name,123456789012 +``` From c1de9723ae634afb6e8aa5a3ebbd8a9ab4c686c4 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Sat, 15 Jan 2022 20:08:19 -0500 Subject: [PATCH 2/8] Update CHANGELOG for #22609 --- .changelog/22609.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/22609.txt diff --git a/.changelog/22609.txt b/.changelog/22609.txt new file mode 100644 index 00000000000..e3b7150c72c --- /dev/null +++ b/.changelog/22609.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_s3_bucket_server_side_encryption_configuration +``` \ No newline at end of file From dd8b653fe4f1a6975b7e4d41132ff5a1766a0b0d Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Sat, 15 Jan 2022 20:12:22 -0500 Subject: [PATCH 3/8] fix with terrafmt --- .../s3/bucket_server_side_encryption_configuration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c7fdde7b433..5a109dfa862 100644 --- a/internal/service/s3/bucket_server_side_encryption_configuration_test.go +++ b/internal/service/s3/bucket_server_side_encryption_configuration_test.go @@ -526,7 +526,7 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "test" { kms_master_key_id = aws_kms_key.test.id sse_algorithm = "aws:kms" } - bucket_key_enabled = %[2]t + bucket_key_enabled = %[2]t } } `, rName, enabled) From 7288456e2a24ff4dc84ab4153736429b3795bcf1 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 2 Feb 2022 20:22:03 -0500 Subject: [PATCH 4/8] add missing error code --- internal/service/s3/errors.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/service/s3/errors.go b/internal/service/s3/errors.go index 65cdef8d9ac..574d5fd7c35 100644 --- a/internal/service/s3/errors.go +++ b/internal/service/s3/errors.go @@ -11,4 +11,5 @@ const ( ErrCodeNoSuchWebsiteConfiguration = "NoSuchWebsiteConfiguration" ErrCodeObjectLockConfigurationNotFound = "ObjectLockConfigurationNotFoundError" ErrCodeOperationAborted = "OperationAborted" + ErrCodeServerSideEncryptionConfigurationNotFound = "ServerSideEncryptionConfigurationNotFoundError" ) From 2ad9cd46f171ba254b9359c8b5741cb803bb405d Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 2 Feb 2022 21:00:44 -0500 Subject: [PATCH 5/8] update imports referencing tfawserr --- .../service/s3/bucket_server_side_encryption_configuration.go | 2 +- .../s3/bucket_server_side_encryption_configuration_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/s3/bucket_server_side_encryption_configuration.go b/internal/service/s3/bucket_server_side_encryption_configuration.go index 40aff5d745f..08ae223510c 100644 --- a/internal/service/s3/bucket_server_side_encryption_configuration.go +++ b/internal/service/s3/bucket_server_side_encryption_configuration.go @@ -8,7 +8,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3" - "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 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 5a109dfa862..b359f0455be 100644 --- a/internal/service/s3/bucket_server_side_encryption_configuration_test.go +++ b/internal/service/s3/bucket_server_side_encryption_configuration_test.go @@ -6,7 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3" - "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" From b0f918402ee861a250a35cf813cc6afae36ee3e4 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Thu, 3 Feb 2022 01:38:54 -0500 Subject: [PATCH 6/8] r/s3_bucket_server_side_encryption_configuration: re-use share id create/parse method --- ...et_server_side_encryption_configuration.go | 38 ++----------------- ...rver_side_encryption_configuration_test.go | 22 ++++++++++- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/internal/service/s3/bucket_server_side_encryption_configuration.go b/internal/service/s3/bucket_server_side_encryption_configuration.go index 08ae223510c..82c54537658 100644 --- a/internal/service/s3/bucket_server_side_encryption_configuration.go +++ b/internal/service/s3/bucket_server_side_encryption_configuration.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "log" - "strings" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3" @@ -104,7 +103,7 @@ func resourceBucketServerSideEncryptionConfigurationCreate(ctx context.Context, return diag.FromErr(fmt.Errorf("error creating S3 bucket (%s) server-side encryption configuration: %w", bucket, err)) } - d.SetId(resourceBucketServerSideEncryptionConfigurationCreateResourceID(bucket, expectedBucketOwner)) + d.SetId(CreateResourceID(bucket, expectedBucketOwner)) return resourceBucketServerSideEncryptionConfigurationRead(ctx, d, meta) } @@ -112,7 +111,7 @@ func resourceBucketServerSideEncryptionConfigurationCreate(ctx context.Context, func resourceBucketServerSideEncryptionConfigurationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.AWSClient).S3Conn - bucket, expectedBucketOwner, err := resourceBucketServerSideEncryptionConfigurationParseResourceID(d.Id()) + bucket, expectedBucketOwner, err := ParseResourceID(d.Id()) if err != nil { return diag.FromErr(err) } @@ -163,7 +162,7 @@ func resourceBucketServerSideEncryptionConfigurationRead(ctx context.Context, d func resourceBucketServerSideEncryptionConfigurationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.AWSClient).S3Conn - bucket, expectedBucketOwner, err := resourceBucketServerSideEncryptionConfigurationParseResourceID(d.Id()) + bucket, expectedBucketOwner, err := ParseResourceID(d.Id()) if err != nil { return diag.FromErr(err) } @@ -198,7 +197,7 @@ func resourceBucketServerSideEncryptionConfigurationUpdate(ctx context.Context, func resourceBucketServerSideEncryptionConfigurationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.AWSClient).S3Conn - bucket, expectedBucketOwner, err := resourceBucketServerSideEncryptionConfigurationParseResourceID(d.Id()) + bucket, expectedBucketOwner, err := ParseResourceID(d.Id()) if err != nil { return diag.FromErr(err) } @@ -224,35 +223,6 @@ func resourceBucketServerSideEncryptionConfigurationDelete(ctx context.Context, return nil } -func resourceBucketServerSideEncryptionConfigurationCreateResourceID(bucket, expectedBucketOwner string) string { - if bucket == "" { - return expectedBucketOwner - } - - if expectedBucketOwner == "" { - return bucket - } - - parts := []string{bucket, expectedBucketOwner} - id := strings.Join(parts, ",") - - return id -} - -func resourceBucketServerSideEncryptionConfigurationParseResourceID(id string) (string, string, error) { - parts := strings.Split(id, ",") - - if len(parts) == 1 && parts[0] != "" { - return parts[0], "", nil - } - - if len(parts) == 2 && parts[0] != "" && parts[1] != "" { - return parts[0], parts[1], nil - } - - return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected BUCKET or BUCKET,EXPECTED_BUCKET_OWNER", id) -} - func expandBucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefault(l []interface{}) *s3.ServerSideEncryptionByDefault { if len(l) == 0 || l[0] == nil { return nil 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 b359f0455be..4ef86aca5b0 100644 --- a/internal/service/s3/bucket_server_side_encryption_configuration_test.go +++ b/internal/service/s3/bucket_server_side_encryption_configuration_test.go @@ -322,8 +322,17 @@ func testAccCheckBucketServerSideEncryptionConfigurationDestroy(s *terraform.Sta continue } + bucket, expectedBucketOwner, err := tfs3.ParseResourceID(rs.Primary.ID) + if err != nil { + return err + } + input := &s3.GetBucketEncryptionInput{ - Bucket: aws.String(rs.Primary.ID), + Bucket: aws.String(bucket), + } + + if expectedBucketOwner != "" { + input.ExpectedBucketOwner = aws.String(expectedBucketOwner) } output, err := conn.GetBucketEncryption(input) @@ -357,8 +366,17 @@ func testAccCheckBucketServerSideEncryptionConfigurationExists(resourceName stri conn := acctest.Provider.Meta().(*conns.AWSClient).S3Conn + bucket, expectedBucketOwner, err := tfs3.ParseResourceID(rs.Primary.ID) + if err != nil { + return err + } + input := &s3.GetBucketEncryptionInput{ - Bucket: aws.String(rs.Primary.ID), + Bucket: aws.String(bucket), + } + + if expectedBucketOwner != "" { + input.ExpectedBucketOwner = aws.String(expectedBucketOwner) } output, err := conn.GetBucketEncryption(input) From 42e02c2a00c029aa89391783e8b9c06c184e587d Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Thu, 3 Feb 2022 01:41:47 -0500 Subject: [PATCH 7/8] provider: add back in the new resource --- internal/provider/provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index b472e1ba309..da1105c54e3 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1636,6 +1636,7 @@ func Provider() *schema.Provider { "aws_s3_bucket_public_access_block": s3.ResourceBucketPublicAccessBlock(), "aws_s3_bucket_replication_configuration": s3.ResourceBucketReplicationConfiguration(), "aws_s3_bucket_request_payment_configuration": s3.ResourceBucketRequestPaymentConfiguration(), + "aws_s3_bucket_server_side_encryption_configuration": s3.ResourceBucketServerSideEncryptionConfiguration(), "aws_s3_bucket_versioning": s3.ResourceBucketVersioning(), "aws_s3_bucket_website_configuration": s3.ResourceBucketWebsiteConfiguration(), "aws_s3_object": s3.ResourceObject(), From c86f571d5d8fd2e29b177419c9f23be48362eb1b Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Thu, 3 Feb 2022 13:44:21 -0500 Subject: [PATCH 8/8] run gofmt after rebase --- internal/provider/provider.go | 42 +++++++++++++++++------------------ internal/service/s3/errors.go | 14 ++++++------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index da1105c54e3..33cd8969176 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1620,28 +1620,28 @@ func Provider() *schema.Provider { "aws_route53_resolver_rule": route53resolver.ResourceRule(), "aws_route53_resolver_rule_association": route53resolver.ResourceRuleAssociation(), - "aws_s3_bucket": s3.ResourceBucket(), - "aws_s3_bucket_accelerate_configuration": s3.ResourceBucketAccelerateConfiguration(), - "aws_s3_bucket_analytics_configuration": s3.ResourceBucketAnalyticsConfiguration(), - "aws_s3_bucket_cors_configuration": s3.ResourceBucketCorsConfiguration(), - "aws_s3_bucket_intelligent_tiering_configuration": s3.ResourceBucketIntelligentTieringConfiguration(), - "aws_s3_bucket_inventory": s3.ResourceBucketInventory(), - "aws_s3_bucket_lifecycle_configuration": s3.ResourceBucketLifecycleConfiguration(), - "aws_s3_bucket_logging": s3.ResourceBucketLogging(), - "aws_s3_bucket_metric": s3.ResourceBucketMetric(), - "aws_s3_bucket_notification": s3.ResourceBucketNotification(), - "aws_s3_bucket_object_lock_configuration": s3.ResourceBucketObjectLockConfiguration(), - "aws_s3_bucket_ownership_controls": s3.ResourceBucketOwnershipControls(), - "aws_s3_bucket_policy": s3.ResourceBucketPolicy(), - "aws_s3_bucket_public_access_block": s3.ResourceBucketPublicAccessBlock(), - "aws_s3_bucket_replication_configuration": s3.ResourceBucketReplicationConfiguration(), - "aws_s3_bucket_request_payment_configuration": s3.ResourceBucketRequestPaymentConfiguration(), + "aws_s3_bucket": s3.ResourceBucket(), + "aws_s3_bucket_accelerate_configuration": s3.ResourceBucketAccelerateConfiguration(), + "aws_s3_bucket_analytics_configuration": s3.ResourceBucketAnalyticsConfiguration(), + "aws_s3_bucket_cors_configuration": s3.ResourceBucketCorsConfiguration(), + "aws_s3_bucket_intelligent_tiering_configuration": s3.ResourceBucketIntelligentTieringConfiguration(), + "aws_s3_bucket_inventory": s3.ResourceBucketInventory(), + "aws_s3_bucket_lifecycle_configuration": s3.ResourceBucketLifecycleConfiguration(), + "aws_s3_bucket_logging": s3.ResourceBucketLogging(), + "aws_s3_bucket_metric": s3.ResourceBucketMetric(), + "aws_s3_bucket_notification": s3.ResourceBucketNotification(), + "aws_s3_bucket_object_lock_configuration": s3.ResourceBucketObjectLockConfiguration(), + "aws_s3_bucket_ownership_controls": s3.ResourceBucketOwnershipControls(), + "aws_s3_bucket_policy": s3.ResourceBucketPolicy(), + "aws_s3_bucket_public_access_block": s3.ResourceBucketPublicAccessBlock(), + "aws_s3_bucket_replication_configuration": s3.ResourceBucketReplicationConfiguration(), + "aws_s3_bucket_request_payment_configuration": s3.ResourceBucketRequestPaymentConfiguration(), "aws_s3_bucket_server_side_encryption_configuration": s3.ResourceBucketServerSideEncryptionConfiguration(), - "aws_s3_bucket_versioning": s3.ResourceBucketVersioning(), - "aws_s3_bucket_website_configuration": s3.ResourceBucketWebsiteConfiguration(), - "aws_s3_object": s3.ResourceObject(), - "aws_s3_object_copy": s3.ResourceObjectCopy(), - "aws_s3_bucket_object": s3.ResourceBucketObject(), // DEPRECATED: use aws_s3_object instead + "aws_s3_bucket_versioning": s3.ResourceBucketVersioning(), + "aws_s3_bucket_website_configuration": s3.ResourceBucketWebsiteConfiguration(), + "aws_s3_object": s3.ResourceObject(), + "aws_s3_object_copy": s3.ResourceObjectCopy(), + "aws_s3_bucket_object": s3.ResourceBucketObject(), // DEPRECATED: use aws_s3_object instead "aws_s3_access_point": s3control.ResourceAccessPoint(), "aws_s3control_access_point_policy": s3control.ResourceAccessPointPolicy(), diff --git a/internal/service/s3/errors.go b/internal/service/s3/errors.go index 574d5fd7c35..19315f7339b 100644 --- a/internal/service/s3/errors.go +++ b/internal/service/s3/errors.go @@ -4,12 +4,12 @@ package s3 // https://docs.aws.amazon.com/sdk-for-go/api/service/s3/#pkg-constants const ( - ErrCodeNoSuchConfiguration = "NoSuchConfiguration" - ErrCodeNoSuchCORSConfiguration = "NoSuchCORSConfiguration" - ErrCodeNoSuchLifecycleConfiguration = "NoSuchLifecycleConfiguration" - ErrCodeNoSuchPublicAccessBlockConfiguration = "NoSuchPublicAccessBlockConfiguration" - ErrCodeNoSuchWebsiteConfiguration = "NoSuchWebsiteConfiguration" - ErrCodeObjectLockConfigurationNotFound = "ObjectLockConfigurationNotFoundError" - ErrCodeOperationAborted = "OperationAborted" + ErrCodeNoSuchConfiguration = "NoSuchConfiguration" + ErrCodeNoSuchCORSConfiguration = "NoSuchCORSConfiguration" + ErrCodeNoSuchLifecycleConfiguration = "NoSuchLifecycleConfiguration" + ErrCodeNoSuchPublicAccessBlockConfiguration = "NoSuchPublicAccessBlockConfiguration" + ErrCodeNoSuchWebsiteConfiguration = "NoSuchWebsiteConfiguration" + ErrCodeObjectLockConfigurationNotFound = "ObjectLockConfigurationNotFoundError" + ErrCodeOperationAborted = "OperationAborted" ErrCodeServerSideEncryptionConfigurationNotFound = "ServerSideEncryptionConfigurationNotFoundError" )