-
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 #17039 from DrFaust92/r/vpc_endpoint_policy
r/vpc_endpoint_policy - new resource
- Loading branch information
Showing
5 changed files
with
372 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-resource | ||
aws_vpc_endpoint_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,141 @@ | ||
package ec2 | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/ec2" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||
"github.com/hashicorp/terraform-provider-aws/internal/conns" | ||
"github.com/hashicorp/terraform-provider-aws/internal/tfresource" | ||
"github.com/hashicorp/terraform-provider-aws/internal/verify" | ||
) | ||
|
||
func ResourceVPCEndpointPolicy() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceVPCEndpointPolicyPut, | ||
Update: resourceVPCEndpointPolicyPut, | ||
Read: resourceVPCEndpointPolicyRead, | ||
Delete: resourceVPCEndpointPolicyDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"policy": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ValidateFunc: validation.StringIsJSON, | ||
DiffSuppressFunc: verify.SuppressEquivalentPolicyDiffs, | ||
StateFunc: func(v interface{}) string { | ||
json, _ := structure.NormalizeJsonString(v) | ||
return json | ||
}, | ||
}, | ||
"vpc_endpoint_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Create: schema.DefaultTimeout(10 * time.Minute), | ||
Delete: schema.DefaultTimeout(10 * time.Minute), | ||
}, | ||
} | ||
} | ||
|
||
func resourceVPCEndpointPolicyPut(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*conns.AWSClient).EC2Conn | ||
|
||
endpointID := d.Get("vpc_endpoint_id").(string) | ||
req := &ec2.ModifyVpcEndpointInput{ | ||
VpcEndpointId: aws.String(endpointID), | ||
} | ||
|
||
policy, err := structure.NormalizeJsonString(d.Get("policy")) | ||
if err != nil { | ||
return fmt.Errorf("policy contains an invalid JSON: %w", err) | ||
} | ||
|
||
if policy == "" { | ||
req.ResetPolicy = aws.Bool(true) | ||
} else { | ||
req.PolicyDocument = aws.String(policy) | ||
} | ||
|
||
log.Printf("[DEBUG] Updating VPC Endpoint Policy: %#v", req) | ||
if _, err := conn.ModifyVpcEndpoint(req); err != nil { | ||
return fmt.Errorf("Error updating VPC Endpoint Policy: %w", err) | ||
} | ||
d.SetId(endpointID) | ||
|
||
_, err = WaitVPCEndpointAvailable(conn, endpointID, d.Timeout(schema.TimeoutCreate)) | ||
|
||
if err != nil { | ||
return fmt.Errorf("error waiting for VPC Endpoint (%s) to policy to set: %w", endpointID, err) | ||
} | ||
|
||
return resourceVPCEndpointPolicyRead(d, meta) | ||
} | ||
|
||
func resourceVPCEndpointPolicyRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*conns.AWSClient).EC2Conn | ||
|
||
vpce, err := FindVPCEndpointByID(conn, d.Id()) | ||
|
||
if !d.IsNewResource() && tfresource.NotFound(err) { | ||
log.Printf("[WARN] VPC Endpoint Policy (%s) not found, removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
if err != nil { | ||
return fmt.Errorf("error reading VPC Endpoint Policy (%s): %w", d.Id(), err) | ||
} | ||
|
||
d.Set("vpc_endpoint_id", d.Id()) | ||
|
||
policyToSet, err := verify.SecondJSONUnlessEquivalent(d.Get("policy").(string), aws.StringValue(vpce.PolicyDocument)) | ||
|
||
if err != nil { | ||
return fmt.Errorf("while setting policy (%s), encountered: %w", policyToSet, err) | ||
} | ||
|
||
policyToSet, err = structure.NormalizeJsonString(policyToSet) | ||
|
||
if err != nil { | ||
return fmt.Errorf("policy (%s) is invalid JSON: %w", policyToSet, err) | ||
} | ||
|
||
d.Set("policy", policyToSet) | ||
return nil | ||
} | ||
|
||
func resourceVPCEndpointPolicyDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*conns.AWSClient).EC2Conn | ||
|
||
req := &ec2.ModifyVpcEndpointInput{ | ||
VpcEndpointId: aws.String(d.Id()), | ||
ResetPolicy: aws.Bool(true), | ||
} | ||
|
||
log.Printf("[DEBUG] Resetting VPC Endpoint Policy: %#v", req) | ||
if _, err := conn.ModifyVpcEndpoint(req); err != nil { | ||
return fmt.Errorf("Error Resetting VPC Endpoint Policy: %w", err) | ||
} | ||
|
||
_, err := WaitVPCEndpointAvailable(conn, d.Id(), d.Timeout(schema.TimeoutDelete)) | ||
|
||
if err != nil { | ||
return fmt.Errorf("error waiting for VPC Endpoint (%s) to be reset: %w", d.Id(), err) | ||
} | ||
|
||
return 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,158 @@ | ||
package ec2_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/service/ec2" | ||
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/hashicorp/terraform-provider-aws/internal/acctest" | ||
tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" | ||
) | ||
|
||
func TestAccEC2VPCEndpointPolicy_basic(t *testing.T) { | ||
var endpoint ec2.VpcEndpoint | ||
|
||
resourceName := "aws_vpc_endpoint_policy.test" | ||
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { acctest.PreCheck(t) }, | ||
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), | ||
Providers: acctest.Providers, | ||
CheckDestroy: testAccCheckVpcEndpointDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccVpcEndpointPolicyBasicConfig(rName, policy1), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckVpcEndpointExists(resourceName, &endpoint), | ||
), | ||
}, | ||
{ | ||
ResourceName: resourceName, | ||
ImportState: true, | ||
ImportStateVerify: true, | ||
}, | ||
{ | ||
Config: testAccVpcEndpointPolicyBasicConfig(rName, policy2), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckVpcEndpointExists(resourceName, &endpoint), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccEC2VPCEndpointPolicy_disappears(t *testing.T) { | ||
var endpoint ec2.VpcEndpoint | ||
resourceName := "aws_vpc_endpoint_policy.test" | ||
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { acctest.PreCheck(t) }, | ||
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), | ||
Providers: acctest.Providers, | ||
CheckDestroy: testAccCheckVpcEndpointDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccVpcEndpointPolicyBasicConfig(rName, policy1), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckVpcEndpointExists(resourceName, &endpoint), | ||
acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceVPCEndpointPolicy(), resourceName), | ||
), | ||
ExpectNonEmptyPlan: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccEC2VPCEndpointPolicy_disappears_endpoint(t *testing.T) { | ||
var endpoint ec2.VpcEndpoint | ||
resourceName := "aws_vpc_endpoint_policy.test" | ||
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { acctest.PreCheck(t) }, | ||
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), | ||
Providers: acctest.Providers, | ||
CheckDestroy: testAccCheckVpcEndpointDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccVpcEndpointPolicyBasicConfig(rName, policy1), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckVpcEndpointExists(resourceName, &endpoint), | ||
acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceVPCEndpoint(), "aws_vpc_endpoint.test"), | ||
), | ||
ExpectNonEmptyPlan: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
const policy1 = ` | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Sid": "ReadOnly", | ||
"Principal": "*", | ||
"Action": [ | ||
"dynamodb:DescribeTable", | ||
"dynamodb:ListTables" | ||
], | ||
"Effect": "Allow", | ||
"Resource": "*" | ||
} | ||
] | ||
} | ||
` | ||
|
||
const policy2 = ` | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Sid": "AllowAll", | ||
"Effect": "Allow", | ||
"Principal": { | ||
"AWS": "*" | ||
}, | ||
"Action": "*", | ||
"Resource": "*" | ||
} | ||
] | ||
} | ||
` | ||
|
||
func testAccVpcEndpointPolicyBasicConfig(rName, policy string) string { | ||
return fmt.Sprintf(` | ||
data "aws_vpc_endpoint_service" "test" { | ||
service = "dynamodb" | ||
} | ||
resource "aws_vpc" "test" { | ||
cidr_block = "10.0.0.0/16" | ||
tags = { | ||
Name = %[1]q | ||
} | ||
} | ||
resource "aws_vpc_endpoint" "test" { | ||
service_name = data.aws_vpc_endpoint_service.test.service_name | ||
vpc_id = aws_vpc.test.id | ||
tags = { | ||
Name = %[1]q | ||
} | ||
} | ||
resource "aws_vpc_endpoint_policy" "test" { | ||
vpc_endpoint_id = aws_vpc_endpoint.test.id | ||
policy = <<POLICY | ||
%[2]s | ||
POLICY | ||
} | ||
`, rName, 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
--- | ||
subcategory: "VPC" | ||
layout: "aws" | ||
page_title: "AWS: aws_vpc_endpoint_policy" | ||
description: |- | ||
Provides a VPC Endpoint Policy resource. | ||
--- | ||
|
||
# Resource: aws_vpc_endpoint_policy | ||
|
||
Provides a VPC Endpoint Policy resource. | ||
|
||
## Example Usage | ||
|
||
```terraform | ||
data "aws_vpc_endpoint_service" "example" { | ||
service = "dynamodb" | ||
} | ||
resource "aws_vpc" "example" { | ||
cidr_block = "10.0.0.0/16" | ||
} | ||
resource "aws_vpc_endpoint" "example" { | ||
service_name = data.aws_vpc_endpoint_service.example.service_name | ||
vpc_id = aws_vpc.example.id | ||
} | ||
resource "aws_vpc_endpoint_policy" "example" { | ||
vpc_endpoint_id = aws_vpc_endpoint.example.id | ||
policy = jsonencode({ | ||
"Version" : "2012-10-17", | ||
"Statement" : [ | ||
{ | ||
"Sid" : "AllowAll", | ||
"Effect" : "Allow", | ||
"Principal" : { | ||
"AWS" : "*" | ||
}, | ||
"Action" : [ | ||
"dynamodb:*" | ||
], | ||
"Resource" : "*" | ||
} | ||
] | ||
}) | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `vpc_endpoint_id` - (Required) The VPC Endpoint ID. | ||
* `policy` - (Optional) A policy to attach to the endpoint that controls access to the service. Defaults to full access. All `Gateway` and some `Interface` endpoints support policies - see the [relevant AWS documentation](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints-access.html) for more details. For more information about building AWS IAM policy documents with Terraform, see the [AWS IAM Policy Document Guide](https://learn.hashicorp.com/terraform/aws/iam-policy). | ||
|
||
## Attributes Reference | ||
|
||
In addition to all arguments above, the following attributes are exported: | ||
|
||
* `id` - The ID of the VPC endpoint. | ||
|
||
## Import | ||
|
||
VPC Endpoint Policies can be imported using the `id`, e.g. | ||
|
||
``` | ||
$ terraform import aws_vpc_endpoint_policy.example vpce-3ecf2a57 | ||
``` |