opentofu/builtin/providers/aws/resource_aws_s3_bucket_policy_test.go
James Nugent 93f31fce17 provider/aws: Add aws_s3_bucket_policy resource
This commit adds a new "attachment" style resource for setting the
policy of an AWS S3 bucket. This is desirable such that the ARN of the
bucket can be referenced in an IAM Policy Document.

In addition, we now suppress diffs on the (now-computed) policy in the
S3 bucket for structurally equivalent policies, which prevents flapping
because of whitespace and map ordering changes made by the S3 endpoint.
2016-09-02 09:07:54 -07:00

181 lines
4.6 KiB
Go

package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/jen20/awspolicyequivalence"
)
func TestAccAWSS3BucketPolicy_basic(t *testing.T) {
name := fmt.Sprintf("tf-test-bucket-%d", acctest.RandInt())
expectedPolicyText := fmt.Sprintf(
`{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"s3:*","Resource":["arn:aws:s3:::%s","arn:aws:s3:::%s/*"]}]}`,
name, name)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3BucketDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSS3BucketPolicyConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
testAccCheckAWSS3BucketHasPolicy("aws_s3_bucket.bucket", expectedPolicyText),
),
},
},
})
}
func TestAccAWSS3BucketPolicy_policyUpdate(t *testing.T) {
name := fmt.Sprintf("tf-test-bucket-%d", acctest.RandInt())
expectedPolicyText1 := fmt.Sprintf(
`{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"s3:*","Resource":["arn:aws:s3:::%s","arn:aws:s3:::%s/*"]}]}`,
name, name)
expectedPolicyText2 := fmt.Sprintf(
`{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":["s3:DeleteBucket", "s3:ListBucket", "s3:ListBucketVersions"], "Resource":["arn:aws:s3:::%s","arn:aws:s3:::%s/*"]}]}`,
name, name)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSS3BucketDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSS3BucketPolicyConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
testAccCheckAWSS3BucketHasPolicy("aws_s3_bucket.bucket", expectedPolicyText1),
),
},
{
Config: testAccAWSS3BucketPolicyConfig_updated(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
testAccCheckAWSS3BucketHasPolicy("aws_s3_bucket.bucket", expectedPolicyText2),
),
},
},
})
}
func testAccCheckAWSS3BucketHasPolicy(n string, expectedPolicyText string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No S3 Bucket ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).s3conn
policy, err := conn.GetBucketPolicy(&s3.GetBucketPolicyInput{
Bucket: aws.String(rs.Primary.ID),
})
if err != nil {
return fmt.Errorf("GetBucketPolicy error: %v", err)
}
actualPolicyText := *policy.Policy
equivalent, err := awspolicy.PoliciesAreEquivalent(actualPolicyText, expectedPolicyText)
if err != nil {
return fmt.Errorf("Error testing policy equivalence: %s", err)
}
if !equivalent {
return fmt.Errorf("Non-equivalent policy error:\n\nexpected: %s\n\n got: %s\n",
expectedPolicyText, actualPolicyText)
}
return nil
}
}
func testAccAWSS3BucketPolicyConfig(bucketName string) string {
return fmt.Sprintf(`
resource "aws_s3_bucket" "bucket" {
bucket = "%s"
tags {
TestName = "TestAccAWSS3BucketPolicy_basic"
}
}
resource "aws_s3_bucket_policy" "bucket" {
bucket = "${aws_s3_bucket.bucket.bucket}"
policy = "${data.aws_iam_policy_document.policy.json}"
}
data "aws_iam_policy_document" "policy" {
statement {
effect = "Allow"
actions = [
"s3:*",
]
resources = [
"${aws_s3_bucket.bucket.arn}",
"${aws_s3_bucket.bucket.arn}/*",
]
principals {
type = "AWS"
identifiers = ["*"]
}
}
}
`, bucketName)
}
func testAccAWSS3BucketPolicyConfig_updated(bucketName string) string {
return fmt.Sprintf(`
resource "aws_s3_bucket" "bucket" {
bucket = "%s"
tags {
TestName = "TestAccAWSS3BucketPolicy_basic"
}
}
resource "aws_s3_bucket_policy" "bucket" {
bucket = "${aws_s3_bucket.bucket.bucket}"
policy = "${data.aws_iam_policy_document.policy.json}"
}
data "aws_iam_policy_document" "policy" {
statement {
effect = "Allow"
actions = [
"s3:DeleteBucket",
"s3:ListBucket",
"s3:ListBucketVersions"
]
resources = [
"${aws_s3_bucket.bucket.arn}",
"${aws_s3_bucket.bucket.arn}/*",
]
principals {
type = "AWS"
identifiers = ["*"]
}
}
}
`, bucketName)
}