Skip to content

Commit

Permalink
New Resource: aws_s3control_bucket_policy
Browse files Browse the repository at this point in the history
Reference: #15412
Reference: #15416

Output from acceptance testing:

```
Pending
```
  • Loading branch information
bflad committed Oct 16, 2020
1 parent 0c5df6a commit cbd7c0d
Show file tree
Hide file tree
Showing 4 changed files with 433 additions and 0 deletions.
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,7 @@ func Provider() *schema.Provider {
"aws_s3_bucket_metric": resourceAwsS3BucketMetric(),
"aws_s3_bucket_inventory": resourceAwsS3BucketInventory(),
"aws_s3control_bucket": resourceAwsS3ControlBucket(),
"aws_s3control_bucket_policy": resourceAwsS3ControlBucketPolicy(),
"aws_security_group": resourceAwsSecurityGroup(),
"aws_network_interface_sg_attachment": resourceAwsNetworkInterfaceSGAttachment(),
"aws_default_security_group": resourceAwsDefaultSecurityGroup(),
Expand Down
166 changes: 166 additions & 0 deletions aws/resource_aws_s3control_bucket_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package aws

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/s3control"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func resourceAwsS3ControlBucketPolicy() *schema.Resource {
return &schema.Resource{
Create: resourceAwsS3ControlBucketPolicyCreate,
Read: resourceAwsS3ControlBucketPolicyRead,
Update: resourceAwsS3ControlBucketPolicyUpdate,
Delete: resourceAwsS3ControlBucketPolicyDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"bucket": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateArn,
},
"policy": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
},
},
}
}

func resourceAwsS3ControlBucketPolicyCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).s3controlconn

bucket := d.Get("bucket").(string)

input := &s3control.PutBucketPolicyInput{
Bucket: aws.String(bucket),
Policy: aws.String(d.Get("policy").(string)),
}

_, err := conn.PutBucketPolicy(input)

if err != nil {
return fmt.Errorf("error creating S3 Control Bucket Policy (%s): %w", bucket, err)
}

d.SetId(bucket)

return resourceAwsS3ControlBucketPolicyRead(d, meta)
}

func resourceAwsS3ControlBucketPolicyRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).s3controlconn

parsedArn, err := arn.Parse(d.Id())

if err != nil {
return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): %w", d.Id(), err)
}

if parsedArn.AccountID == "" {
return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): unknown format", d.Id())
}

input := &s3control.GetBucketPolicyInput{
AccountId: aws.String(parsedArn.AccountID),
Bucket: aws.String(d.Id()),
}

output, err := conn.GetBucketPolicy(input)

if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "NoSuchBucket") {
log.Printf("[WARN] S3 Control Bucket Policy (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "NoSuchBucketPolicy") {
log.Printf("[WARN] S3 Control Bucket Policy (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "NoSuchOutpost") {
log.Printf("[WARN] S3 Control Bucket Policy (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("error reading S3 Control Bucket Policy (%s): %w", d.Id(), err)
}

if output == nil {
return fmt.Errorf("error reading S3 Control Bucket Policy (%s): empty response", d.Id())
}

d.Set("bucket", d.Id())
d.Set("policy", output.Policy)

return nil
}

func resourceAwsS3ControlBucketPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).s3controlconn

input := &s3control.PutBucketPolicyInput{
Bucket: aws.String(d.Id()),
Policy: aws.String(d.Get("policy").(string)),
}

_, err := conn.PutBucketPolicy(input)

if err != nil {
return fmt.Errorf("error updating S3 Control Bucket Policy (%s): %w", d.Id(), err)
}

return resourceAwsS3ControlBucketPolicyRead(d, meta)
}

func resourceAwsS3ControlBucketPolicyDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).s3controlconn

parsedArn, err := arn.Parse(d.Id())

if err != nil {
return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): %w", d.Id(), err)
}

input := &s3control.DeleteBucketPolicyInput{
AccountId: aws.String(parsedArn.AccountID),
Bucket: aws.String(d.Id()),
}

_, err = conn.DeleteBucketPolicy(input)

if tfawserr.ErrCodeEquals(err, "NoSuchBucket") {
return nil
}

if tfawserr.ErrCodeEquals(err, "NoSuchBucketPolicy") {
return nil
}

if tfawserr.ErrCodeEquals(err, "NoSuchOutpost") {
return nil
}

if err != nil {
return fmt.Errorf("error deleting S3 Control Bucket Policy (%s): %w", d.Id(), err)
}

return nil
}
209 changes: 209 additions & 0 deletions aws/resource_aws_s3control_bucket_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
package aws

import (
"fmt"
"regexp"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/s3control"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"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"
)

func TestAccAWSS3ControlBucketPolicy_basic(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_s3control_bucket_policy.test"
s3ControlBucketResourceName := "aws_s3control_bucket.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3ControlBucketPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:*"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3ControlBucketPolicyExists(resourceName),
resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "arn"),
resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:\*`)),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSS3ControlBucketPolicy_disappears(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_s3control_bucket_policy.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3ControlBucketPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:*"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3ControlBucketPolicyExists(resourceName),
testAccCheckResourceDisappears(testAccProvider, resourceAwsS3ControlBucketPolicy(), resourceName),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func TestAccAWSS3ControlBucketPolicy_Policy(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_s3control_bucket_policy.test"
s3ControlBucketResourceName := "aws_s3control_bucket.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3ControlBucketPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:CreateBucket"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3ControlBucketPolicyExists(resourceName),
resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "bucket"),
resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:CreateBucket`)),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:DeleteBucket"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3ControlBucketPolicyExists(resourceName),
resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "bucket"),
resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:DeleteBucket`)),
),
},
},
})
}

func testAccCheckAWSS3ControlBucketPolicyDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).s3controlconn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_s3control_bucket_policy" {
continue
}

parsedArn, err := arn.Parse(rs.Primary.ID)

if err != nil {
return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): %w", rs.Primary.ID, err)
}

input := &s3control.GetBucketPolicyInput{
AccountId: aws.String(parsedArn.AccountID),
Bucket: aws.String(rs.Primary.ID),
}

_, err = conn.GetBucketPolicy(input)

if tfawserr.ErrCodeEquals(err, "NoSuchBucket") {
return nil
}

if tfawserr.ErrCodeEquals(err, "NoSuchBucketPolicy") {
return nil
}

if tfawserr.ErrCodeEquals(err, "NoSuchOutpost") {
return nil
}

if err != nil {
return err
}

return fmt.Errorf("S3 Control Bucket Policy (%s) still exists", rs.Primary.ID)
}

return nil
}

func testAccCheckAWSS3ControlBucketPolicyExists(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("no resource ID is set")
}

conn := testAccProvider.Meta().(*AWSClient).s3controlconn

parsedArn, err := arn.Parse(rs.Primary.ID)

if err != nil {
return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): %w", rs.Primary.ID, err)
}

input := &s3control.GetBucketPolicyInput{
AccountId: aws.String(parsedArn.AccountID),
Bucket: aws.String(rs.Primary.ID),
}

_, err = conn.GetBucketPolicy(input)

if err != nil {
return err
}

return nil
}
}

func testAccAWSS3ControlBucketPolicyConfig_Policy(rName, action string) string {
return fmt.Sprintf(`
data "aws_outposts_outposts" "test" {}
data "aws_outposts_outpost" "test" {
id = tolist(data.aws_outposts_outposts.test.ids)[0]
}
resource "aws_s3control_bucket" "test" {
bucket = %[1]q
outpost_id = data.aws_outposts_outpost.test.id
}
resource "aws_s3control_bucket_policy" "test" {
bucket = aws_s3control_bucket.test.arn
policy = jsonencode({
Id = "testBucketPolicy"
Statement = [
{
Action = %[2]q
Effect = "Allow"
Principal = {
AWS = "*"
}
Resource = aws_s3control_bucket.test.arn
Sid = "st1"
}
]
Version = "2012-10-17"
})
}
`, rName, action)
}
Loading

0 comments on commit cbd7c0d

Please sign in to comment.