From f738833029a927a360d1cac92aa7259200ebc8ae Mon Sep 17 00:00:00 2001 From: Anna Khmelnitsky Date: Wed, 19 Apr 2023 18:16:46 +0000 Subject: [PATCH] Add spoofguard profile resource Signed-off-by: Anna Khmelnitsky --- nsxt/provider.go | 1 + ...esource_nsxt_policy_spoof_guard_profile.go | 189 ++++++++++++++++++ ...ce_nsxt_policy_spoof_guard_profile_test.go | 177 ++++++++++++++++ .../policy_spoof_guard_profile.html.markdown | 53 +++++ 4 files changed, 420 insertions(+) create mode 100644 nsxt/resource_nsxt_policy_spoof_guard_profile.go create mode 100644 nsxt/resource_nsxt_policy_spoof_guard_profile_test.go create mode 100644 website/docs/r/policy_spoof_guard_profile.html.markdown diff --git a/nsxt/provider.go b/nsxt/provider.go index 49614e7ac..0a6c4b025 100644 --- a/nsxt/provider.go +++ b/nsxt/provider.go @@ -387,6 +387,7 @@ func Provider() *schema.Provider { "nsxt_policy_ipsec_vpn_local_endpoint": resourceNsxtPolicyIPSecVpnLocalEndpoint(), "nsxt_policy_ip_discovery_profile": resourceNsxtPolicyIPDiscoveryProfile(), "nsxt_policy_context_profile_custom_attribute": resourceNsxtPolicyContextProfileCustomAttribute(), + "nsxt_policy_spoof_guard_profile": resourceNsxtPolicySpoofGuardProfile(), }, ConfigureFunc: providerConfigure, diff --git a/nsxt/resource_nsxt_policy_spoof_guard_profile.go b/nsxt/resource_nsxt_policy_spoof_guard_profile.go new file mode 100644 index 000000000..fd0e38e94 --- /dev/null +++ b/nsxt/resource_nsxt_policy_spoof_guard_profile.go @@ -0,0 +1,189 @@ +/* Copyright © 2020 VMware, Inc. All Rights Reserved. + SPDX-License-Identifier: MPL-2.0 */ + +package nsxt + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" + gm_infra "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra" + gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" +) + +func resourceNsxtPolicySpoofGuardProfile() *schema.Resource { + return &schema.Resource{ + Create: resourceNsxtPolicySpoofGuardProfileCreate, + Read: resourceNsxtPolicySpoofGuardProfileRead, + Update: resourceNsxtPolicySpoofGuardProfileUpdate, + Delete: resourceNsxtPolicySpoofGuardProfileDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "nsx_id": getNsxIDSchema(), + "path": getPathSchema(), + "display_name": getDisplayNameSchema(), + "description": getDescriptionSchema(), + "revision": getRevisionSchema(), + "tag": getTagsSchema(), + "address_binding_allowlist": { + Type: schema.TypeBool, + Optional: true, + }, + }, + } +} + +func resourceNsxtPolicySpoofGuardProfileExists(id string, connector client.Connector, isGlobalManager bool) (bool, error) { + var err error + if isGlobalManager { + client := gm_infra.NewSpoofguardProfilesClient(connector) + _, err = client.Get(id) + } else { + client := infra.NewSpoofguardProfilesClient(connector) + _, err = client.Get(id) + } + if err == nil { + return true, nil + } + + if isNotFoundError(err) { + return false, nil + } + + return false, logAPIError("Error retrieving resource", err) +} + +func resourceNsxtPolicySpoofGuardProfilePatch(d *schema.ResourceData, m interface{}, id string) error { + connector := getPolicyConnector(m) + + displayName := d.Get("display_name").(string) + description := d.Get("description").(string) + tags := getPolicyTagsFromSchema(d) + addressBindingAllowlist := d.Get("address_binding_allowlist").(bool) + + obj := model.SpoofGuardProfile{ + DisplayName: &displayName, + Description: &description, + Tags: tags, + AddressBindingAllowlist: &addressBindingAllowlist, + } + + log.Printf("[INFO] Patching SpoofGuardProfile with ID %s", id) + if isPolicyGlobalManager(m) { + gmObj, convErr := convertModelBindingType(obj, model.SpoofGuardProfileBindingType(), gm_model.SpoofGuardProfileBindingType()) + if convErr != nil { + return convErr + } + client := gm_infra.NewSpoofguardProfilesClient(connector) + return client.Patch(id, gmObj.(gm_model.SpoofGuardProfile), nil) + } + + client := infra.NewSpoofguardProfilesClient(connector) + return client.Patch(id, obj, nil) +} + +func resourceNsxtPolicySpoofGuardProfileCreate(d *schema.ResourceData, m interface{}) error { + + // Initialize resource Id and verify this ID is not yet used + id, err := getOrGenerateID(d, m, resourceNsxtPolicySpoofGuardProfileExists) + if err != nil { + return err + } + + err = resourceNsxtPolicySpoofGuardProfilePatch(d, m, id) + if err != nil { + return handleCreateError("SpoofGuardProfile", id, err) + } + + d.SetId(id) + d.Set("nsx_id", id) + + return resourceNsxtPolicySpoofGuardProfileRead(d, m) +} + +func resourceNsxtPolicySpoofGuardProfileRead(d *schema.ResourceData, m interface{}) error { + connector := getPolicyConnector(m) + + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining SpoofGuardProfile ID") + } + + var obj model.SpoofGuardProfile + if isPolicyGlobalManager(m) { + client := gm_infra.NewSpoofguardProfilesClient(connector) + gmObj, err := client.Get(id) + if err != nil { + return handleReadError(d, "SpoofGuardProfile", id, err) + } + + lmObj, err := convertModelBindingType(gmObj, gm_model.SpoofGuardProfileBindingType(), model.SpoofGuardProfileBindingType()) + if err != nil { + return err + } + obj = lmObj.(model.SpoofGuardProfile) + } else { + client := infra.NewSpoofguardProfilesClient(connector) + var err error + obj, err = client.Get(id) + if err != nil { + return handleReadError(d, "SpoofGuardProfile", id, err) + } + } + + d.Set("display_name", obj.DisplayName) + d.Set("description", obj.Description) + setPolicyTagsInSchema(d, obj.Tags) + d.Set("nsx_id", id) + d.Set("path", obj.Path) + d.Set("revision", obj.Revision) + + d.Set("address_binding_allowlist", obj.AddressBindingAllowlist) + + return nil +} + +func resourceNsxtPolicySpoofGuardProfileUpdate(d *schema.ResourceData, m interface{}) error { + + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining SpoofGuardProfile ID") + } + + err := resourceNsxtPolicySpoofGuardProfilePatch(d, m, id) + if err != nil { + return handleUpdateError("SpoofGuardProfile", id, err) + } + + return resourceNsxtPolicySpoofGuardProfileRead(d, m) +} + +func resourceNsxtPolicySpoofGuardProfileDelete(d *schema.ResourceData, m interface{}) error { + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining SpoofGuardProfile ID") + } + + connector := getPolicyConnector(m) + var err error + if isPolicyGlobalManager(m) { + client := gm_infra.NewSpoofguardProfilesClient(connector) + err = client.Delete(id, nil) + } else { + client := infra.NewSpoofguardProfilesClient(connector) + err = client.Delete(id, nil) + } + + if err != nil { + return handleDeleteError("SpoofGuardProfile", id, err) + } + + return nil +} diff --git a/nsxt/resource_nsxt_policy_spoof_guard_profile_test.go b/nsxt/resource_nsxt_policy_spoof_guard_profile_test.go new file mode 100644 index 000000000..52d299b43 --- /dev/null +++ b/nsxt/resource_nsxt_policy_spoof_guard_profile_test.go @@ -0,0 +1,177 @@ +/* Copyright © 2020 VMware, Inc. All Rights Reserved. + SPDX-License-Identifier: MPL-2.0 */ + +package nsxt + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +var accTestPolicySpoofGuardProfileCreateAttributes = map[string]string{ + "display_name": getAccTestResourceName(), + "description": "terraform created", + "address_binding_allowlist": "true", +} + +var accTestPolicySpoofGuardProfileUpdateAttributes = map[string]string{ + "display_name": getAccTestResourceName(), + "description": "terraform updated", + "address_binding_allowlist": "false", +} + +func TestAccResourceNsxtPolicySpoofGuardProfile_basic(t *testing.T) { + testResourceName := "nsxt_policy_spoof_guard_profile.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtPolicySpoofGuardProfileCheckDestroy(state, accTestPolicySpoofGuardProfileUpdateAttributes["display_name"]) + }, + Steps: []resource.TestStep{ + { + Config: testAccNsxtPolicySpoofGuardProfileTemplate(true), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicySpoofGuardProfileExists(accTestPolicySpoofGuardProfileCreateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "display_name", accTestPolicySpoofGuardProfileCreateAttributes["display_name"]), + resource.TestCheckResourceAttr(testResourceName, "description", accTestPolicySpoofGuardProfileCreateAttributes["description"]), + resource.TestCheckResourceAttr(testResourceName, "address_binding_allowlist", accTestPolicySpoofGuardProfileCreateAttributes["address_binding_allowlist"]), + + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), + ), + }, + { + Config: testAccNsxtPolicySpoofGuardProfileTemplate(false), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicySpoofGuardProfileExists(accTestPolicySpoofGuardProfileUpdateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "display_name", accTestPolicySpoofGuardProfileUpdateAttributes["display_name"]), + resource.TestCheckResourceAttr(testResourceName, "description", accTestPolicySpoofGuardProfileUpdateAttributes["description"]), + resource.TestCheckResourceAttr(testResourceName, "address_binding_allowlist", accTestPolicySpoofGuardProfileUpdateAttributes["address_binding_allowlist"]), + + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), + ), + }, + { + Config: testAccNsxtPolicySpoofGuardProfileMinimalistic(), + Check: resource.ComposeTestCheckFunc( + testAccNsxtPolicySpoofGuardProfileExists(accTestPolicySpoofGuardProfileCreateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "description", ""), + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "0"), + ), + }, + }, + }) +} + +func TestAccResourceNsxtPolicySpoofGuardProfile_importBasic(t *testing.T) { + name := getAccTestResourceName() + testResourceName := "nsxt_policy_spoof_guard_profile.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtPolicySpoofGuardProfileCheckDestroy(state, name) + }, + Steps: []resource.TestStep{ + { + Config: testAccNsxtPolicySpoofGuardProfileMinimalistic(), + }, + { + ResourceName: testResourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccNsxtPolicySpoofGuardProfileExists(displayName string, resourceName string) resource.TestCheckFunc { + return func(state *terraform.State) error { + + connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients)) + + rs, ok := state.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Policy SpoofGuardProfile resource %s not found in resources", resourceName) + } + + resourceID := rs.Primary.ID + if resourceID == "" { + return fmt.Errorf("Policy SpoofGuardProfile resource ID not set in resources") + } + + exists, err := resourceNsxtPolicySpoofGuardProfileExists(resourceID, connector, testAccIsGlobalManager()) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("Policy SpoofGuardProfile %s does not exist", resourceID) + } + + return nil + } +} + +func testAccNsxtPolicySpoofGuardProfileCheckDestroy(state *terraform.State, displayName string) error { + connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients)) + for _, rs := range state.RootModule().Resources { + + if rs.Type != "nsxt_policy_spoof_guard_profile" { + continue + } + + resourceID := rs.Primary.Attributes["id"] + exists, err := resourceNsxtPolicySpoofGuardProfileExists(resourceID, connector, testAccIsGlobalManager()) + if err == nil { + return err + } + + if exists { + return fmt.Errorf("Policy SpoofGuardProfile %s still exists", displayName) + } + } + return nil +} + +func testAccNsxtPolicySpoofGuardProfileTemplate(createFlow bool) string { + var attrMap map[string]string + if createFlow { + attrMap = accTestPolicySpoofGuardProfileCreateAttributes + } else { + attrMap = accTestPolicySpoofGuardProfileUpdateAttributes + } + return fmt.Sprintf(` +resource "nsxt_policy_spoof_guard_profile" "test" { + display_name = "%s" + description = "%s" + + address_binding_allowlist = %s + + tag { + scope = "scope1" + tag = "tag1" + } +}`, attrMap["display_name"], attrMap["description"], attrMap["address_binding_allowlist"]) +} + +func testAccNsxtPolicySpoofGuardProfileMinimalistic() string { + return fmt.Sprintf(` +resource "nsxt_policy_spoof_guard_profile" "test" { + display_name = "%s" + +}`, accTestPolicySpoofGuardProfileUpdateAttributes["display_name"]) +} diff --git a/website/docs/r/policy_spoof_guard_profile.html.markdown b/website/docs/r/policy_spoof_guard_profile.html.markdown new file mode 100644 index 000000000..804f38903 --- /dev/null +++ b/website/docs/r/policy_spoof_guard_profile.html.markdown @@ -0,0 +1,53 @@ +--- +subcategory: "Policy - Segments" +layout: "nsxt" +page_title: "NSXT: nsxt_policy_spoof_guard_profile" +description: A resource to configure SpoofGuard Profile. +--- + +# nsxt_policy_spoof_guard_profile + +This resource provides a method for the management of SpoofGuard Profile. + +This resource is applicable to NSX Global Manager, NSX Policy Manager and VMC. + +## Example Usage + +```hcl +resource "nsxt_policy_spoof_guard_profile" "test" { + display_name = "test" + description = "Terraform provisioned SpoofGuardProfile" + address_binding_allowlist = true +} +``` + +## Argument Reference + +The following arguments are supported: + +* `display_name` - (Required) Display name of the resource. +* `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. +* `address_binding_allowlist` - (Optional) If true, enable the SpoofGuard, which only allows IPs listed in address bindings. + + +## Attributes Reference + +In addition to arguments listed above, the following attributes are exported: + +* `id` - ID of the resource. +* `revision` - Indicates current revision number of the object as seen by NSX-T API server. This attribute can be useful for debugging. +* `path` - The NSX path of the policy resource. + +## Importing + +An existing object can be [imported][docs-import] into this resource, via the following command: + +[docs-import]: https://www.terraform.io/cli/import + +``` +terraform import nsxt_policy_spoof_guard_profile.test UUID +``` + +The above command imports SpoofGuard Profile named `test` with the NSX ID `UUID`.