Skip to content

Commit

Permalink
providers/aws: Add support for policy on S3 bucket
Browse files Browse the repository at this point in the history
  • Loading branch information
justincampbell committed May 16, 2015
1 parent 9f52192 commit d7a2cf8
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 5 deletions.
47 changes: 42 additions & 5 deletions builtin/providers/aws/resource_aws_s3_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ func resourceAwsS3Bucket() *schema.Resource {
ForceNew: true,
},

"policy": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},

"website": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -121,8 +126,14 @@ func resourceAwsS3BucketUpdate(d *schema.ResourceData, meta interface{}) error {
return err
}

if err := resourceAwsS3BucketWebsiteUpdate(s3conn, d); err != nil {
return err
if d.HasChange("website") {
if err := resourceAwsS3BucketPolicyUpdate(s3conn, d); err != nil {
return err
}

if err := resourceAwsS3BucketWebsiteUpdate(s3conn, d); err != nil {
return err
}
}

return resourceAwsS3BucketRead(d, meta)
Expand Down Expand Up @@ -228,11 +239,37 @@ func resourceAwsS3BucketDelete(d *schema.ResourceData, meta interface{}) error {
return nil
}

func resourceAwsS3BucketWebsiteUpdate(s3conn *s3.S3, d *schema.ResourceData) error {
if !d.HasChange("website") {
return nil
func resourceAwsS3BucketPolicyUpdate(s3conn *s3.S3, d *schema.ResourceData) error {
bucket := d.Get("bucket").(string)
policy := d.Get("policy").(string)

if policy != "" {
input := &s3.PutBucketPolicyInput{
Bucket: aws.String(bucket),
Policy: aws.String(policy),
}

log.Printf("[DEBUG] S3 put bucket policy: %s", input)

_, err := s3conn.PutBucketPolicy(input)
if err != nil {
return fmt.Errorf("Error putting S3 policy: %s", err)
}
} else {
input := &s3.DeleteBucketPolicyInput{
Bucket: aws.String(bucket),
}

_, err := s3conn.DeleteBucketPolicy(input)
if err != nil {
return fmt.Errorf("Error deleting S3 policy: %s", err)
}
}

return nil
}

func resourceAwsS3BucketWebsiteUpdate(s3conn *s3.S3, d *schema.ResourceData) error {
ws := d.Get("website").([]interface{})

if len(ws) == 1 {
Expand Down
69 changes: 69 additions & 0 deletions builtin/providers/aws/resource_aws_s3_bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aws
import (
"fmt"
"math/rand"
"strconv"
"testing"
"time"

Expand Down Expand Up @@ -35,6 +36,32 @@ func TestAccAWSS3Bucket_basic(t *testing.T) {
})
}

func TestAccAWSS3Bucket_Policy(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3BucketDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSS3BucketConfigWithPolicy,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
testAccCheckAWSS3BucketPolicy(
"aws_s3_bucket.bucket", testAccAWSS3BucketPolicy),
),
},
resource.TestStep{
Config: testAccAWSS3BucketConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
testAccCheckAWSS3BucketPolicy(
"aws_s3_bucket.bucket", ""),
),
},
},
})
}

func TestAccAWSS3Bucket_Website(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Expand Down Expand Up @@ -145,6 +172,38 @@ func testAccCheckAWSS3BucketExists(n string) resource.TestCheckFunc {
}
}

func testAccCheckAWSS3BucketPolicy(n string, policy string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, _ := s.RootModule().Resources[n]
conn := testAccProvider.Meta().(*AWSClient).s3conn

out, err := conn.GetBucketPolicy(&s3.GetBucketPolicyInput{
Bucket: aws.String(rs.Primary.ID),
})

if err != nil {
if policy == "" {
// If we want to assert that the policy is not there, than
// this error is expected
return nil
} else {
return fmt.Errorf("GetBucketPolicy error: %v", err)
}
}

if v := out.Policy; v == nil {
if policy != "" {
return fmt.Errorf("bad policy, found nil, expected: %s", policy)
}
} else {
if *v != policy {
return fmt.Errorf("bad policy, expected: %s, got %#v", policy, v)
}
}

return nil
}
}
func testAccCheckAWSS3BucketWebsite(n string, indexDoc string, errorDoc string, redirectTo string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, _ := s.RootModule().Resources[n]
Expand Down Expand Up @@ -202,6 +261,8 @@ func testAccCheckAWSS3BucketWebsite(n string, indexDoc string, errorDoc string,
// within AWS
var randInt = rand.New(rand.NewSource(time.Now().UnixNano())).Int()
var testAccWebsiteEndpoint = fmt.Sprintf("tf-test-bucket-%d.s3-website-us-west-2.amazonaws.com", randInt)
var testAccAWSS3BucketPolicy = fmt.Sprintf(`{ "Version": "2008-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::tf-test-bucket-%d/*" } ] }`, randInt)

var testAccAWSS3BucketConfig = fmt.Sprintf(`
resource "aws_s3_bucket" "bucket" {
bucket = "tf-test-bucket-%d"
Expand Down Expand Up @@ -242,3 +303,11 @@ resource "aws_s3_bucket" "bucket" {
}
}
`, randInt)

var testAccAWSS3BucketConfigWithPolicy = fmt.Sprintf(`
resource "aws_s3_bucket" "bucket" {
bucket = "tf-test-bucket-%d"
acl = "public-read"
policy = %s
}
`, randInt, strconv.Quote(testAccAWSS3BucketPolicy))
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ The following arguments are supported:

* `bucket` - (Required) The name of the bucket.
* `acl` - (Optional) The [canned ACL](http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl) to apply. Defaults to "private".
* `policy` - (Optional) A valid [bucket policy](http://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html) JSON document.
* `tags` - (Optional) A mapping of tags to assign to the bucket.
* `website` - (Optional) A website object (documented below).

Expand Down

0 comments on commit d7a2cf8

Please sign in to comment.