diff --git a/nsxt/resource_nsxt_policy_project.go b/nsxt/resource_nsxt_policy_project.go index 9fffd9853..f96260357 100644 --- a/nsxt/resource_nsxt_policy_project.go +++ b/nsxt/resource_nsxt_policy_project.go @@ -12,6 +12,7 @@ import ( "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" infra "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/orgs" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/orgs/projects" ) func resourceNsxtPolicyProject() *schema.Resource { @@ -71,6 +72,31 @@ func resourceNsxtPolicyProject() *schema.Resource { Elem: getElemPolicyPathSchema(), Optional: true, }, + "default_security_profile": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "north_south_firewall": { + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: "Flag that indicates whether north-south firewall (Gateway Firewall) is enabled", + }, + }, + }, + }, + }, + }, + }, }, } } @@ -143,7 +169,41 @@ func resourceNsxtPolicyProjectPatch(connector client.Connector, d *schema.Resour log.Printf("[INFO] Patching Project with ID %s", id) client := infra.NewProjectsClient(connector) - return client.Patch(defaultOrgID, id, obj) + err := client.Patch(defaultOrgID, id, obj) + if err != nil { + return err + } + + if d.HasChanges("default_security_profile") { + err = patchVpcSecurityProfile(d, connector, id) + } + return err +} + +func patchVpcSecurityProfile(d *schema.ResourceData, connector client.Connector, projectID string) error { + enabled := false + defaultSecurityProfile := d.Get("default_security_profile") + if defaultSecurityProfile != nil { + dsp := defaultSecurityProfile.([]interface{}) + if len(dsp) > 0 { + northSouthFirewall := dsp[0].(map[string]interface{})["north_south_firewall"] + if northSouthFirewall != nil { + nsfw := northSouthFirewall.([]interface{}) + if len(nsfw) > 0 { + elem := nsfw[0].(map[string]interface{}) + enabled = elem["enabled"].(bool) + } + } + } + } + // Default security profile is created by NSX, we can assume that it's there already + client := projects.NewVpcSecurityProfilesClient(connector) + obj := model.VpcSecurityProfile{ + NorthSouthFirewall: &model.NorthSouthFirewall{ + Enabled: &enabled, + }, + } + return client.Patch(defaultOrgID, projectID, "default", obj) } func resourceNsxtPolicyProjectCreate(d *schema.ResourceData, m interface{}) error { diff --git a/nsxt/resource_nsxt_policy_project_test.go b/nsxt/resource_nsxt_policy_project_test.go index 793e3bed0..01d8ffa5d 100644 --- a/nsxt/resource_nsxt_policy_project_test.go +++ b/nsxt/resource_nsxt_policy_project_test.go @@ -10,10 +10,11 @@ import ( "testing" "text/template" - "github.com/vmware/terraform-provider-nsxt/nsxt/util" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/orgs/projects" + + "github.com/vmware/terraform-provider-nsxt/nsxt/util" ) var shortID = getAccTestRandomString(6) @@ -163,7 +164,7 @@ func TestAccResourceNsxtPolicyProject_411basic(t *testing.T) { }, Providers: testAccProviders, CheckDestroy: func(state *terraform.State) error { - return testAccNsxtPolicyProjectCheckDestroy(state, accTestPolicyProjectUpdateAttributes["display_name"]) + return testAccNsxtPolicyProjectCheckDestroy(state, accTestPolicyProjectUpdateAttributes["DisplayName"]) }, Steps: []resource.TestStep{ { @@ -217,7 +218,7 @@ func TestAccResourceNsxtPolicyProject_420basic(t *testing.T) { }, Providers: testAccProviders, CheckDestroy: func(state *terraform.State) error { - return testAccNsxtPolicyProjectCheckDestroy(state, accTestPolicyProjectUpdateAttributes["display_name"]) + return testAccNsxtPolicyProjectCheckDestroy(state, accTestPolicyProjectUpdateAttributes["DisplayName"]) }, Steps: []resource.TestStep{ { @@ -274,7 +275,7 @@ func TestAccResourceNsxtPolicyProject_900basic(t *testing.T) { }, Providers: testAccProviders, CheckDestroy: func(state *terraform.State) error { - return testAccNsxtPolicyProjectCheckDestroy(state, accTestPolicyProjectUpdateAttributes["display_name"]) + return testAccNsxtPolicyProjectCheckDestroy(state, accTestPolicyProjectUpdateAttributes["DisplayName"]) }, Steps: []resource.TestStep{ { @@ -301,6 +302,51 @@ func TestAccResourceNsxtPolicyProject_900basic(t *testing.T) { }) } +func TestAccResourceNsxtPolicyProject_900defaultSecurityProfile(t *testing.T) { + testResourceName := "nsxt_policy_project.test" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccOnlyLocalManager(t) + testAccNSXVersion(t, "9.0.0") + }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtPolicyProjectCheckDestroy(state, accTestPolicyProjectCreateAttributes["DisplayName"]) + }, + Steps: []resource.TestStep{ + { + // Create: Set T0, Ext GW connection, Ext IPv4 Block, activate default DFW + Config: testAccNsxtPolicyProjectMinimalistic(), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicyProjectGetSecurityProfileNSEnabled(testResourceName, false), + ), + }, + { + // Update: Set T0, Ext GW connection, No Ext IPv4 Block, disable default DFW + Config: testAccNsxtPolicyProjectDefaultSecurityPolicy(false), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicyProjectGetSecurityProfileNSEnabled(testResourceName, false), + ), + }, + { + // Update: Set T0, Ext GW connection, No Ext IPv4 Block, disable default DFW + Config: testAccNsxtPolicyProjectDefaultSecurityPolicy(true), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicyProjectGetSecurityProfileNSEnabled(testResourceName, true), + ), + }, + { + // Update: Set T0, Ext GW connection, No Ext IPv4 Block, disable default DFW + Config: testAccNsxtPolicyProjectDefaultSecurityPolicy(false), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicyProjectGetSecurityProfileNSEnabled(testResourceName, false), + ), + }, + }, + }) +} + func TestAccResourceNsxtPolicyProject_importBasic(t *testing.T) { name := getAccTestResourceName() testResourceName := "nsxt_policy_project.test" @@ -328,6 +374,32 @@ func TestAccResourceNsxtPolicyProject_importBasic(t *testing.T) { }) } +func testAccNsxtPolicyProjectGetSecurityProfileNSEnabled(resourceName string, expectedVal bool) resource.TestCheckFunc { + return func(state *terraform.State) error { + + rs, ok := state.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Policy Project resource %s not found in resources", resourceName) + } + + resourceID := rs.Primary.ID + if resourceID == "" { + return fmt.Errorf("Policy Project resource ID not set in resources") + } + + connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients)) + client := projects.NewVpcSecurityProfilesClient(connector) + obj, err := client.Get(defaultOrgID, resourceID, "default") + if err != nil { + return err + } + if *obj.NorthSouthFirewall.Enabled != expectedVal { + return fmt.Errorf("expected NorthSouthFirewall to be %v, isntead status is %v", *obj.NorthSouthFirewall.Enabled, expectedVal) + } + return nil + } +} + func testAccNsxtPolicyProjectExists(displayName string, resourceName string) resource.TestCheckFunc { return func(state *terraform.State) error { @@ -504,3 +576,16 @@ resource "nsxt_policy_project" "test" { }`, accTestPolicyProjectUpdateAttributes["DisplayName"]) } + +func testAccNsxtPolicyProjectDefaultSecurityPolicy(enabled bool) string { + return fmt.Sprintf(` +resource "nsxt_policy_project" "test" { + display_name = "%s" + default_security_profile { + north_south_firewall { + enabled = %s + } + } + +}`, accTestPolicyProjectCreateAttributes["DisplayName"], strconv.FormatBool(enabled)) +} diff --git a/website/docs/r/policy_project.html.markdown b/website/docs/r/policy_project.html.markdown index b82e7bbbd..2326bb81e 100644 --- a/website/docs/r/policy_project.html.markdown +++ b/website/docs/r/policy_project.html.markdown @@ -38,8 +38,10 @@ The following arguments are supported: * `site_path` - (Optional) This represents the path of the site which is managed by Global Manager. For the local manager, if set, this needs to point to 'default'. * `tier0_gateway_paths` - (Optional) The tier 0 has to be pre-created before Project is created. The tier 0 typically provides connectivity to external world. List of sites for Project has to be subset of sites where the tier 0 spans. * `external_ipv4_blocks` - (Optional) IP blocks used for allocating CIDR blocks for public subnets. These can be consumed by all the VPCs under this project. Available since NSX 4.1.1. -* `tgw_external_connections` - Transit gateway connection objects available to the project. Gateway connection and distributed VLAN connection object path will be allowed. Available since NSX 9.0.0. - +* `tgw_external_connections` - (Optional) Transit gateway connection objects available to the project. Gateway connection and distributed VLAN connection object path will be allowed. Available since NSX 9.0.0. +* `default_security_profile`- (Optional) Default security profile properties for project. + * `north_south_firewall` - (Required) North South firewall configuration. + * `enabled` - (Required) This flag indicates whether north-south firewall (Gateway Firewall) is enabled. If set to false, then gateway firewall policies will not be enforced on the VPCs associated with this configuration. ## Attributes Reference