Skip to content

Commit 2637d50

Browse files
authored
Merge pull request #1143 from wvanderwaal-iqmessenger/policy_based_vpn_mode
Added policy_based_vpn_mode to NAT resource
2 parents 4da0202 + 8cf9c98 commit 2637d50

File tree

3 files changed

+197
-53
lines changed

3 files changed

+197
-53
lines changed

nsxt/resource_nsxt_policy_nat_rule.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ var policyNATRuleFirewallMatchTypeValues = []string{
3434
model.PolicyNatRule_FIREWALL_MATCH_BYPASS,
3535
}
3636

37+
var policyNATRulePolicyBasedVpnModeTypeValues = []string{
38+
model.PolicyNatRule_POLICY_BASED_VPN_MODE_BYPASS,
39+
model.PolicyNatRule_POLICY_BASED_VPN_MODE_MATCH,
40+
}
41+
3742
func resourceNsxtPolicyNATRule() *schema.Resource {
3843
return &schema.Resource{
3944
Create: resourceNsxtPolicyNATRuleCreate,
@@ -131,6 +136,13 @@ func resourceNsxtPolicyNATRule() *schema.Resource {
131136
Computed: true,
132137
Elem: getElemPolicyPathSchema(),
133138
},
139+
"policy_based_vpn_mode": {
140+
Type: schema.TypeString,
141+
Description: "Policy based vpn mode match flag. DNAT and NO_DNAT only",
142+
Optional: true,
143+
Computed: true,
144+
ValidateFunc: validation.StringInSlice(policyNATRulePolicyBasedVpnModeTypeValues, false),
145+
},
134146
},
135147
}
136148
}
@@ -185,6 +197,13 @@ func patchNsxtPolicyNATRule(sessionContext utl.SessionContext, connector client.
185197
if err != nil {
186198
return err
187199
}
200+
if nsxVersionHigherOrEqual("4.0.0") {
201+
_, err = getPolicyBasedVpnMode(rule)
202+
if err != nil {
203+
return err
204+
}
205+
}
206+
188207
if isT0 {
189208
client := t0nat.NewNatRulesClient(sessionContext, connector)
190209
return client.Patch(gwID, natType, *rule.Id, rule)
@@ -214,6 +233,19 @@ func getTranslatedNetworks(rule model.PolicyNatRule) (*string, error) {
214233
return tNets, nil
215234
}
216235

236+
func policyBasedVpnModeNeeded(action string) bool {
237+
return action == model.PolicyNatRule_ACTION_DNAT || action == model.PolicyNatRule_ACTION_NO_DNAT
238+
}
239+
240+
func getPolicyBasedVpnMode(rule model.PolicyNatRule) (*string, error) {
241+
pbvmMatch := rule.PolicyBasedVpnMode
242+
action := rule.Action
243+
if pbvmMatch != nil && !policyBasedVpnModeNeeded(*action) {
244+
return pbvmMatch, fmt.Errorf("Invalid NAT rule action %s for policy based vpn mode %s. policy based vpn mode supported only on DNAT/NO_DNAT rule", *action, *pbvmMatch)
245+
}
246+
return pbvmMatch, nil
247+
}
248+
217249
func resourceNsxtPolicyNATRuleRead(d *schema.ResourceData, m interface{}) error {
218250
connector := getPolicyConnector(m)
219251

@@ -263,7 +295,9 @@ func resourceNsxtPolicyNATRuleRead(d *schema.ResourceData, m interface{}) error
263295
}
264296
d.Set("translated_ports", obj.TranslatedPorts)
265297
d.Set("scope", obj.Scope)
266-
298+
if nsxVersionHigherOrEqual("4.0.0") {
299+
d.Set("policy_based_vpn_mode", obj.PolicyBasedVpnMode)
300+
}
267301
d.SetId(id)
268302

269303
return nil
@@ -305,6 +339,7 @@ func resourceNsxtPolicyNATRuleCreate(d *schema.ResourceData, m interface{}) erro
305339
priority := int64(d.Get("rule_priority").(int))
306340
service := d.Get("service").(string)
307341
ports := d.Get("translated_ports").(string)
342+
pbvmMatch := d.Get("policy_based_vpn_mode").(string)
308343
dNets := stringListToCommaSeparatedString(interfaceListToStringList(d.Get("destination_networks").([]interface{})))
309344
sNets := stringListToCommaSeparatedString(interfaceListToStringList(d.Get("source_networks").([]interface{})))
310345
tNets := stringListToCommaSeparatedString(interfaceListToStringList(d.Get("translated_networks").([]interface{})))
@@ -334,6 +369,9 @@ func resourceNsxtPolicyNATRuleCreate(d *schema.ResourceData, m interface{}) erro
334369
if ports != "" {
335370
ruleStruct.TranslatedPorts = &ports
336371
}
372+
if pbvmMatch != "" && nsxVersionHigherOrEqual("4.0.0") {
373+
ruleStruct.PolicyBasedVpnMode = &pbvmMatch
374+
}
337375

338376
log.Printf("[INFO] Creating NAT Rule with ID %s", id)
339377

@@ -404,6 +442,10 @@ func resourceNsxtPolicyNATRuleUpdate(d *schema.ResourceData, m interface{}) erro
404442
if tPorts != "" {
405443
ruleStruct.TranslatedPorts = &tPorts
406444
}
445+
pbvmMatch := d.Get("policy_based_vpn_mode").(string)
446+
if pbvmMatch != "" && nsxVersionHigherOrEqual("4.0.0") {
447+
ruleStruct.PolicyBasedVpnMode = &pbvmMatch
448+
}
407449

408450
log.Printf("[INFO] Updating NAT Rule with ID %s", id)
409451
err := patchNsxtPolicyNATRule(context, connector, gwID, ruleStruct, isT0)

nsxt/resource_nsxt_policy_nat_rule_test.go

Lines changed: 135 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,67 @@ func testAccResourceNsxtPolicyNATRuleBasicT1(t *testing.T, withContext bool, pre
139139
})
140140
}
141141

142+
func TestAccResourceNsxtPolicyNATRule_withPolicyBasedVpnMode(t *testing.T) {
143+
name := getAccTestResourceName()
144+
updateName := getAccTestResourceName()
145+
snet := "22.1.1.2"
146+
dnet := "33.1.1.2"
147+
tnet := "44.1.1.2"
148+
action := model.PolicyNatRule_ACTION_DNAT
149+
150+
resource.ParallelTest(t, resource.TestCase{
151+
PreCheck: func() { testAccPreCheck(t); testAccNSXVersion(t, "4.0.0") },
152+
Providers: testAccProviders,
153+
CheckDestroy: func(state *terraform.State) error {
154+
return testAccNsxtPolicyNATRuleCheckDestroy(state, name, false)
155+
},
156+
Steps: []resource.TestStep{
157+
{
158+
Config: testAccNsxtPolicyNATRuleTier1CreateTemplateWithPolicyBasedVpnMode(name, action, testAccResourcePolicyNATRuleSourceNet, testAccResourcePolicyNATRuleDestNet, testAccResourcePolicyNATRuleTransNet, model.PolicyNatRule_POLICY_BASED_VPN_MODE_BYPASS, false),
159+
Check: resource.ComposeTestCheckFunc(
160+
testAccNsxtPolicyNATRuleExists(testAccResourcePolicyNATRuleName, false),
161+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "display_name", name),
162+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "description", "Acceptance Test"),
163+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "destination_networks.#", "1"),
164+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "source_networks.#", "1"),
165+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "translated_networks.#", "1"),
166+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "destination_networks.0", testAccResourcePolicyNATRuleDestNet),
167+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "source_networks.0", testAccResourcePolicyNATRuleSourceNet),
168+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "translated_networks.0", testAccResourcePolicyNATRuleTransNet),
169+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "tag.#", "2"),
170+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "action", action),
171+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "logging", "false"),
172+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "firewall_match", model.PolicyNatRule_FIREWALL_MATCH_BYPASS),
173+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "policy_based_vpn_mode", model.PolicyNatRule_POLICY_BASED_VPN_MODE_BYPASS),
174+
resource.TestCheckResourceAttrSet(testAccResourcePolicyNATRuleName, "path"),
175+
resource.TestCheckResourceAttrSet(testAccResourcePolicyNATRuleName, "revision"),
176+
),
177+
},
178+
{
179+
Config: testAccNsxtPolicyNATRuleTier1CreateTemplateWithPolicyBasedVpnMode(updateName, action, snet, dnet, tnet, model.PolicyNatRule_POLICY_BASED_VPN_MODE_MATCH, false),
180+
Check: resource.ComposeTestCheckFunc(
181+
testAccNsxtPolicyNATRuleExists(testAccResourcePolicyNATRuleName, false),
182+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "display_name", updateName),
183+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "description", "Acceptance Test"),
184+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "destination_networks.#", "1"),
185+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "source_networks.#", "1"),
186+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "translated_networks.#", "1"),
187+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "destination_networks.0", dnet),
188+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "source_networks.0", snet),
189+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "translated_networks.0", tnet),
190+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "tag.#", "2"),
191+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "action", action),
192+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "logging", "false"),
193+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "firewall_match", model.PolicyNatRule_FIREWALL_MATCH_BYPASS),
194+
resource.TestCheckResourceAttr(testAccResourcePolicyNATRuleName, "policy_based_vpn_mode", model.PolicyNatRule_POLICY_BASED_VPN_MODE_MATCH),
195+
resource.TestCheckResourceAttrSet(testAccResourcePolicyNATRuleName, "path"),
196+
resource.TestCheckResourceAttrSet(testAccResourcePolicyNATRuleName, "revision"),
197+
),
198+
},
199+
},
200+
})
201+
}
202+
142203
func TestAccResourceNsxtPolicyNATRule_basicT0(t *testing.T) {
143204
name := getAccTestResourceName()
144205
updateName := getAccTestResourceName()
@@ -455,16 +516,16 @@ data "nsxt_policy_service" "test" {
455516
456517
resource "nsxt_policy_nat_rule" "test" {
457518
%s
458-
display_name = "%s"
459-
description = "Acceptance Test"
460-
gateway_path = nsxt_policy_tier1_gateway.test.path
461-
action = "%s"
462-
source_networks = ["%s"]
463-
destination_networks = ["%s"]
464-
translated_networks = ["%s"]
465-
logging = false
466-
firewall_match = "%s"
467-
service = data.nsxt_policy_service.test.path
519+
display_name = "%s"
520+
description = "Acceptance Test"
521+
gateway_path = nsxt_policy_tier1_gateway.test.path
522+
action = "%s"
523+
source_networks = ["%s"]
524+
destination_networks = ["%s"]
525+
translated_networks = ["%s"]
526+
logging = false
527+
firewall_match = "%s"
528+
service = data.nsxt_policy_service.test.path
468529
469530
tag {
470531
scope = "scope1"
@@ -479,6 +540,44 @@ resource "nsxt_policy_nat_rule" "test" {
479540
`, context, name, action, sourceNet, destNet, translatedNet, model.PolicyNatRule_FIREWALL_MATCH_BYPASS)
480541
}
481542

543+
func testAccNsxtPolicyNATRuleTier1CreateTemplateWithPolicyBasedVpnMode(name string, action string, sourceNet string, destNet string, translatedNet string, policyBasedVpnMode string, withContext bool) string {
544+
context := ""
545+
if withContext {
546+
context = testAccNsxtPolicyMultitenancyContext()
547+
}
548+
return testAccNsxtPolicyEdgeClusterReadTemplate(getEdgeClusterName()) +
549+
testAccNsxtPolicyTier1WithEdgeClusterTemplate("test", false, withContext) + fmt.Sprintf(`
550+
data "nsxt_policy_service" "test" {
551+
display_name = "DNS-UDP"
552+
}
553+
554+
resource "nsxt_policy_nat_rule" "test" {
555+
%s
556+
display_name = "%s"
557+
description = "Acceptance Test"
558+
gateway_path = nsxt_policy_tier1_gateway.test.path
559+
action = "%s"
560+
source_networks = ["%s"]
561+
destination_networks = ["%s"]
562+
translated_networks = ["%s"]
563+
logging = false
564+
firewall_match = "%s"
565+
service = data.nsxt_policy_service.test.path
566+
policy_based_vpn_mode = "%s"
567+
568+
tag {
569+
scope = "scope1"
570+
tag = "tag1"
571+
}
572+
573+
tag {
574+
scope = "scope2"
575+
tag = "tag2"
576+
}
577+
}
578+
`, context, name, action, sourceNet, destNet, translatedNet, model.PolicyNatRule_FIREWALL_MATCH_BYPASS, policyBasedVpnMode)
579+
}
580+
482581
func testAccNsxtPolicyNATRuleTier1UpdateMultipleSourceNetworksTemplate(name string, action string, sourceNet1 string, sourceNet2 string, destNet string, translatedNet string, withContext bool) string {
483582
context := ""
484583
if withContext {
@@ -488,15 +587,15 @@ func testAccNsxtPolicyNATRuleTier1UpdateMultipleSourceNetworksTemplate(name stri
488587
testAccNsxtPolicyTier1WithEdgeClusterTemplate("test", false, withContext) + fmt.Sprintf(`
489588
resource "nsxt_policy_nat_rule" "test" {
490589
%s
491-
display_name = "%s"
492-
description = "Acceptance Test"
493-
gateway_path = nsxt_policy_tier1_gateway.test.path
494-
action = "%s"
495-
source_networks = ["%s", "%s"]
496-
destination_networks = ["%s"]
497-
translated_networks = ["%s"]
498-
logging = false
499-
firewall_match = "%s"
590+
display_name = "%s"
591+
description = "Acceptance Test"
592+
gateway_path = nsxt_policy_tier1_gateway.test.path
593+
action = "%s"
594+
source_networks = ["%s", "%s"]
595+
destination_networks = ["%s"]
596+
translated_networks = ["%s"]
597+
logging = false
598+
firewall_match = "%s"
500599
501600
tag {
502601
scope = "scope1"
@@ -549,15 +648,15 @@ resource "nsxt_policy_tier0_gateway_interface" "test" {
549648
}
550649
551650
resource "nsxt_policy_nat_rule" "test" {
552-
display_name = "%s"
553-
description = "Acceptance Test"
554-
gateway_path = nsxt_policy_tier0_gateway.test.path
555-
action = "%s"
556-
source_networks = ["%s"]
557-
translated_networks = ["%s"]
558-
logging = false
559-
firewall_match = "%s"
560-
scope = [nsxt_policy_tier0_gateway_interface.test[1].path, nsxt_policy_tier0_gateway_interface.test[0].path]
651+
display_name = "%s"
652+
description = "Acceptance Test"
653+
gateway_path = nsxt_policy_tier0_gateway.test.path
654+
action = "%s"
655+
source_networks = ["%s"]
656+
translated_networks = ["%s"]
657+
logging = false
658+
firewall_match = "%s"
659+
scope = [nsxt_policy_tier0_gateway_interface.test[1].path, nsxt_policy_tier0_gateway_interface.test[0].path]
561660
562661
tag {
563662
scope = "scope1"
@@ -577,14 +676,14 @@ func testAccNsxPolicyNatRuleNoTranslatedNetworkTemplate(name string, action stri
577676
return testAccNsxtPolicyEdgeClusterReadTemplate(getEdgeClusterName()) +
578677
testAccNsxtPolicyTier1WithEdgeClusterTemplate("test", false, false) + fmt.Sprintf(`
579678
resource "nsxt_policy_nat_rule" "test" {
580-
display_name = "%s"
581-
description = "Acceptance Test"
582-
gateway_path = nsxt_policy_tier1_gateway.test.path
583-
action = "%s"
584-
source_networks = ["%s"]
585-
destination_networks = ["%s"]
586-
logging = false
587-
firewall_match = "%s"
679+
display_name = "%s"
680+
description = "Acceptance Test"
681+
gateway_path = nsxt_policy_tier1_gateway.test.path
682+
action = "%s"
683+
source_networks = ["%s"]
684+
destination_networks = ["%s"]
685+
logging = false
686+
firewall_match = "%s"
588687
589688
tag {
590689
scope = "scope1"

website/docs/r/policy_nat_rule.html.markdown

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ This resource is applicable to NSX Global Manager, NSX Policy Manager and VMC.
1515

1616
```hcl
1717
resource "nsxt_policy_nat_rule" "dnat1" {
18-
display_name = "dnat_rule1"
19-
action = "DNAT"
20-
source_networks = ["9.1.1.1", "9.2.1.1"]
21-
destination_networks = ["11.1.1.1"]
22-
translated_networks = ["10.1.1.1"]
23-
gateway_path = nsxt_policy_tier1_gateway.t1gateway.path
24-
logging = false
25-
firewall_match = "MATCH_INTERNAL_ADDRESS"
18+
display_name = "dnat_rule1"
19+
action = "DNAT"
20+
source_networks = ["9.1.1.1", "9.2.1.1"]
21+
destination_networks = ["11.1.1.1"]
22+
translated_networks = ["10.1.1.1"]
23+
gateway_path = nsxt_policy_tier1_gateway.t1gateway.path
24+
logging = false
25+
firewall_match = "MATCH_INTERNAL_ADDRESS"
26+
policy_based_vpn_mode = "BYPASS"
2627
2728
tag {
2829
scope = "color"
@@ -42,14 +43,15 @@ resource "nsxt_policy_nat_rule" "dnat1" {
4243
context {
4344
project_id = data.nsxt_policy_project.demoproj.id
4445
}
45-
display_name = "dnat_rule1"
46-
action = "DNAT"
47-
source_networks = ["9.1.1.1", "9.2.1.1"]
48-
destination_networks = ["11.1.1.1"]
49-
translated_networks = ["10.1.1.1"]
50-
gateway_path = nsxt_policy_tier1_gateway.t1gateway.path
51-
logging = false
52-
firewall_match = "MATCH_INTERNAL_ADDRESS"
46+
display_name = "dnat_rule1"
47+
action = "DNAT"
48+
source_networks = ["9.1.1.1", "9.2.1.1"]
49+
destination_networks = ["11.1.1.1"]
50+
translated_networks = ["10.1.1.1"]
51+
gateway_path = nsxt_policy_tier1_gateway.t1gateway.path
52+
logging = false
53+
firewall_match = "MATCH_INTERNAL_ADDRESS"
54+
policy_based_vpn_mode = "BYPASS"
5355
5456
tag {
5557
scope = "color"
@@ -80,6 +82,7 @@ The following arguments are supported:
8082
* `translated_networks` - (Optional) A list of translated network IP addresses or CIDR.
8183
* `translated_ports` - (Optional) Port number or port range. For use with `DNAT` action only.
8284
* `scope` - (Optional) A list of paths to interfaces and/or labels where the NAT Rule is enforced.
85+
* `policy_based_vpn_mode` - (Optional) Policy based VPN mode. One of `BYPASS`, `MATCH`. For use with `DNAT` and `NO_DNAT` actions only. Defaults to `BYPASS` when applicable. This argument is supported for NSX 4.0.0 and above.
8386

8487
## Attributes Reference
8588

0 commit comments

Comments
 (0)