From 833340c39496994437873c26ef2c1b478386bf9e Mon Sep 17 00:00:00 2001 From: Shizhao Liu Date: Mon, 15 May 2023 18:48:44 +0000 Subject: [PATCH] Fix issue when creating IPSecVpnSession with Compliance suite Change tunnel_profile_path to use the computedPolicyPath so that IPSecVpnSession with compliance suite can be configured correctly. The MR also made enhancement to the docs. Signed-off-by: Shizhao Liu --- .../resource_nsxt_policy_ipsec_vpn_session.go | 2 +- ...urce_nsxt_policy_ipsec_vpn_session_test.go | 226 +++++++++++++++++- .../r/policy_ipsec_vpn_session.html.markdown | 9 +- 3 files changed, 220 insertions(+), 17 deletions(-) diff --git a/nsxt/resource_nsxt_policy_ipsec_vpn_session.go b/nsxt/resource_nsxt_policy_ipsec_vpn_session.go index 72607e488..ce734b8fe 100644 --- a/nsxt/resource_nsxt_policy_ipsec_vpn_session.go +++ b/nsxt/resource_nsxt_policy_ipsec_vpn_session.go @@ -78,7 +78,7 @@ func resourceNsxtPolicyIPSecVpnSession() *schema.Resource { "description": getDescriptionSchema(), "revision": getRevisionSchema(), "tag": getTagsSchema(), - "tunnel_profile_path": getPolicyPathSchema(true, false, "Policy path referencing Tunnel profile to be used."), + "tunnel_profile_path": getComputedPolicyPathSchema("Policy path referencing tunnel profile."), "local_endpoint_path": getPolicyPathSchema(true, false, "Policy path referencing Local endpoint."), "ike_profile_path": getComputedPolicyPathSchema("Policy path referencing Ike profile."), "dpd_profile_path": getComputedPolicyPathSchema("Policy path referencing dpd profile."), diff --git a/nsxt/resource_nsxt_policy_ipsec_vpn_session_test.go b/nsxt/resource_nsxt_policy_ipsec_vpn_session_test.go index 4f21ba6e8..5facc7dcc 100644 --- a/nsxt/resource_nsxt_policy_ipsec_vpn_session_test.go +++ b/nsxt/resource_nsxt_policy_ipsec_vpn_session_test.go @@ -75,6 +75,35 @@ var accTestPolicyIPSecVpnSessionPolicyBasedUpdateAttributes = map[string]string{ "action": "PROTECT", } +var accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes = map[string]string{ + "display_name": ipsecVpnResourceName, + "description": "Test compliance suite", + "enabled": "true", + "vpn_type": "RouteBased", + "authentication_mode": "CERTIFICATE", + "compliance_suite": "FIPS", + "ip_addresses": "169.254.152.26", + "prefix_length": "24", + "peer_address": "18.18.18.21", + "peer_id": "18.18.18.21", + "connection_initiation_mode": "ON_DEMAND", +} + +var accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes = map[string]string{ + "display_name": ipsecVpnResourceName, + "description": "Test compliance suite", + "enabled": "true", + "vpn_type": "PolicyBased", + "authentication_mode": "CERTIFICATE", + "compliance_suite": "FIPS", + "peer_address": "18.18.18.21", + "peer_id": "18.18.18.21", + "connection_initiation_mode": "RESPOND_ONLY", + "sources": "192.170.10.0/24", + "destinations": "192.171.10.0/24", + "action": "PROTECT", +} + var testAccIPSecVpnSessionResourceName = "nsxt_policy_ipsec_vpn_session.test" func TestAccResourceNsxtPolicyIPSecVpnSessionRouteBased_basic(t *testing.T) { @@ -175,6 +204,51 @@ func TestAccResourceNsxtPolicyIPSecVpnSessionRouteBased_basic(t *testing.T) { }) } +func TestAccResourceNsxtPolicyIPSecVpnSessionRouteBasedWithComplianceSuite(t *testing.T) { + + testResourceName := testAccIPSecVpnSessionResourceName + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccOnlyLocalManager(t) + testAccEnvDefined(t, "NSXT_TEST_CERTIFICATE_NAME") + }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtPolicyIPSecVpnSessionCheckDestroy(state, accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["display_name"]) + }, + Steps: []resource.TestStep{ + { + Config: testAccNsxtPolicyIPSecVpnSessionRouteBasedTemplateWithComplianceSuite(true), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicyIPSecVpnSessionExists(accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "display_name", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["display_name"]), + resource.TestCheckResourceAttr(testResourceName, "description", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["description"]), + resource.TestCheckResourceAttrSet(testResourceName, "dpd_profile_path"), + resource.TestCheckResourceAttr(testResourceName, "enabled", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["enabled"]), + resource.TestCheckResourceAttrSet(testResourceName, "service_path"), + resource.TestCheckResourceAttr(testResourceName, "vpn_type", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["vpn_type"]), + resource.TestCheckResourceAttr(testResourceName, "authentication_mode", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["authentication_mode"]), + resource.TestCheckResourceAttr(testResourceName, "compliance_suite", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["compliance_suite"]), + resource.TestCheckResourceAttr(testResourceName, "ip_addresses.0", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["ip_addresses"]), + resource.TestCheckResourceAttr(testResourceName, "prefix_length", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["prefix_length"]), + resource.TestCheckResourceAttr(testResourceName, "peer_address", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["peer_address"]), + resource.TestCheckResourceAttr(testResourceName, "peer_id", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["peer_id"]), + resource.TestCheckResourceAttr(testResourceName, "connection_initiation_mode", accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes["connection_initiation_mode"]), + + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), + ), + }, + { + Config: testAccNsxtPolicyGatewayTemplate(true), + }, + }, + }) +} + func TestAccResourceNsxtPolicyIPSecVpnSessionRouteBased_import(t *testing.T) { testResourceName := testAccIPSecVpnSessionResourceName @@ -273,6 +347,53 @@ func TestAccResourceNsxtPolicyIPSecVpnSessionPolicyBased_basic(t *testing.T) { }) } +func TestAccResourceNsxtPolicyIPSecVpnSessionPolicyBasedWithComplianceSuite(t *testing.T) { + + testResourceName := testAccIPSecVpnSessionResourceName + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccOnlyLocalManager(t) + testAccEnvDefined(t, "NSXT_TEST_CERTIFICATE_NAME") + }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtPolicyIPSecVpnSessionCheckDestroy(state, accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["display_name"]) + }, + Steps: []resource.TestStep{ + { + Config: testAccNsxtPolicyIPSecVpnSessionPolicyBasedTemplateWithComplianceSuite(true), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicyIPSecVpnSessionExists(accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "display_name", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["display_name"]), + resource.TestCheckResourceAttr(testResourceName, "description", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["description"]), + resource.TestCheckResourceAttrSet(testResourceName, "dpd_profile_path"), + resource.TestCheckResourceAttr(testResourceName, "enabled", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["enabled"]), + resource.TestCheckResourceAttrSet(testResourceName, "service_path"), + resource.TestCheckResourceAttr(testResourceName, "vpn_type", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["vpn_type"]), + resource.TestCheckResourceAttr(testResourceName, "authentication_mode", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["authentication_mode"]), + resource.TestCheckResourceAttr(testResourceName, "compliance_suite", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["compliance_suite"]), + resource.TestCheckResourceAttr(testResourceName, "peer_address", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["peer_address"]), + resource.TestCheckResourceAttr(testResourceName, "peer_id", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["peer_id"]), + resource.TestCheckResourceAttr(testResourceName, "connection_initiation_mode", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["connection_initiation_mode"]), + resource.TestCheckResourceAttr(testResourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "rule.0.sources.0", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["sources"]), + resource.TestCheckResourceAttr(testResourceName, "rule.0.destinations.0", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["destinations"]), + resource.TestCheckResourceAttr(testResourceName, "rule.0.action", accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes["action"]), + + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), + ), + }, + { + Config: testAccNsxtPolicyGatewayTemplate(true), + }, + }, + }) +} + func TestAccResourceNsxtPolicyIPSecVpnSessionPolicyBased_tier1(t *testing.T) { testResourceName := testAccIPSecVpnSessionResourceName resource.Test(t, resource.TestCase{ @@ -484,7 +605,32 @@ func testAccNSXPolicyIPSecVpnSessionImporterGetID(s *terraform.State) (string, e return fmt.Sprintf("%s/sessions/%s", servicePath, resourceID), nil } -func testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(isT0 bool) string { +func testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(isT0 bool, useCert bool) string { + certName := getTestCertificateName(false) + var localEndpointTemplate string + if useCert { + localEndpointTemplate = fmt.Sprintf(` +data "nsxt_policy_certificate" "test" { + display_name = "%s" + } + +resource "nsxt_policy_ipsec_vpn_local_endpoint" "test" { + service_path = nsxt_policy_ipsec_vpn_service.test_ipsec_svc.path + display_name = "%s" + local_address = "20.20.0.25" + certificate_path = data.nsxt_policy_certificate.test.path + trust_ca_paths = [data.nsxt_policy_certificate.test.path] + } + `, certName, ipsecVpnResourceName) + } else { + localEndpointTemplate = fmt.Sprintf(` +resource "nsxt_policy_ipsec_vpn_local_endpoint" "test" { + service_path = nsxt_policy_ipsec_vpn_service.test_ipsec_svc.path + display_name = "%s" + local_address = "20.20.0.25" + } + `, ipsecVpnResourceName) + } var vpnServiceTemplate string if isT0 { vpnServiceTemplate = fmt.Sprintf(` @@ -501,7 +647,7 @@ resource "nsxt_policy_ipsec_vpn_service" "test_ipsec_svc" { } `, ipsecVpnResourceName) } - return vpnServiceTemplate + fmt.Sprintf(` + return vpnServiceTemplate + localEndpointTemplate + fmt.Sprintf(` resource "nsxt_policy_ipsec_vpn_ike_profile" "test" { display_name = "%s" description = "Ike profile for ipsec vpn session" @@ -529,19 +675,13 @@ resource "nsxt_policy_ipsec_vpn_dpd_profile" "test" { enabled = true retry_count = 8 } - -resource "nsxt_policy_ipsec_vpn_local_endpoint" "test" { - service_path = nsxt_policy_ipsec_vpn_service.test_ipsec_svc.path - display_name = "%s" - local_address = "20.20.0.25" - } -`, ipsecVpnResourceName, ipsecVpnResourceName, ipsecVpnResourceName, ipsecVpnResourceName) +`, ipsecVpnResourceName, ipsecVpnResourceName, ipsecVpnResourceName) } func testAccNsxtPolicyIPSecVpnSessionRouteBasedMinimalistic() string { attrMap := accTestPolicyIPSecVpnSessionRouteBasedCreateAttributes return testAccNsxtPolicyTier0WithEdgeClusterForVPN() + - testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(true) + + testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(true, false) + fmt.Sprintf(` resource "nsxt_policy_ipsec_vpn_session" "test" { display_name = "%s" @@ -564,7 +704,7 @@ func testAccNsxtPolicyIPSecVpnSessionRouteBasedTemplate(createFlow bool, isT0 bo } else { attrMap = accTestPolicyIPSecVpnSessionRouteBasedUpdateAttributes } - return testAccNsxtPolicyGatewayTemplate(isT0) + testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(isT0) + + return testAccNsxtPolicyGatewayTemplate(isT0) + testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(isT0, false) + fmt.Sprintf(` resource "nsxt_policy_ipsec_vpn_session" "test" { display_name = "%s" @@ -600,7 +740,7 @@ func testAccNsxtPolicyIPSecVpnSessionPolicyBasedTemplate(createFlow bool, isT0 b } else { attrMap = accTestPolicyIPSecVpnSessionPolicyBasedUpdateAttributes } - return testAccNsxtPolicyGatewayTemplate(isT0) + testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(isT0) + + return testAccNsxtPolicyGatewayTemplate(isT0) + testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(isT0, false) + fmt.Sprintf(` resource "nsxt_policy_ipsec_vpn_session" "test" { display_name = "%s" @@ -633,3 +773,65 @@ resource "nsxt_policy_ipsec_vpn_session" "test" { attrMap["authentication_mode"], attrMap["compliance_suite"], attrMap["peer_address"], attrMap["peer_id"], attrMap["psk"], attrMap["connection_initiation_mode"], attrMap["sources"], attrMap["destinations"], attrMap["action"]) } + +func testAccNsxtPolicyIPSecVpnSessionRouteBasedTemplateWithComplianceSuite(isT0 bool) string { + attrMap := accTestPolicyIPSecVpnSessionRouteBasedComlianceSuiteAttributes + return testAccNsxtPolicyGatewayTemplate(isT0) + testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(isT0, true) + + fmt.Sprintf(` +resource "nsxt_policy_ipsec_vpn_session" "test" { + display_name = "%s" + description = "%s" + dpd_profile_path = nsxt_policy_ipsec_vpn_dpd_profile.test.path + local_endpoint_path = nsxt_policy_ipsec_vpn_local_endpoint.test.path + enabled = "%s" + service_path = nsxt_policy_ipsec_vpn_service.test_ipsec_svc.path + vpn_type = "%s" + authentication_mode = "%s" + compliance_suite = "%s" + peer_address = "%s" + peer_id = "%s" + connection_initiation_mode = "%s" + ip_addresses = ["%s"] + prefix_length = "%s" + + tag { + scope = "scope1" + tag = "tag1" + } +}`, attrMap["display_name"], attrMap["description"], attrMap["enabled"], attrMap["vpn_type"], + attrMap["authentication_mode"], attrMap["compliance_suite"], attrMap["peer_address"], attrMap["peer_id"], + attrMap["connection_initiation_mode"], attrMap["ip_addresses"], attrMap["prefix_length"]) +} + +func testAccNsxtPolicyIPSecVpnSessionPolicyBasedTemplateWithComplianceSuite(isT0 bool) string { + attrMap := accTestPolicyIPSecVpnSessionPolicyBasedComlianceSuiteAttributes + return testAccNsxtPolicyGatewayTemplate(isT0) + testAccNsxtPolicyIPSecVpnSessionPreConditionTemplate(isT0, true) + + fmt.Sprintf(` +resource "nsxt_policy_ipsec_vpn_session" "test" { + display_name = "%s" + description = "%s" + dpd_profile_path = nsxt_policy_ipsec_vpn_dpd_profile.test.path + local_endpoint_path = nsxt_policy_ipsec_vpn_local_endpoint.test.path + enabled = "%s" + service_path = nsxt_policy_ipsec_vpn_service.test_ipsec_svc.path + vpn_type = "%s" + authentication_mode = "%s" + compliance_suite = "%s" + peer_address = "%s" + peer_id = "%s" + connection_initiation_mode = "%s" + + rule { + sources = ["%s"] + destinations = ["%s"] + action = "%s" + } + + tag { + scope = "scope1" + tag = "tag1" + } +}`, attrMap["display_name"], attrMap["description"], attrMap["enabled"], attrMap["vpn_type"], + attrMap["authentication_mode"], attrMap["compliance_suite"], attrMap["peer_address"], attrMap["peer_id"], + attrMap["connection_initiation_mode"], attrMap["sources"], attrMap["destinations"], attrMap["action"]) +} diff --git a/website/docs/r/policy_ipsec_vpn_session.html.markdown b/website/docs/r/policy_ipsec_vpn_session.html.markdown index dc3d67289..7bd2bd1a2 100644 --- a/website/docs/r/policy_ipsec_vpn_session.html.markdown +++ b/website/docs/r/policy_ipsec_vpn_session.html.markdown @@ -66,19 +66,20 @@ The following arguments are supported: * `description` - (Optional) Description of the resource. * `tag` - (Optional) A list of scope + tag pairs to associate with this resource. * `nsx_id` - (Optional) The NSX ID of this resource. If set, this ID will be used to create the resource. -* `ike_profile_path` - (Optional) Policy path referencing IKE profile. -* `tunnel_profile_path` - (Required) Policy path referencing Tunnel profile to be used. +* `ike_profile_path` - (Optional) Policy path referencing IKE profile. Note that if user wants to create session with `compliance_suite`, then this field should not be configured, the provider will use the default Profile for each compliance suite type. +* `tunnel_profile_path` - (Optional) Policy path referencing Tunnel profile to be used. Note that if user wants to create session with `compliance_suite`, then this field should not be configured, the provider will use the default Profile for each compliance suite type. * `enabled` - (Optional) Boolean. Enable/Disable IPsec VPN session. Default is "true" (session enabled). * `service_path` - (Required) The path of the IPSec VPN service for the VPN session. * `dpd_profile_path` - (Optional) Policy path referencing Dead Peer Detection (DPD) profile. Default is set to system default profile. * `vpn_type` - (Required) `RouteBased` or `PolicyBased`. Policy Based VPN requires to define protect rules that match local and peer subnets. IPSec security association is negotiated for each pair of local and peer subnet. For PolicyBased Session, `rule` must be specified with `sources`, `destination` and `action`. A Route Based VPN is more flexible, more powerful and recommended over policy based VPN. IP Tunnel port is created and all traffic routed via tunnel port is protected. Routes can be configured statically or can be learned through BGP. A route based VPN is a must for establishing redundant VPN session to remote site. For RouteBased VPN session, `ip_addresses` and `prefix_length` must be specified to create the tunnel interface and its subnet. * `compliance_suite` - (Optional) Compliance suite. Value is one of `CNSA`, `SUITE_B_GCM_128`, `SUITE_B_GCM_256`, `PRIME`, `FOUNDATION`, `FIPS`, `None`. -* `compliance_initiaion_mode` - (Optional) Connection initiation mode used by local endpoint to establish ike connection with peer site. `INITIATOR` - In this mode local endpoint initiates tunnel setup and will also respond to incoming tunnel setup requests from peer gateway. `RESPOND_ONLY` - In this mode, local endpoint shall only respond to incoming tunnel setup requests. It shall not initiate the tunnel setup. `ON_DEMAND` - In this mode local endpoint will initiate tunnel creation once first packet matching the policy rule is received and will also respond to incoming initiation request. +* `compliance_initiation_mode` - (Optional) Connection initiation mode used by local endpoint to establish ike connection with peer site. `INITIATOR` - In this mode local endpoint initiates tunnel setup and will also respond to incoming tunnel setup requests from peer gateway. `RESPOND_ONLY` - In this mode, local endpoint shall only respond to incoming tunnel setup requests. It shall not initiate the tunnel setup. `ON_DEMAND` - In this mode local endpoint will initiate tunnel creation once first packet matching the policy rule is received and will also respond to incoming initiation request. +* `authentication_mode` - (Optional) Peer authentication mode. `PSK` - In this mode a secret key shared between local and peer sites is to be used for authentication. The secret key can be a string with a maximum length of 128 characters. `CERTIFICATE` - In this mode a certificate defined at the global level is to be used for authentication. If user wants to configure compliance_suite, then the authentication_mode can only be `CERTIFICATE`. * `ip_addresses` - (Optional) IP Tunnel interface (commonly referred as VTI) ip_addresses. Only applied for Route Based VPN Session. * `prefix_length` - (Optional) Subnet Prefix Length. Only applied for Route Based VPN Session. * `peer_address` - (Optional) Public IPV4 address of the remote device terminating the VPN connection. * `peer_id` - (Optional) Peer ID to uniquely identify the peer site. The peer ID is the public IP address of the remote device terminating the VPN tunnel. When NAT is configured for the peer, enter the private IP address of the peer. -* `local_endpoint_path` - (Required) Policy path referencing Local endpoint. In VMC, Local Endpoints are pre-configured the user can refer to their path using `data nsxt_policy_ipsec_vpn_local_endpoint` and using the "Private IP1" or "Public IP1" values to refer to the private and public endpoints respectively. +* `local_endpoint_path` - (Required) Policy path referencing Local endpoint. In VMC, Local Endpoints are pre-configured the user can refer to their path using `data nsxt_policy_ipsec_vpn_local_endpoint` and using the "Private IP1" or "Public IP1" values to refer to the private and public endpoints respectively. Note that if `authentication_mode` is `CERTIFICATE`, then the local_endpoint must be configured with `certificate_path` and `trust_ca_paths`. * `rule` - (Optional) Bypass rules for this IPSec VPN Session. Only applicable to `PolicyBased` VPN Session. * `sources` - (Optional) List of source subnets. Subnet format is ipv4 CIDR. * `destinations` - (Optional) List of distination subnets. Subnet format is ipv4 CIDR.