Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

f-aws_directconnect_connection_macsec #26274

Merged
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8d71007
First push to add MACSec support
Jun 21, 2022
5c4d093
Add working acceptance tests
ddericco Aug 10, 2022
6738f1f
Add changelog, run acc test linting
ddericco Aug 12, 2022
a1c5b07
[WIP] Add and update docs
ddericco Aug 23, 2022
45071a7
Minor doc/linting fixes
ddericco Aug 25, 2022
dd223d2
Add support to delete keys on disassociate
ddericco Aug 25, 2022
4ca85df
Add read function to macsec_key resource
ddericco Sep 1, 2022
96a5dd5
Update acceptance tests, clean up dx_connection resource
ddericco Sep 2, 2022
c23c8f1
Minor linting fixes
ddericco Sep 2, 2022
063abff
Add sweeper for aws_dx_macsec_keys, remove secret delete function
ddericco Sep 15, 2022
810926c
Update aws_dx_connection documentation, fix sweeper attribute error
ddericco Sep 15, 2022
ae5cc7f
Remove unneeded schema items, fix docs conflict
ddericco Sep 15, 2022
c12eecc
Minor linting fixes
ddericco Sep 15, 2022
143007a
Additional linting fixes
ddericco Sep 15, 2022
b07f472
Apply code review suggestion: `request_macsec` attribute
ddericco Dec 15, 2022
7f5f063
Merge branch 'hashicorp:main' into f-aws_directconnect_connection-macsec
ddericco Dec 15, 2022
a72afad
Add ForceNew to required attribute, remove update Noop
ddericco Dec 15, 2022
6f984de
Add ForceNew to macsec connection, remove check on macsec_capable attr
ddericco Dec 15, 2022
db13c88
Rerun Terrafmt linting
ddericco Dec 15, 2022
047756f
Apply CR suggestion: rename to `aws_dx_macsec_key_association`
ddericco Dec 15, 2022
8ad97cb
Update internal/provider/provider.go
ddericco Dec 15, 2022
fd0aa9d
Rename docs, add encryption_mode acc test [WIP]
ddericco Dec 15, 2022
3e236d9
Add skip_destroy argument for aws_dx_connection
ddericco Dec 16, 2022
4f71c06
WIP - encryption_mode acceptance test
ddericco Dec 16, 2022
63282e5
Tweak CHANGELOG entries.
ewbankkit Dec 16, 2022
9da4e2b
Fix semgrep 'dgryski.semgrep-go.oddifsequence.odd-sequence-ifs'.
ewbankkit Dec 16, 2022
3d6318c
Fix golangci-lint 'whitespace'.
ewbankkit Dec 16, 2022
e87145e
Remove unused commented functions
ddericco Dec 16, 2022
3f6e762
Cosmetics.
ewbankkit Dec 16, 2022
9e087b5
Finalize encryption_mode acc test
ddericco Dec 18, 2022
1a820f4
r/aws_dx_connection: Fix golangci-lint 'unparam'.
ewbankkit Dec 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changelog/26274.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
```release-note:new-resource
aws_dx_macsec_key_association
```

```release-note:enhancement
resource/aws_dx_connection: Add arguments to enable MACsec support
resource/aws_dx_connection: Add `skip_destroy` argument
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,7 @@ func New(_ context.Context) (*schema.Provider, error) {
"aws_dx_hosted_transit_virtual_interface": directconnect.ResourceHostedTransitVirtualInterface(),
"aws_dx_hosted_transit_virtual_interface_accepter": directconnect.ResourceHostedTransitVirtualInterfaceAccepter(),
"aws_dx_lag": directconnect.ResourceLag(),
"aws_dx_macsec_key_association": directconnect.ResourceMacSecKeyAssociation(),
"aws_dx_private_virtual_interface": directconnect.ResourcePrivateVirtualInterface(),
"aws_dx_public_virtual_interface": directconnect.ResourcePublicVirtualInterface(),
"aws_dx_transit_virtual_interface": directconnect.ResourceTransitVirtualInterface(),
Expand Down
53 changes: 53 additions & 0 deletions internal/service/directconnect/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/aws/aws-sdk-go/service/directconnect"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
Expand Down Expand Up @@ -40,6 +41,13 @@ func ResourceConnection() *schema.Resource {
ForceNew: true,
ValidateFunc: validConnectionBandWidth(),
},
// The MAC Security (MACsec) connection encryption mode.
"encryption_mode": {
Type: schema.TypeString,
Computed: true,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"no_encrypt", "should_encrypt", "must_encrypt"}, false),
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
},
"has_logical_redundancy": {
Type: schema.TypeString,
Computed: true,
Expand All @@ -53,6 +61,18 @@ func ResourceConnection() *schema.Resource {
Required: true,
ForceNew: true,
},
// Indicates whether the connection supports MAC Security (MACsec).
"macsec_capable": {
Type: schema.TypeBool,
Computed: true,
},
// Enable or disable MAC Security (MACsec) on this connection.
"request_macsec": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
"name": {
Type: schema.TypeString,
Required: true,
Expand All @@ -62,12 +82,22 @@ func ResourceConnection() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
// The MAC Security (MACsec) port link status of the connection.
"port_encryption_status": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"skip_destroy": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
"vlan_id": {
Expand All @@ -90,6 +120,7 @@ func resourceConnectionCreate(d *schema.ResourceData, meta interface{}) error {
Bandwidth: aws.String(d.Get("bandwidth").(string)),
ConnectionName: aws.String(name),
Location: aws.String(d.Get("location").(string)),
RequestMACSec: aws.Bool(d.Get("request_macsec").(bool)),
}

if v, ok := d.GetOk("provider_name"); ok {
Expand All @@ -108,6 +139,7 @@ func resourceConnectionCreate(d *schema.ResourceData, meta interface{}) error {
}

d.SetId(aws.StringValue(output.ConnectionId))
d.Set("request_macsec", d.Get("request_macsec").(bool))

return resourceConnectionRead(d, meta)
}
Expand Down Expand Up @@ -139,11 +171,14 @@ func resourceConnectionRead(d *schema.ResourceData, meta interface{}) error {
d.Set("arn", arn)
d.Set("aws_device", connection.AwsDeviceV2)
d.Set("bandwidth", connection.Bandwidth)
d.Set("encryption_mode", connection.EncryptionMode)
d.Set("has_logical_redundancy", connection.HasLogicalRedundancy)
d.Set("jumbo_frame_capable", connection.JumboFrameCapable)
d.Set("location", connection.Location)
d.Set("macsec_capable", connection.MacSecCapable)
d.Set("name", connection.ConnectionName)
d.Set("owner_account_id", connection.OwnerAccount)
d.Set("port_encryption_status", connection.PortEncryptionStatus)
d.Set("provider_name", connection.ProviderName)
d.Set("vlan_id", connection.Vlan)

Expand All @@ -170,6 +205,19 @@ func resourceConnectionRead(d *schema.ResourceData, meta interface{}) error {
func resourceConnectionUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).DirectConnectConn

// Update encryption mode
if d.HasChange("encryption_mode") {
input := &directconnect.UpdateConnectionInput{
ConnectionId: aws.String(d.Id()),
EncryptionMode: aws.String(d.Get("encryption_mode").(string)),
}
log.Printf("[DEBUG] Modifying Direct Connect connection attributes: %s", input)
_, err := conn.UpdateConnection(input)
if err != nil {
return fmt.Errorf("error modifying Direct Connect connection (%s) attributes: %s", d.Id(), err)
}
}

arn := d.Get("arn").(string)
if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")
Expand All @@ -183,6 +231,11 @@ func resourceConnectionUpdate(d *schema.ResourceData, meta interface{}) error {
}

func resourceConnectionDelete(d *schema.ResourceData, meta interface{}) error {
if v, ok := d.GetOk("skip_destroy"); ok && v.(bool) {
log.Printf("[DEBUG] Retaining Direct Connect Connection: %s", d.Id())
return nil
}

conn := meta.(*conns.AWSClient).DirectConnectConn

return deleteConnection(conn, d.Id(), waitConnectionDeleted)
Expand Down
178 changes: 178 additions & 0 deletions internal/service/directconnect/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package directconnect_test

import (
"fmt"
"os"
"regexp"
"testing"

Expand Down Expand Up @@ -73,6 +74,79 @@ func TestAccDirectConnectConnection_disappears(t *testing.T) {
})
}

ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
func TestAccDirectConnectConnection_encryptionMode(t *testing.T) {
dxKey := "DX_CONNECTION_ID"
connectionId := os.Getenv(dxKey)
if connectionId == "" {
t.Skipf("Environment variable %s is not set", dxKey)
}

dxName := "DX_CONNECTION_NAME"
connectionName := os.Getenv(dxName)
if connectionName == "" {
t.Skipf("Environment variable %s is not set", connectionName)
}

resourceName := "aws_dx_connection.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, directconnect.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
Steps: []resource.TestStep{
{
Config: testAccConnectionConfig_encryptionMode(connectionName),
ResourceName: resourceName,
ImportState: true,
ImportStateId: connectionId,
ImportStatePersist: true,
},
{
Config: testAccConnectionConfig_encryptionModeMustEncrypt(resourceName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "encryption_mode", "must_encrypt"),
),
},
},
})
}

func TestAccDirectConnectConnection_macsecRequested(t *testing.T) {
var connection directconnect.Connection
resourceName := "aws_dx_connection.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, directconnect.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckConnectionDestroy,
Steps: []resource.TestStep{
{
Config: testAccConnectionConfig_macsecEnabled(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckConnectionExists(resourceName, &connection),
acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "directconnect", regexp.MustCompile(`dxcon/.+`)),
resource.TestCheckResourceAttr(resourceName, "bandwidth", "100Gbps"),
resource.TestCheckResourceAttrSet(resourceName, "location"),
resource.TestCheckResourceAttr(resourceName, "request_macsec", "true"),
acctest.CheckResourceAttrAccountID(resourceName, "owner_account_id"),
resource.TestCheckResourceAttr(resourceName, "name", rName),
resource.TestCheckResourceAttrSet(resourceName, "provider_name"),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
// Ignore the "macsec_requested" attribute as isn't returned by the API during read/refresh
ImportStateVerifyIgnore: []string{"request_macsec"},
},
},
})
}

func TestAccDirectConnectConnection_providerName(t *testing.T) {
var connection directconnect.Connection
resourceName := "aws_dx_connection.test"
Expand Down Expand Up @@ -107,6 +181,28 @@ func TestAccDirectConnectConnection_providerName(t *testing.T) {
})
}

func TestAccDirectConnectConnection_skipDestroy(t *testing.T) {
var connection directconnect.Connection
resourceName := "aws_dx_connection.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, directconnect.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckConnectionNoDestroy,
Steps: []resource.TestStep{
{
Config: testAccConnectionConfig_skipDestroy(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckConnectionExists(resourceName, &connection),
resource.TestCheckResourceAttr(resourceName, "skip_destroy", "true"),
),
},
},
})
}

func TestAccDirectConnectConnection_tags(t *testing.T) {
var connection directconnect.Connection
resourceName := "aws_dx_connection.test"
Expand Down Expand Up @@ -205,6 +301,22 @@ func testAccCheckConnectionExists(name string, v *directconnect.Connection) reso
}
}

func testAccCheckConnectionNoDestroy(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).DirectConnectConn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_dx_connection" {
continue
}

_, err := tfdirectconnect.FindConnectionByID(conn, rs.Primary.ID)

return err
}

return nil
}

func testAccConnectionConfig_basic(rName string) string {
return fmt.Sprintf(`
data "aws_dx_locations" "test" {}
Expand All @@ -222,6 +334,54 @@ resource "aws_dx_connection" "test" {
`, rName)
}

func testAccConnectionConfig_encryptionModeMustEncrypt(rName string) string {
return fmt.Sprintf(`
resource "aws_dx_connection" "test" {
name = %[1]q
location = "CSOW"
bandwidth = "100Gbps"
encryption_mode = "must_encrypt"
skip_destroy = true
}
`, rName)
}

func testAccConnectionConfig_encryptionMode(rName string) string {
return fmt.Sprintf(`
resource "aws_dx_connection" "test" {
name = %[1]q
location = "CSOW"
bandwidth = "100Gbps"
encryption_mode = "should_encrypt"
skip_destroy = true
}
`, rName)
}

func testAccConnectionConfig_macsecEnabled(rName string) string {
return fmt.Sprintf(`
data "aws_dx_locations" "test" {}

locals {
location_codes = tolist(data.aws_dx_locations.test.location_codes)
idx = min(2, length(local.location_codes) - 1)
}

data "aws_dx_location" "test" {
location_code = local.location_codes[local.idx]
}

resource "aws_dx_connection" "test" {
name = %[1]q
bandwidth = "100Gbps"
location = data.aws_dx_location.test.location_code
request_macsec = true

provider_name = data.aws_dx_location.test.available_providers[0]
}
`, rName)
}

func testAccConnectionConfig_providerName(rName string) string {
return fmt.Sprintf(`
data "aws_dx_locations" "test" {}
Expand All @@ -245,6 +405,24 @@ resource "aws_dx_connection" "test" {
`, rName)
}

func testAccConnectionConfig_skipDestroy(rName string) string {
return fmt.Sprintf(`
data "aws_dx_locations" "test" {}

locals {
location_codes = tolist(data.aws_dx_locations.test.location_codes)
idx = min(2, length(local.location_codes) - 1)
}

resource "aws_dx_connection" "test" {
name = %[1]q
bandwidth = "1Gbps"
location = local.location_codes[local.idx]
skip_destroy = true
}
`, rName)
}

func testAccConnectionConfig_tags1(rName, tagKey1, tagValue1 string) string {
return fmt.Sprintf(`
data "aws_dx_locations" "test" {}
Expand Down
Loading