-
Notifications
You must be signed in to change notification settings - Fork 9.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17738 from yuonoda/f-data_source_aws_s3_bucket_po…
…licy New Data Source: aws_s3_bucket_policy
- Loading branch information
Showing
5 changed files
with
269 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:new-data-source | ||
aws_s3_bucket_policy | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | ||
} | ||
`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |