Skip to content

Commit

Permalink
service/s3: Add support for S3 Bucket Keys (#16581)
Browse files Browse the repository at this point in the history
Output from acceptance testing in AWS Commercial:

```
--- PASS: TestAccAWSS3Bucket_acceleration (77.72s)
--- PASS: TestAccAWSS3Bucket_AclToGrant (67.81s)
--- PASS: TestAccAWSS3Bucket_basic (43.99s)
--- PASS: TestAccAWSS3Bucket_Bucket_EmptyString (44.40s)
--- PASS: TestAccAWSS3Bucket_bucketKeyEnabled (43.09s)
--- PASS: TestAccAWSS3Bucket_Cors_Delete (31.97s)
--- PASS: TestAccAWSS3Bucket_Cors_EmptyOrigin (40.73s)
--- PASS: TestAccAWSS3Bucket_Cors_Update (75.47s)
--- PASS: TestAccAWSS3Bucket_disableDefaultEncryption_whenDefaultEncryptionIsEnabled (71.37s)
--- PASS: TestAccAWSS3Bucket_enableDefaultEncryption_whenAES256IsUsed (40.40s)
--- PASS: TestAccAWSS3Bucket_enableDefaultEncryption_whenTypical (43.33s)
--- PASS: TestAccAWSS3Bucket_forceDestroy (31.28s)
--- PASS: TestAccAWSS3Bucket_forceDestroyWithEmptyPrefixes (34.81s)
--- PASS: TestAccAWSS3Bucket_forceDestroyWithObjectLockEnabled (37.66s)
--- PASS: TestAccAWSS3Bucket_generatedName (37.26s)
--- PASS: TestAccAWSS3Bucket_GrantToAcl (68.73s)
--- PASS: TestAccAWSS3Bucket_ignoreTags (68.51s)
--- PASS: TestAccAWSS3Bucket_LifecycleBasic (91.66s)
--- PASS: TestAccAWSS3Bucket_LifecycleExpireMarkerOnly (71.82s)
--- PASS: TestAccAWSS3Bucket_LifecycleRule_AbortIncompleteMultipartUploadDays_NoExpiration (38.91s)
--- PASS: TestAccAWSS3Bucket_LifecycleRule_Expiration_EmptyConfigurationBlock (31.06s)
--- PASS: TestAccAWSS3Bucket_Logging (63.26s)
--- PASS: TestAccAWSS3Bucket_namePrefix (46.80s)
--- PASS: TestAccAWSS3Bucket_objectLock (68.55s)
--- PASS: TestAccAWSS3Bucket_Policy (100.51s)
--- PASS: TestAccAWSS3Bucket_Replication (141.65s)
--- PASS: TestAccAWSS3Bucket_Replication_MultipleDestinations_EmptyFilter (49.89s)
--- PASS: TestAccAWSS3Bucket_Replication_MultipleDestinations_NonEmptyFilter (49.86s)
--- PASS: TestAccAWSS3Bucket_Replication_MultipleDestinations_TwoDestination (46.15s)
--- PASS: TestAccAWSS3Bucket_ReplicationConfiguration_Rule_Destination_AccessControlTranslation (87.62s)
--- PASS: TestAccAWSS3Bucket_ReplicationConfiguration_Rule_Destination_AddAccessControlTranslation (86.86s)
--- PASS: TestAccAWSS3Bucket_ReplicationExpectVersioningValidationError (14.78s)
--- PASS: TestAccAWSS3Bucket_ReplicationSchemaV2 (163.32s)
--- PASS: TestAccAWSS3Bucket_ReplicationWithoutPrefix (51.27s)
--- PASS: TestAccAWSS3Bucket_ReplicationWithoutStorageClass (45.50s)
--- PASS: TestAccAWSS3Bucket_RequestPayer (70.57s)
--- PASS: TestAccAWSS3Bucket_SameRegionReplicationSchemaV2 (56.90s)
--- PASS: TestAccAWSS3Bucket_shouldFailNotFound (20.04s)
--- PASS: TestAccAWSS3Bucket_tagsWithNoSystemTags (140.95s)
--- PASS: TestAccAWSS3Bucket_tagsWithSystemTags (177.22s)
--- PASS: TestAccAWSS3Bucket_UpdateAcl (78.18s)
--- PASS: TestAccAWSS3Bucket_UpdateGrant (108.69s)
--- PASS: TestAccAWSS3Bucket_Versioning (103.73s)
--- PASS: TestAccAWSS3Bucket_Website_Simple (106.81s)
--- PASS: TestAccAWSS3Bucket_WebsiteRedirect (110.01s)
--- PASS: TestAccAWSS3Bucket_WebsiteRoutingRules (73.38s)

--- PASS: TestAccAWSS3BucketObject_acl (97.64s)
--- PASS: TestAccAWSS3BucketObject_bucketBucketKeyEnabled (47.14s)
--- PASS: TestAccAWSS3BucketObject_content (33.47s)
--- PASS: TestAccAWSS3BucketObject_contentBase64 (31.68s)
--- PASS: TestAccAWSS3BucketObject_defaultBucketSSE (40.86s)
--- PASS: TestAccAWSS3BucketObject_empty (32.54s)
--- PASS: TestAccAWSS3BucketObject_etagEncryption (33.10s)
--- PASS: TestAccAWSS3BucketObject_ignoreTags (69.05s)
--- PASS: TestAccAWSS3BucketObject_kms (38.94s)
--- PASS: TestAccAWSS3BucketObject_metadata (90.62s)
--- PASS: TestAccAWSS3BucketObject_noNameNoKey (2.10s)
--- PASS: TestAccAWSS3BucketObject_NonVersioned (31.53s)
--- PASS: TestAccAWSS3BucketObject_objectBucketKeyEnabled (38.89s)
--- PASS: TestAccAWSS3BucketObject_ObjectLockLegalHoldStartWithNone (91.67s)
--- PASS: TestAccAWSS3BucketObject_ObjectLockLegalHoldStartWithOn (60.02s)
--- PASS: TestAccAWSS3BucketObject_ObjectLockRetentionStartWithNone (92.71s)
--- PASS: TestAccAWSS3BucketObject_ObjectLockRetentionStartWithSet (116.24s)
--- PASS: TestAccAWSS3BucketObject_source (33.40s)
--- PASS: TestAccAWSS3BucketObject_sse (38.30s)
--- PASS: TestAccAWSS3BucketObject_storageClass (150.35s)
--- PASS: TestAccAWSS3BucketObject_tags (123.37s)
--- PASS: TestAccAWSS3BucketObject_tagsLeadingMultipleSlashes (126.89s)
--- PASS: TestAccAWSS3BucketObject_tagsLeadingSingleSlash (126.64s)
--- PASS: TestAccAWSS3BucketObject_tagsMultipleSlashes (117.47s)
--- PASS: TestAccAWSS3BucketObject_updates (60.84s)
--- PASS: TestAccAWSS3BucketObject_updateSameFile (60.72s)
--- PASS: TestAccAWSS3BucketObject_updatesWithVersioning (61.90s)
--- PASS: TestAccAWSS3BucketObject_updatesWithVersioningViaAccessPoint (76.09s)
--- PASS: TestAccAWSS3BucketObject_withContentCharacteristics (31.05s)

--- PASS: TestAccDataSourceAWSS3BucketObject_allParams (37.71s)
--- PASS: TestAccDataSourceAWSS3BucketObject_basic (39.61s)
--- PASS: TestAccDataSourceAWSS3BucketObject_basicViaAccessPoint (39.30s)
--- PASS: TestAccDataSourceAWSS3BucketObject_bucketKeyEnabled (41.45s)
--- PASS: TestAccDataSourceAWSS3BucketObject_kmsEncrypted (38.94s)
--- PASS: TestAccDataSourceAWSS3BucketObject_LeadingSlash (67.65s)
--- PASS: TestAccDataSourceAWSS3BucketObject_MultipleSlashes (66.64s)
--- PASS: TestAccDataSourceAWSS3BucketObject_ObjectLockLegalHoldOff (37.55s)
--- PASS: TestAccDataSourceAWSS3BucketObject_ObjectLockLegalHoldOn (38.33s)
--- PASS: TestAccDataSourceAWSS3BucketObject_readableBody (35.63s)
--- PASS: TestAccDataSourceAWSS3BucketObject_SingleSlashAsKey (31.84s)
```

Output from acceptance testing in AWS GovCloud (US):

```
--- FAIL: TestAccAWSS3Bucket_LifecycleBasic (45.90s) # #18511
--- PASS: TestAccAWSS3Bucket_AclToGrant (72.45s)
--- PASS: TestAccAWSS3Bucket_basic (39.51s)
--- PASS: TestAccAWSS3Bucket_Bucket_EmptyString (40.99s)
--- PASS: TestAccAWSS3Bucket_bucketKeyEnabled (57.24s)
--- PASS: TestAccAWSS3Bucket_Cors_Delete (33.66s)
--- PASS: TestAccAWSS3Bucket_Cors_EmptyOrigin (43.24s)
--- PASS: TestAccAWSS3Bucket_Cors_Update (76.55s)
--- PASS: TestAccAWSS3Bucket_disableDefaultEncryption_whenDefaultEncryptionIsEnabled (83.35s)
--- PASS: TestAccAWSS3Bucket_enableDefaultEncryption_whenAES256IsUsed (50.07s)
--- PASS: TestAccAWSS3Bucket_enableDefaultEncryption_whenTypical (59.66s)
--- PASS: TestAccAWSS3Bucket_forceDestroy (41.90s)
--- PASS: TestAccAWSS3Bucket_forceDestroyWithEmptyPrefixes (41.74s)
--- PASS: TestAccAWSS3Bucket_forceDestroyWithObjectLockEnabled (43.77s)
--- PASS: TestAccAWSS3Bucket_generatedName (39.92s)
--- PASS: TestAccAWSS3Bucket_GrantToAcl (76.18s)
--- PASS: TestAccAWSS3Bucket_ignoreTags (69.36s)
--- PASS: TestAccAWSS3Bucket_LifecycleExpireMarkerOnly (52.92s)
--- PASS: TestAccAWSS3Bucket_LifecycleRule_AbortIncompleteMultipartUploadDays_NoExpiration (42.01s)
--- PASS: TestAccAWSS3Bucket_LifecycleRule_Expiration_EmptyConfigurationBlock (33.30s)
--- PASS: TestAccAWSS3Bucket_Logging (54.19s)
--- PASS: TestAccAWSS3Bucket_namePrefix (41.12s)
--- PASS: TestAccAWSS3Bucket_objectLock (82.24s)
--- PASS: TestAccAWSS3Bucket_Policy (109.36s)
--- PASS: TestAccAWSS3Bucket_Replication (167.07s)
--- PASS: TestAccAWSS3Bucket_Replication_MultipleDestinations_TwoDestination (64.85s)
--- PASS: TestAccAWSS3Bucket_ReplicationConfiguration_Rule_Destination_AccessControlTranslation (105.07s)
--- PASS: TestAccAWSS3Bucket_ReplicationConfiguration_Rule_Destination_AddAccessControlTranslation (68.50s)
--- PASS: TestAccAWSS3Bucket_ReplicationExpectVersioningValidationError (21.57s)
--- PASS: TestAccAWSS3Bucket_ReplicationSchemaV2 (177.48s)
--- PASS: TestAccAWSS3Bucket_ReplicationWithoutPrefix (64.72s)
--- PASS: TestAccAWSS3Bucket_ReplicationWithoutStorageClass (51.92s)
--- PASS: TestAccAWSS3Bucket_RequestPayer (79.18s)
--- PASS: TestAccAWSS3Bucket_SameRegionReplicationSchemaV2 (70.20s)
--- PASS: TestAccAWSS3Bucket_shouldFailNotFound (28.74s)
--- PASS: TestAccAWSS3Bucket_tagsWithNoSystemTags (146.42s)
--- PASS: TestAccAWSS3Bucket_tagsWithSystemTags (195.57s)
--- PASS: TestAccAWSS3Bucket_UpdateAcl (69.73s)
--- PASS: TestAccAWSS3Bucket_UpdateGrant (113.18s)
--- PASS: TestAccAWSS3Bucket_Versioning (110.36s)
--- PASS: TestAccAWSS3Bucket_Website_Simple (105.63s)
--- PASS: TestAccAWSS3Bucket_WebsiteRedirect (122.37s)
--- PASS: TestAccAWSS3Bucket_WebsiteRoutingRules (83.63s)
--- SKIP: TestAccAWSS3Bucket_acceleration (0.00s)
--- SKIP: TestAccAWSS3Bucket_Replication_MultipleDestinations_EmptyFilter (31.31s)
--- SKIP: TestAccAWSS3Bucket_Replication_MultipleDestinations_NonEmptyFilter (29.41s)

--- PASS: TestAccAWSS3BucketObject_acl (80.47s)
--- PASS: TestAccAWSS3BucketObject_bucketBucketKeyEnabled (43.37s)
--- PASS: TestAccAWSS3BucketObject_content (35.12s)
--- PASS: TestAccAWSS3BucketObject_contentBase64 (33.84s)
--- PASS: TestAccAWSS3BucketObject_defaultBucketSSE (43.09s)
--- PASS: TestAccAWSS3BucketObject_empty (36.84s)
--- PASS: TestAccAWSS3BucketObject_etagEncryption (34.47s)
--- PASS: TestAccAWSS3BucketObject_ignoreTags (68.34s)
--- PASS: TestAccAWSS3BucketObject_kms (32.07s)
--- PASS: TestAccAWSS3BucketObject_metadata (78.86s)
--- PASS: TestAccAWSS3BucketObject_noNameNoKey (3.25s)
--- PASS: TestAccAWSS3BucketObject_objectBucketKeyEnabled (35.73s)
--- PASS: TestAccAWSS3BucketObject_ObjectLockLegalHoldStartWithNone (94.04s)
--- PASS: TestAccAWSS3BucketObject_ObjectLockLegalHoldStartWithOn (69.24s)
--- PASS: TestAccAWSS3BucketObject_ObjectLockRetentionStartWithNone (90.95s)
--- PASS: TestAccAWSS3BucketObject_ObjectLockRetentionStartWithSet (122.98s)
--- PASS: TestAccAWSS3BucketObject_source (34.57s)
--- PASS: TestAccAWSS3BucketObject_sse (31.84s)
--- PASS: TestAccAWSS3BucketObject_storageClass (126.89s)
--- PASS: TestAccAWSS3BucketObject_tags (111.75s)
--- PASS: TestAccAWSS3BucketObject_tagsLeadingMultipleSlashes (117.49s)
--- PASS: TestAccAWSS3BucketObject_tagsLeadingSingleSlash (115.91s)
--- PASS: TestAccAWSS3BucketObject_tagsMultipleSlashes (114.99s)
--- PASS: TestAccAWSS3BucketObject_updates (69.26s)
--- PASS: TestAccAWSS3BucketObject_updateSameFile (66.18s)
--- PASS: TestAccAWSS3BucketObject_updatesWithVersioning (67.47s)
--- PASS: TestAccAWSS3BucketObject_updatesWithVersioningViaAccessPoint (70.95s)
--- PASS: TestAccAWSS3BucketObject_withContentCharacteristics (33.42s)
--- SKIP: TestAccAWSS3BucketObject_NonVersioned (0.05s)

--- PASS: TestAccDataSourceAWSS3BucketObject_allParams (38.87s)
--- PASS: TestAccDataSourceAWSS3BucketObject_basic (42.58s)
--- PASS: TestAccDataSourceAWSS3BucketObject_basicViaAccessPoint (38.88s)
--- PASS: TestAccDataSourceAWSS3BucketObject_bucketKeyEnabled (38.86s)
--- PASS: TestAccDataSourceAWSS3BucketObject_kmsEncrypted (41.60s)
--- PASS: TestAccDataSourceAWSS3BucketObject_LeadingSlash (72.16s)
--- PASS: TestAccDataSourceAWSS3BucketObject_MultipleSlashes (76.35s)
--- PASS: TestAccDataSourceAWSS3BucketObject_ObjectLockLegalHoldOff (41.74s)
--- PASS: TestAccDataSourceAWSS3BucketObject_ObjectLockLegalHoldOn (38.42s)
--- PASS: TestAccDataSourceAWSS3BucketObject_readableBody (38.45s)
--- PASS: TestAccDataSourceAWSS3BucketObject_SingleSlashAsKey (34.70s)
```
  • Loading branch information
mattburgess authored Apr 2, 2021
1 parent 2bc0856 commit 924f23a
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .changelog/16581.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```release-note:enhancement
data-source/aws_s3_bucket_object: Add `bucket_key_enabled` attribute (Support S3 Bucket Keys)
```

```release-note:enhancement
resource/aws_s3_bucket: Add `bucket_key_enabled` argument to `server_side_encryption_configuration` `rule` configuration block (Support S3 Bucket Keys)
```

```release-note:enhancement
resource/aws_s3_bucket_object: Add `bucket_key_enabled` attribute (Support S3 Bucket Keys)
```
5 changes: 5 additions & 0 deletions aws/data_source_aws_s3_bucket_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ func dataSourceAwsS3BucketObject() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"bucket_key_enabled": {
Type: schema.TypeBool,
Computed: true,
},
"cache_control": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -157,6 +161,7 @@ func dataSourceAwsS3BucketObjectRead(d *schema.ResourceData, meta interface{}) e

d.SetId(uniqueId)

d.Set("bucket_key_enabled", out.BucketKeyEnabled)
d.Set("cache_control", out.CacheControl)
d.Set("content_disposition", out.ContentDisposition)
d.Set("content_encoding", out.ContentEncoding)
Expand Down
65 changes: 65 additions & 0 deletions aws/data_source_aws_s3_bucket_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,43 @@ func TestAccDataSourceAWSS3BucketObject_kmsEncrypted(t *testing.T) {
})
}

func TestAccDataSourceAWSS3BucketObject_bucketKeyEnabled(t *testing.T) {
rInt := acctest.RandInt()

var rObj s3.GetObjectOutput
var dsObj s3.GetObjectOutput

resourceName := "aws_s3_bucket_object.object"
dataSourceName := "data.aws_s3_bucket_object.obj"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, s3.EndpointsID),
Providers: testAccProviders,
PreventPostDestroyRefresh: true,
Steps: []resource.TestStep{
{
Config: testAccAWSDataSourceS3ObjectConfig_bucketKeyEnabled(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketObjectExists(resourceName, &rObj),
testAccCheckAwsS3ObjectDataSourceExists(dataSourceName, &dsObj),
resource.TestCheckResourceAttr(dataSourceName, "content_length", "22"),
resource.TestCheckResourceAttrPair(dataSourceName, "content_type", resourceName, "content_type"),
resource.TestCheckResourceAttrPair(dataSourceName, "etag", resourceName, "etag"),
resource.TestCheckResourceAttrPair(dataSourceName, "server_side_encryption", resourceName, "server_side_encryption"),
resource.TestCheckResourceAttrPair(dataSourceName, "sse_kms_key_id", resourceName, "kms_key_id"),
resource.TestCheckResourceAttrPair(dataSourceName, "bucket_key_enabled", resourceName, "bucket_key_enabled"),
resource.TestMatchResourceAttr(dataSourceName, "last_modified", regexp.MustCompile(rfc1123RegexPattern)),
resource.TestCheckResourceAttrPair(dataSourceName, "object_lock_legal_hold_status", resourceName, "object_lock_legal_hold_status"),
resource.TestCheckResourceAttrPair(dataSourceName, "object_lock_mode", resourceName, "object_lock_mode"),
resource.TestCheckResourceAttrPair(dataSourceName, "object_lock_retain_until_date", resourceName, "object_lock_retain_until_date"),
resource.TestCheckResourceAttr(dataSourceName, "body", "Keep Calm and Carry On"),
),
},
},
})
}

func TestAccDataSourceAWSS3BucketObject_allParams(t *testing.T) {
rInt := acctest.RandInt()

Expand All @@ -172,6 +209,7 @@ func TestAccDataSourceAWSS3BucketObject_allParams(t *testing.T) {
resource.TestMatchResourceAttr(dataSourceName, "last_modified", regexp.MustCompile(rfc1123RegexPattern)),
resource.TestCheckResourceAttrPair(dataSourceName, "version_id", resourceName, "version_id"),
resource.TestCheckNoResourceAttr(dataSourceName, "body"),
resource.TestCheckResourceAttrPair(dataSourceName, "bucket_key_enabled", resourceName, "bucket_key_enabled"),
resource.TestCheckResourceAttrPair(dataSourceName, "cache_control", resourceName, "cache_control"),
resource.TestCheckResourceAttrPair(dataSourceName, "content_disposition", resourceName, "content_disposition"),
resource.TestCheckResourceAttrPair(dataSourceName, "content_encoding", resourceName, "content_encoding"),
Expand Down Expand Up @@ -506,6 +544,33 @@ data "aws_s3_bucket_object" "obj" {
`, randInt)
}

func testAccAWSDataSourceS3ObjectConfig_bucketKeyEnabled(randInt int) string {
return fmt.Sprintf(`
resource "aws_s3_bucket" "object_bucket" {
bucket = "tf-object-test-bucket-%[1]d"
}
resource "aws_kms_key" "example" {
description = "TF Acceptance Test KMS key"
deletion_window_in_days = 7
}
resource "aws_s3_bucket_object" "object" {
bucket = aws_s3_bucket.object_bucket.bucket
key = "tf-testing-obj-%[1]d-encrypted"
content = "Keep Calm and Carry On"
content_type = "text/plain"
kms_key_id = aws_kms_key.example.arn
bucket_key_enabled = true
}
data "aws_s3_bucket_object" "obj" {
bucket = aws_s3_bucket.object_bucket.bucket
key = aws_s3_bucket_object.object.key
}
`, randInt)
}

func testAccAWSDataSourceS3ObjectConfig_allParams(randInt int) string {
return fmt.Sprintf(`
resource "aws_s3_bucket" "object_bucket" {
Expand Down
9 changes: 9 additions & 0 deletions aws/resource_aws_s3_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,10 @@ func resourceAwsS3Bucket() *schema.Resource {
},
},
},
"bucket_key_enabled": {
Type: schema.TypeBool,
Optional: true,
},
},
},
},
Expand Down Expand Up @@ -1931,6 +1935,10 @@ func resourceAwsS3BucketServerSideEncryptionConfigurationUpdate(s3conn *s3.S3, d
ApplyServerSideEncryptionByDefault: rcDefaultRule,
}

if val, ok := rr["bucket_key_enabled"].(bool); ok {
rcRule.BucketKeyEnabled = aws.Bool(val)
}

rules = append(rules, rcRule)
}

Expand Down Expand Up @@ -2291,6 +2299,7 @@ func flattenAwsS3ServerSideEncryptionConfiguration(c *s3.ServerSideEncryptionCon
d["kms_master_key_id"] = aws.StringValue(v.ApplyServerSideEncryptionByDefault.KMSMasterKeyID)
d["sse_algorithm"] = aws.StringValue(v.ApplyServerSideEncryptionByDefault.SSEAlgorithm)
r["apply_server_side_encryption_by_default"] = []map[string]interface{}{d}
r["bucket_key_enabled"] = aws.BoolValue(v.BucketKeyEnabled)
rules = append(rules, r)
}
}
Expand Down
12 changes: 12 additions & 0 deletions aws/resource_aws_s3_bucket_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ func resourceAwsS3BucketObject() *schema.Resource {
ValidateFunc: validation.StringInSlice(s3.ObjectCannedACL_Values(), false),
},

"bucket_key_enabled": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},

"cache_control": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -259,6 +265,10 @@ func resourceAwsS3BucketObjectPut(d *schema.ResourceData, meta interface{}) erro
putInput.ContentDisposition = aws.String(v.(string))
}

if v, ok := d.GetOk("bucket_key_enabled"); ok {
putInput.BucketKeyEnabled = aws.Bool(v.(bool))
}

if v, ok := d.GetOk("server_side_encryption"); ok {
putInput.ServerSideEncryption = aws.String(v.(string))
}
Expand Down Expand Up @@ -347,6 +357,7 @@ func resourceAwsS3BucketObjectRead(d *schema.ResourceData, meta interface{}) err

log.Printf("[DEBUG] Reading S3 Bucket Object meta: %s", resp)

d.Set("bucket_key_enabled", resp.BucketKeyEnabled)
d.Set("cache_control", resp.CacheControl)
d.Set("content_disposition", resp.ContentDisposition)
d.Set("content_encoding", resp.ContentEncoding)
Expand Down Expand Up @@ -537,6 +548,7 @@ func resourceAwsS3BucketObjectCustomizeDiff(_ context.Context, d *schema.Resourc

func hasS3BucketObjectContentChanges(d resourceDiffer) bool {
for _, key := range []string{
"bucket_key_enabled",
"cache_control",
"content_base64",
"content_disposition",
Expand Down
96 changes: 96 additions & 0 deletions aws/resource_aws_s3_bucket_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,52 @@ func TestAccAWSS3BucketObject_ObjectLockRetentionStartWithSet(t *testing.T) {
})
}

func TestAccAWSS3BucketObject_objectBucketKeyEnabled(t *testing.T) {
var obj s3.GetObjectOutput
resourceName := "aws_s3_bucket_object.object"
rInt := acctest.RandInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, s3.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSS3BucketObjectConfig_objectBucketKeyEnabled(rInt, "stuff"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketObjectExists(resourceName, &obj),
testAccCheckAWSS3BucketObjectBody(&obj, "stuff"),
resource.TestCheckResourceAttr(resourceName, "bucket_key_enabled", "true"),
),
},
},
})
}

func TestAccAWSS3BucketObject_bucketBucketKeyEnabled(t *testing.T) {
var obj s3.GetObjectOutput
resourceName := "aws_s3_bucket_object.object"
rInt := acctest.RandInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, s3.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSS3BucketObjectConfig_bucketBucketKeyEnabled(rInt, "stuff"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketObjectExists(resourceName, &obj),
testAccCheckAWSS3BucketObjectBody(&obj, "stuff"),
resource.TestCheckResourceAttr(resourceName, "bucket_key_enabled", "true"),
),
},
},
})
}

func TestAccAWSS3BucketObject_defaultBucketSSE(t *testing.T) {
var obj1 s3.GetObjectOutput
resourceName := "aws_s3_bucket_object.object"
Expand Down Expand Up @@ -1861,6 +1907,56 @@ resource "aws_s3_bucket_object" "object" {
`, randInt, source)
}

func testAccAWSS3BucketObjectConfig_objectBucketKeyEnabled(randInt int, content string) string {
return fmt.Sprintf(`
resource "aws_kms_key" "test" {
description = "Encrypts test bucket objects"
deletion_window_in_days = 7
}
resource "aws_s3_bucket" "object_bucket" {
bucket = "tf-object-test-bucket-%[1]d"
}
resource "aws_s3_bucket_object" "object" {
bucket = aws_s3_bucket.object_bucket.bucket
key = "test-key"
content = %q
kms_key_id = aws_kms_key.test.arn
bucket_key_enabled = true
}
`, randInt, content)
}

func testAccAWSS3BucketObjectConfig_bucketBucketKeyEnabled(randInt int, content string) string {
return fmt.Sprintf(`
resource "aws_kms_key" "test" {
description = "Encrypts test bucket objects"
deletion_window_in_days = 7
}
resource "aws_s3_bucket" "object_bucket" {
bucket = "tf-object-test-bucket-%[1]d"
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
}
}
}
resource "aws_s3_bucket_object" "object" {
bucket = aws_s3_bucket.object_bucket.bucket
key = "test-key"
content = %q
}
`, randInt, content)
}

func testAccAWSS3BucketObjectConfig_defaultBucketSSE(randInt int, content string) string {
return fmt.Sprintf(`
resource "aws_kms_key" "test" {
Expand Down
55 changes: 55 additions & 0 deletions aws/resource_aws_s3_bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,38 @@ func TestAccAWSS3Bucket_disableDefaultEncryption_whenDefaultEncryptionIsEnabled(
})
}

func TestAccAWSS3Bucket_bucketKeyEnabled(t *testing.T) {
bucketName := acctest.RandomWithPrefix("tf-test-bucket")
resourceName := "aws_s3_bucket.arbitrary"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, s3.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3BucketDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSS3BucketKeyEnabled(bucketName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketExists(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 TestAccAWSS3Bucket_shouldFailNotFound is designed to fail with a "plan
// not empty" error in Terraform, to check against regresssions.
// See https:/hashicorp/terraform/pull/2925
Expand Down Expand Up @@ -3543,6 +3575,29 @@ resource "aws_s3_bucket" "arbitrary" {
`, bucketName)
}

func testAccAWSS3BucketKeyEnabled(bucketName string) string {
return fmt.Sprintf(`
resource "aws_kms_key" "arbitrary" {
description = "KMS Key for Bucket %[1]s"
deletion_window_in_days = 7
}
resource "aws_s3_bucket" "arbitrary" {
bucket = %[1]q
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = aws_kms_key.arbitrary.arn
sse_algorithm = "aws:kms"
}
bucket_key_enabled = true
}
}
}
`, bucketName)
}

func testAccAWSS3BucketEnableDefaultEncryptionWithAES256(bucketName string) string {
return fmt.Sprintf(`
resource "aws_s3_bucket" "arbitrary" {
Expand Down
1 change: 1 addition & 0 deletions website/docs/d/s3_bucket_object.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ The following arguments are supported:
In addition to all arguments above, the following attributes are exported:

* `body` - Object data (see **limitations above** to understand cases in which this field is actually available)
* `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.
* `cache_control` - Specifies caching behavior along the request/reply chain.
* `content_disposition` - Specifies presentational information for the object.
* `content_encoding` - Specifies what content encodings have been applied to the object and thus what decoding mechanisms must be applied to obtain the media-type referenced by the Content-Type header field.
Expand Down
1 change: 1 addition & 0 deletions website/docs/r/s3_bucket.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ The `server_side_encryption_configuration` object supports the following:
The `rule` object supports the following:

* `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` object supports the following:

Expand Down
1 change: 1 addition & 0 deletions website/docs/r/s3_bucket_object.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ This attribute is not compatible with KMS encryption, `kms_key_id` or `server_si
* `kms_key_id` - (Optional) Amazon Resource Name (ARN) of the KMS Key to use for object encryption. If the S3 Bucket has server-side encryption enabled, that value will automatically be used. If referencing the
`aws_kms_key` resource, use the `arn` attribute. If referencing the `aws_kms_alias` data source or resource, use the `target_key_arn` attribute. Terraform will only perform drift detection if a configuration value
is provided.
* `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.
* `metadata` - (Optional) A map of keys/values to provision metadata (will be automatically prefixed by `x-amz-meta-`, note that only lowercase label are currently supported by the AWS Go API).
* `tags` - (Optional) A map of tags to assign to the object.
* `force_destroy` - (Optional) Allow the object to be deleted by removing any legal hold on any object version.
Expand Down

0 comments on commit 924f23a

Please sign in to comment.