Skip to content

Commit

Permalink
Merge pull request #17738 from yuonoda/f-data_source_aws_s3_bucket_po…
Browse files Browse the repository at this point in the history
…licy

New Data Source:  aws_s3_bucket_policy
  • Loading branch information
johnsonaj authored Apr 21, 2022
2 parents 4bf2b48 + 4d7b9a4 commit aa96ab4
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/17738.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_s3_bucket_policy
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ func Provider() *schema.Provider {
"aws_s3_objects": s3.DataSourceObjects(),
"aws_s3_bucket_object": s3.DataSourceBucketObject(), // DEPRECATED: use aws_s3_object instead
"aws_s3_bucket_objects": s3.DataSourceBucketObjects(), // DEPRECATED: use aws_s3_objects instead
"aws_s3_bucket_policy": s3.DataSourceBucketPolicy(),

"aws_sagemaker_prebuilt_ecr_image": sagemaker.DataSourcePrebuiltECRImage(),

Expand Down
80 changes: 80 additions & 0 deletions internal/service/s3/bucket_policy_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package s3

import (
"context"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func DataSourceBucketPolicy() *schema.Resource {
return &schema.Resource{
ReadWithoutTimeout: dataSourceBucketPolicyRead,

Schema: map[string]*schema.Schema{
"bucket": {
Type: schema.TypeString,
Required: true,
},
"policy": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceBucketPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).S3Conn

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

out, err := FindBucketPolicy(ctx, conn, name)
if err != nil {
return diag.Errorf("failed getting S3 bucket policy (%s): %s", name, err)
}

policy, err := structure.NormalizeJsonString(aws.StringValue(out.Policy))
if err != nil {
return diag.Errorf("policy (%s) is an invalid JSON: %s", policy, err)
}

d.SetId(name)
d.Set("policy", policy)

return nil
}

func FindBucketPolicy(ctx context.Context, conn *s3.S3, name string) (*s3.GetBucketPolicyOutput, error) {
in := &s3.GetBucketPolicyInput{
Bucket: aws.String(name),
}
log.Printf("[DEBUG] Reading S3 bucket policy: %s", in)

out, err := conn.GetBucketPolicyWithContext(ctx, in)

if tfawserr.ErrCodeEquals(err, ErrCodeNoSuchBucketPolicy) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: in,
}
}

if err != nil {
return nil, err
}

if out == nil {
return nil, tfresource.NewEmptyResultError(in)
}

return out, nil
}
148 changes: 148 additions & 0 deletions internal/service/s3/bucket_policy_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package s3_test

import (
"context"
"fmt"
"testing"

"github.com/aws/aws-sdk-go/service/s3"
awspolicy "github.com/hashicorp/awspolicyequivalence"
sdkacctest "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"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tfs3 "github.com/hashicorp/terraform-provider-aws/internal/service/s3"
)

func TestAccDataSourceBucketPolicy_basic(t *testing.T) {
var conf s3.GetBucketPolicyOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
dataSourceName := "data.aws_s3_bucket_policy.test"
resourceName := "aws_s3_bucket_policy.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
Providers: acctest.Providers,
Steps: []resource.TestStep{
{
Config: testAccDataSourceBucketPolicyConfigBasicConfig(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckBucketPolicyExists(resourceName, &conf),
testAccCheckBucketPolicyMatch(dataSourceName, "policy", resourceName, "policy"),
),
},
},
})
}

func testAccCheckBucketPolicyMatch(resource1, attr1, resource2, attr2 string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resource1]
if !ok {
return fmt.Errorf("not found: %s", resource1)
}
if rs.Primary.ID == "" {
return fmt.Errorf("no ID is set")
}
policy1, ok := rs.Primary.Attributes[attr1]
if !ok {
return fmt.Errorf("attribute %q not found for %q", attr1, resource1)
}

rs, ok = s.RootModule().Resources[resource2]
if !ok {
return fmt.Errorf("not found: %s", resource2)
}
if rs.Primary.ID == "" {
return fmt.Errorf("mo ID is set")
}
policy2, ok := rs.Primary.Attributes[attr2]
if !ok {
return fmt.Errorf("attribute %q not found for %q", attr2, resource2)
}

areEquivalent, err := awspolicy.PoliciesAreEquivalent(policy1, policy2)
if err != nil {
return fmt.Errorf("comparing IAM Policies failed: %s", err)
}

if !areEquivalent {
return fmt.Errorf("S3 bucket policies differ.\npolicy1: %s\npolicy2: %s", policy1, policy2)
}

return nil
}
}

func testAccCheckBucketPolicyExists(n string, ci *s3.GetBucketPolicyOutput) 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 Policy ID is set")
}

conn := acctest.Provider.Meta().(*conns.AWSClient).S3Conn

output, err := tfs3.FindBucketPolicy(context.Background(), conn, rs.Primary.ID)
if err != nil {
return err
}

*ci = *output

return nil
}
}

func testAccDataSourceBucketPolicyBaseConfig(rName string) string {
return fmt.Sprintf(`
resource "aws_s3_bucket" "test" {
bucket = %[1]q
tags = {
Name = %[1]q
}
}
resource "aws_s3_bucket_policy" "test" {
bucket = aws_s3_bucket.test.id
policy = data.aws_iam_policy_document.test.json
}
data "aws_iam_policy_document" "test" {
statement {
effect = "Allow"
actions = [
"s3:GetObject",
"s3:ListBucket",
]
resources = [
aws_s3_bucket.test.arn,
"${aws_s3_bucket.test.arn}/*",
]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
`, rName)
}

func testAccDataSourceBucketPolicyConfigBasicConfig(rName string) string {
return acctest.ConfigCompose(testAccDataSourceBucketPolicyBaseConfig(rName), `
data "aws_s3_bucket_policy" "test" {
bucket = aws_s3_bucket.test.id
depends_on = [aws_s3_bucket_policy.test]
}
`)
}
37 changes: 37 additions & 0 deletions website/docs/d/s3_bucket_policy.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
subcategory: "S3 (Simple Storage)"
layout: "aws"
page_title: "AWS: aws_s3_bucket_policy"
description: |-
Provides IAM policy of an S3 bucket
---

# Data Source: aws_s3_bucket_policy

The bucket policy data source returns IAM policy of an S3 bucket.

## Example Usage

The following example retrieves IAM policy of a specified S3 bucket.

```terraform
data "aws_s3_bucket_policy" "example" {
bucket = "example-bucket-name"
}
output "foo" {
value = data.aws_s3_bucket_policy.example.policy
}
```

## Argument Reference

The following arguments are supported:

* `bucket` - (Required) The bucket name.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:

* `policy` - IAM bucket policy.

0 comments on commit aa96ab4

Please sign in to comment.