From ced3fa036359ec79f2ec5ef16ef60504e8ce8287 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 6 Sep 2019 16:14:24 -0400 Subject: [PATCH] Only attempt to force destroy S3 bucket objects if the bucket has Object Lock enabled. --- aws/resource_aws_s3_bucket.go | 7 ++++++- aws/resource_aws_s3_bucket_object.go | 2 +- aws/resource_aws_s3_bucket_object_test.go | 9 ++++++++- aws/resource_aws_s3_bucket_test.go | 18 ++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/aws/resource_aws_s3_bucket.go b/aws/resource_aws_s3_bucket.go index 745c679240e..c485577f0a1 100644 --- a/aws/resource_aws_s3_bucket.go +++ b/aws/resource_aws_s3_bucket.go @@ -1261,7 +1261,12 @@ func resourceAwsS3BucketDelete(d *schema.ResourceData, meta interface{}) error { // Delete everything including locked objects. // Don't ignore any object errors or we could recurse infinitely. - err = deleteAllS3ObjectVersions(s3conn, d.Id(), "", true, false) + objectLockEnabled := false + objectLockConfiguration := expandS3ObjectLockConfiguration(d.Get("object_lock_configuration").([]interface{})) + if objectLockConfiguration != nil && aws.StringValue(objectLockConfiguration.ObjectLockEnabled) == s3.ObjectLockEnabledEnabled { + objectLockEnabled = true + } + err = deleteAllS3ObjectVersions(s3conn, d.Id(), "", objectLockEnabled, false) if err != nil { return fmt.Errorf("error S3 Bucket force_destroy: %s", err) diff --git a/aws/resource_aws_s3_bucket_object.go b/aws/resource_aws_s3_bucket_object.go index 51f10a39f49..81c3d64841a 100644 --- a/aws/resource_aws_s3_bucket_object.go +++ b/aws/resource_aws_s3_bucket_object.go @@ -516,7 +516,7 @@ func resourceAwsS3BucketObjectCustomizeDiff(d *schema.ResourceDiff, meta interfa // deleteAllS3ObjectVersions deletes all versions of a specified key from an S3 bucket. // If key is empty then all versions of all objects are deleted. -// Set force to true to override any S3 object lock protections. +// Set force to true to override any S3 object lock protections on object lock enabled buckets. func deleteAllS3ObjectVersions(conn *s3.S3, bucketName, key string, force, ignoreObjectErrors bool) error { input := &s3.ListObjectVersionsInput{ Bucket: aws.String(bucketName), diff --git a/aws/resource_aws_s3_bucket_object_test.go b/aws/resource_aws_s3_bucket_object_test.go index 5837593e3bb..8b8bb0175a9 100644 --- a/aws/resource_aws_s3_bucket_object_test.go +++ b/aws/resource_aws_s3_bucket_object_test.go @@ -82,8 +82,15 @@ func testSweepS3BucketObjects(region string) error { continue } + objectLockEnabled, err := testS3BucketObjectLockEnabled(conn, bucketName) + + if err != nil { + log.Printf("[ERROR] Error getting S3 Bucket (%s) Object Lock: %s", bucketName, err) + continue + } + // Delete everything including locked objects. Ignore any object errors. - err = deleteAllS3ObjectVersions(conn, bucketName, "", true, true) + err = deleteAllS3ObjectVersions(conn, bucketName, "", objectLockEnabled, true) if err != nil { return fmt.Errorf("error listing S3 Bucket (%s) Objects: %s", bucketName, err) diff --git a/aws/resource_aws_s3_bucket_test.go b/aws/resource_aws_s3_bucket_test.go index c2bb995ce23..2437165bff9 100644 --- a/aws/resource_aws_s3_bucket_test.go +++ b/aws/resource_aws_s3_bucket_test.go @@ -136,6 +136,24 @@ func testS3BucketRegion(conn *s3.S3, bucket string) (string, error) { return aws.StringValue(output.LocationConstraint), nil } +func testS3BucketObjectLockEnabled(conn *s3.S3, bucket string) (bool, error) { + input := &s3.GetObjectLockConfigurationInput{ + Bucket: aws.String(bucket), + } + + output, err := conn.GetObjectLockConfiguration(input) + + if isAWSErr(err, "ObjectLockConfigurationNotFoundError", "") { + return false, nil + } + + if err != nil { + return false, err + } + + return aws.StringValue(output.ObjectLockConfiguration.ObjectLockEnabled) == s3.ObjectLockEnabledEnabled, nil +} + func TestAccAWSS3Bucket_basic(t *testing.T) { rInt := acctest.RandInt() arnRegexp := regexp.MustCompile(`^arn:aws[\w-]*:s3:::`)