diff --git a/go.mod b/go.mod index 400f40b09..bf9e11e5e 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/hashicorp/go-uuid v1.0.2 github.com/hashicorp/terraform-plugin-sdk/v2 v2.10.1 github.com/mitchellh/gox v1.0.1 + github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1-beta.1 // github.com/nutanix-core/ntnx-api-golang-sdk-internal/prism-go-client/v16 v16.8.0-5295 // indirect //github.com/nutanix-core/ntnx-api-golang-sdk-internal/networking-go-client/v16 v4.0.2-beta.1 github.com/nutanix-core/ntnx-api-golang-sdk-internal/networking-go-client/v16 v16.9.0-8634 diff --git a/go.sum b/go.sum index b78bbbe30..2fe1958a5 100644 --- a/go.sum +++ b/go.sum @@ -446,6 +446,10 @@ github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= github.com/nutanix-core/ntnx-api-golang-sdk-internal/networking-go-client/v16 v16.9.0-8634 h1:my6PO/SXWtNqmMAVN2jkQULhK+4UoL1AsTEWW1ENsPY= github.com/nutanix-core/ntnx-api-golang-sdk-internal/networking-go-client/v16 v16.9.0-8634/go.mod h1:vHyQVF3IKxmip+xGxXDQznKk1ffrVa4HSiEEueiekaE= +github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1-beta.1 h1:YpWpFBiRGrVEBgHKaHVb4PDtApjwl988X91EEftIvjk= +github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1-beta.1/go.mod h1:75Ro+aFIepNAkf2eWjFrFR7m+Ct36EVrD9n9pwAYBrc= +github.com/nutanix/ntnx-api-golang-clients/networking-go-client/v4 v4.0.2-beta.1 h1:PvZQwYhhJtxmzLpnzEhHTpp2fV6woc6W65PHGsHzVfs= +github.com/nutanix/ntnx-api-golang-clients/networking-go-client/v4 v4.0.2-beta.1/go.mod h1:+eZgV1+xL/r84qmuFSVt5R8OFRO70rEz92jOnVgJNco= github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4 v4.0.1-beta.1 h1:hvy3QCc2SgVidYxTq0rRPOazJOt1PP8A86kW7j6sywU= github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4 v4.0.1-beta.1/go.mod h1:Yhk+xD4mN90OKEHnk5ARf97CX5p4+MEC/B/YIVoZeZ0= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= diff --git a/nutanix/config.go b/nutanix/config.go index e875fc9b8..747f661fa 100644 --- a/nutanix/config.go +++ b/nutanix/config.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v3/karbon" + "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/microseg" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/networking" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/prism" @@ -89,6 +90,10 @@ func (c *Config) Client() (*Client, error) { if err != nil { return nil, err } + microsegClient, err := microseg.NewMicrosegClient(configCreds) + if err != nil { + return nil, err + } return &Client{ WaitTimeout: c.WaitTimeout, API: v3Client, @@ -98,6 +103,7 @@ func (c *Config) Client() (*Client, error) { Era: eraClient, NetworkingAPI: networkingClient, PrismAPI: prismClient, + MicroSegAPI: microsegClient, }, nil } @@ -111,4 +117,5 @@ type Client struct { Era *era.Client NetworkingAPI *networking.Client PrismAPI *prism.Client + MicroSegAPI *microseg.Client } diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index aeb71c446..7fefed50f 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -225,6 +225,8 @@ func Provider() *schema.Provider { "nutanix_vpcs_v2": networkingv2.DataSourceNutanixVPCsv2(), "nutanix_floating_ip_v2": networkingv2.DatasourceNutanixFloatingIPV2(), "nutanix_floating_ips_v2": networkingv2.DatasourceNutanixFloatingIPsV2(), + "nutanix_network_security_policy_v2": networkingv2.DataSourceNutanixNetworkSecurityPolicyV2(), + "nutanix_network_security_policies_v2": networkingv2.DataSourceNutanixNetworkSecurityPoliciesV2(), "nutanix_route_table_v2": networkingv2.DatasourceNutanixRouteTableV2(), "nutanix_route_tables_v2": networkingv2.DatasourceNutanixRouteTablesV2(), "nutanix_pbr_v2": networkingv2.DatasourceNutanixPbrV2(), @@ -283,6 +285,7 @@ func Provider() *schema.Provider { "nutanix_subnet_v2": networkingv2.ResourceNutanixSubnetV2(), "nutanix_floating_ip_v2": networkingv2.ResourceNutanixFloatingIPv2(), "nutanix_vpc_v2": networkingv2.ResourceNutanixVPCsV2(), + "nutanix_network_security_policy_v2": networkingv2.ResourceNutanixNetworkSecurityPolicyV2(), "nutanix_route_table_v2": networkingv2.ResourceNutanixRouteTablesV2(), "nutanix_pbr_v2": networkingv2.ResourceNutanixPbrsV2(), }, diff --git a/nutanix/sdks/v4/microseg/microseg.go b/nutanix/sdks/v4/microseg/microseg.go new file mode 100644 index 000000000..a34b87a41 --- /dev/null +++ b/nutanix/sdks/v4/microseg/microseg.go @@ -0,0 +1,38 @@ +package microseg + +import ( + "github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4/api" + microseg "github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4/client" + "github.com/terraform-providers/terraform-provider-nutanix/nutanix/client" +) + +type Client struct { + AddressGroupAPIInstance *api.AddressGroupsApi + ServiceGroupAPIInstance *api.ServiceGroupsApi + NetworkingSecurityInstance *api.NetworkSecurityPoliciesApi +} + +func NewMicrosegClient(credentials client.Credentials) (*Client, error) { + var baseClient *microseg.ApiClient + + // check if all required fields are present. Else create an empty client + if credentials.Username != "" && credentials.Password != "" && credentials.Endpoint != "" { + pcClient := microseg.NewApiClient() + + pcClient.Host = credentials.Endpoint + pcClient.Password = credentials.Password + pcClient.Username = credentials.Username + pcClient.Port = 9440 + pcClient.VerifySSL = false + + baseClient = pcClient + } + + f := &Client{ + AddressGroupAPIInstance: api.NewAddressGroupsApi(baseClient), + ServiceGroupAPIInstance: api.NewServiceGroupsApi(baseClient), + NetworkingSecurityInstance: api.NewNetworkSecurityPoliciesApi(baseClient), + } + + return f, nil +} diff --git a/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policies_v2.go b/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policies_v2.go new file mode 100644 index 000000000..babeab8ed --- /dev/null +++ b/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policies_v2.go @@ -0,0 +1,463 @@ +package networkingv2 + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + import1 "github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4/models/microseg/v4/config" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func DataSourceNutanixNetworkSecurityPoliciesV2() *schema.Resource { + return &schema.Resource{ + ReadContext: DataSourceNutanixNetworkSecurityPoliciesV2Read, + Schema: map[string]*schema.Schema{ + "page": { + Type: schema.TypeInt, + Optional: true, + }, + "limit": { + Type: schema.TypeInt, + Optional: true, + }, + "filter": { + Type: schema.TypeString, + Optional: true, + }, + "order_by": { + Type: schema.TypeString, + Optional: true, + }, + "select": { + Type: schema.TypeString, + Optional: true, + }, + "network_policies": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "state": { + Type: schema.TypeString, + Computed: true, + }, + "rules": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "two_env_isolation_rule_spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "first_isolation_group": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "second_isolation_group": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "application_rule_spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secured_group_category_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "src_allow_spec": { + Type: schema.TypeString, + Computed: true, + }, + "dest_allow_spec": { + Type: schema.TypeString, + Computed: true, + }, + "src_category_references": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "dest_category_references": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "src_subnet": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + "prefix_length": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "dest_subnet": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + "prefix_length": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "src_address_group_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "dest_address_group_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "service_group_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "is_all_protocol_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "tcp_services": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_port": { + Type: schema.TypeInt, + Computed: true, + }, + "end_port": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "udp_services": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_port": { + Type: schema.TypeInt, + Computed: true, + }, + "end_port": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "icmp_services": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_all_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "type": { + Type: schema.TypeInt, + Computed: true, + }, + "code": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "network_function_chain_reference": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "intra_entity_group_rule_spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secured_group_action": { + Type: schema.TypeString, + Computed: true, + }, + "secured_group_category_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + "links": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + }, + "rel": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + "is_ipv6_traffic_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "is_hitlog_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "scope": { + Type: schema.TypeString, + Computed: true, + }, + "vpc_reference": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "secured_groups": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "last_update_time": { + Type: schema.TypeString, + Computed: true, + }, + "creation_time": { + Type: schema.TypeString, + Computed: true, + }, + "is_system_defined": { + Type: schema.TypeBool, + Computed: true, + }, + "created_by": { + Type: schema.TypeString, + Computed: true, + }, + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + }, + "rel": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func DataSourceNutanixNetworkSecurityPoliciesV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).MicroSegAPI + + // initialize query params + var filter, orderBy, selects *string + var page, limit *int + + if pagef, ok := d.GetOk("page"); ok { + page = utils.IntPtr(pagef.(int)) + } else { + page = nil + } + if limitf, ok := d.GetOk("limit"); ok { + limit = utils.IntPtr(limitf.(int)) + } else { + limit = nil + } + if filterf, ok := d.GetOk("filter"); ok { + filter = utils.StringPtr(filterf.(string)) + } else { + filter = nil + } + if order, ok := d.GetOk("order_by"); ok { + orderBy = utils.StringPtr(order.(string)) + } else { + orderBy = nil + } + if selectf, ok := d.GetOk("select"); ok { + selects = utils.StringPtr(selectf.(string)) + } else { + selects = nil + } + + resp, err := conn.NetworkingSecurityInstance.ListNetworkSecurityPolicies(page, limit, filter, orderBy, selects) + if err != nil { + return diag.Errorf("error while fetching network security policy: %v", err) + } + + getResp := resp.Data.GetValue().([]import1.NetworkSecurityPolicy) + if err := d.Set("network_policies", flattenNetworkSecurityPolicy(getResp)); err != nil { + return diag.FromErr(err) + } + + d.SetId(resource.UniqueId()) + return nil +} + +func flattenNetworkSecurityPolicy(pr []import1.NetworkSecurityPolicy) []interface{} { + if len(pr) > 0 { + nets := make([]interface{}, len(pr)) + + for k, v := range pr { + net := make(map[string]interface{}) + + net["ext_id"] = v.ExtId + net["name"] = v.Name + net["type"] = flattenSecurityPolicyType(v.Type) + net["description"] = v.Description + net["state"] = flattenPolicyState(v.State) + net["rules"] = flattenNetworkSecurityPolicyRule(v.Rules) + net["is_ipv6_traffic_allowed"] = v.IsIpv6TrafficAllowed + net["is_hitlog_enabled"] = v.IsHitlogEnabled + if v.Scope != nil { + net["scope"] = flattenSecurityPolicyScope(v.Scope) + } + if v.VpcReferences != nil { + net["vpc_reference"] = v.VpcReferences + } + if v.SecuredGroups != nil { + net["secured_groups"] = v.SecuredGroups + } + if v.LastUpdateTime != nil { + t := v.LastUpdateTime + net["last_update_time"] = t.String() + } + if v.CreationTime != nil { + t := v.CreationTime + net["creation_time"] = t.String() + } + net["is_system_defined"] = v.IsSystemDefined + net["created_by"] = v.CreatedBy + + if v.TenantId != nil { + net["tenant_id"] = v.TenantId + } + if v.Links != nil { + net["links"] = flattenLinksMicroSeg(v.Links) + } + + nets[k] = net + } + return nets + } + return nil +} diff --git a/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policies_v2_test.go b/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policies_v2_test.go new file mode 100644 index 000000000..54b50664e --- /dev/null +++ b/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policies_v2_test.go @@ -0,0 +1,73 @@ +package networkingv2_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" +) + +const datasourceNameNsps = "data.nutanix_network_security_policies_v2.test" + +func TestAccNutanixNSPsDataSourceV2_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccNspsDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.#"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.name"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.links.#"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.state"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.rules.#"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.is_system_defined"), + ), + }, + }, + }) +} + +func TestAccNutanixNSPsDataSourceV2_WithFilter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccNspsDataSourceConfigWithFilter(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.#"), + resource.TestCheckResourceAttr(datasourceNameNsps, "network_policies.#", "1"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.name"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.links.#"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.state"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.rules.#"), + resource.TestCheckResourceAttrSet(datasourceNameNsps, "network_policies.0.is_system_defined"), + ), + }, + }, + }) +} + +func testAccNspsDataSourceConfig() string { + return ` + + data "nutanix_network_security_policies_v2" "test" { } + ` +} + +func testAccNspsDataSourceConfigWithFilter() string { + return ` + + data "nutanix_network_security_policies_v2" "dtest" { } + + locals { + nsp_name = data.nutanix_network_security_policies_v2.dtest.network_policies.0.name + } + + data "nutanix_network_security_policies_v2" "test" { + filter = "name eq '${local.nsp_name}'" + } + ` +} diff --git a/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policy_v2.go b/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policy_v2.go new file mode 100644 index 000000000..2833cb6fd --- /dev/null +++ b/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policy_v2.go @@ -0,0 +1,661 @@ +package networkingv2 + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + config "github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4/models/common/v1/config" + import1 "github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4/models/microseg/v4/config" + + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func DataSourceNutanixNetworkSecurityPolicyV2() *schema.Resource { + return &schema.Resource{ + ReadContext: DataSourceNutanixNetworkSecurityPolicyV2Read, + Schema: map[string]*schema.Schema{ + "ext_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "state": { + Type: schema.TypeString, + Computed: true, + }, + "rules": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "two_env_isolation_rule_spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "first_isolation_group": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "second_isolation_group": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "application_rule_spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secured_group_category_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "src_allow_spec": { + Type: schema.TypeString, + Computed: true, + }, + "dest_allow_spec": { + Type: schema.TypeString, + Computed: true, + }, + "src_category_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "dest_category_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "src_subnet": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + "prefix_length": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "dest_subnet": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + "prefix_length": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "src_address_group_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "dest_address_group_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "service_group_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "is_all_protocol_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "tcp_services": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_port": { + Type: schema.TypeInt, + Computed: true, + }, + "end_port": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "udp_services": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_port": { + Type: schema.TypeInt, + Computed: true, + }, + "end_port": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "icmp_services": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_all_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "type": { + Type: schema.TypeInt, + Computed: true, + }, + "code": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "network_function_chain_reference": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "intra_entity_group_rule_spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secured_group_action": { + Type: schema.TypeString, + Computed: true, + }, + "secured_group_category_references": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + "links": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + }, + "rel": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + "is_ipv6_traffic_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "is_hitlog_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "scope": { + Type: schema.TypeString, + Computed: true, + }, + "vpc_reference": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "secured_groups": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "last_update_time": { + Type: schema.TypeString, + Computed: true, + }, + "creation_time": { + Type: schema.TypeString, + Computed: true, + }, + "is_system_defined": { + Type: schema.TypeBool, + Computed: true, + }, + "created_by": { + Type: schema.TypeString, + Computed: true, + }, + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + }, + "rel": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func DataSourceNutanixNetworkSecurityPolicyV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).MicroSegAPI + + extID := d.Get("ext_id") + + resp, err := conn.NetworkingSecurityInstance.GetNetworkSecurityPolicyById(utils.StringPtr((extID.(string)))) + if err != nil { + return diag.Errorf("error while fetching network security policy: %v", err) + } + getResp := resp.Data.GetValue().(import1.NetworkSecurityPolicy) + + if err := d.Set("name", getResp.Name); err != nil { + return diag.FromErr(err) + } + if err := d.Set("type", flattenSecurityPolicyType(getResp.Type)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("description", getResp.Description); err != nil { + return diag.FromErr(err) + } + if err := d.Set("state", flattenPolicyState(getResp.State)); err != nil { + return diag.FromErr(err) + } + + if err := d.Set("rules", flattenNetworkSecurityPolicyRule(getResp.Rules)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_ipv6_traffic_allowed", getResp.IsIpv6TrafficAllowed); err != nil { + return diag.FromErr(err) + } + + if err := d.Set("is_hitlog_enabled", getResp.IsHitlogEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("scope", flattenSecurityPolicyScope(getResp.Scope)); err != nil { + return diag.FromErr(err) + } + + if err := d.Set("vpc_reference", getResp.VpcReferences); err != nil { + return diag.FromErr(err) + } + + if err := d.Set("secured_groups", getResp.SecuredGroups); err != nil { + return diag.FromErr(err) + } + if getResp.CreationTime != nil { + t := getResp.CreationTime + if err := d.Set("creation_time", t.String()); err != nil { + return diag.FromErr(err) + } + } + if getResp.LastUpdateTime != nil { + t := getResp.LastUpdateTime + if err := d.Set("last_update_time", t.String()); err != nil { + return diag.FromErr(err) + } + } + + if err := d.Set("is_system_defined", getResp.IsSystemDefined); err != nil { + return diag.FromErr(err) + } + + if err := d.Set("created_by", getResp.CreatedBy); err != nil { + return diag.FromErr(err) + } + if err := d.Set("tenant_id", getResp.TenantId); err != nil { + return diag.FromErr(err) + } + if err := d.Set("links", flattenLinksMicroSeg(getResp.Links)); err != nil { + return diag.FromErr(err) + } + + d.SetId(*getResp.ExtId) + return nil +} + +func flattenNetworkSecurityPolicyRule(pr []import1.NetworkSecurityPolicyRule) []interface{} { + if len(pr) > 0 { + nets := make([]interface{}, len(pr)) + + for k, v := range pr { + net := make(map[string]interface{}) + + if v.ExtId != nil { + net["ext_id"] = v.ExtId + } + if v.Description != nil { + net["description"] = v.Description + } + if v.Type != nil { + net["type"] = flattenRuleType(v.Type) + } + if v.Spec != nil { + net["spec"] = flattenOneOfNetworkSecurityPolicyRuleSpec(v.Spec) + } + if v.Links != nil { + net["links"] = flattenLinksMicroSeg(v.Links) + } + nets[k] = net + } + return nets + } + return nil +} + +func flattenOneOfNetworkSecurityPolicyRuleSpec(pr *import1.OneOfNetworkSecurityPolicyRuleSpec) []map[string]interface{} { + if pr != nil { + isolationRuleSpec := make(map[string]interface{}) + isolationRuleSpecList := make([]map[string]interface{}, 0) + appRuleSpec := make(map[string]interface{}) + appRuleSpecList := make([]map[string]interface{}, 0) + intraRuleSpec := make(map[string]interface{}) + intraRuleSpecList := make([]map[string]interface{}, 0) + + if *pr.ObjectType_ == "microseg.v4.config.TwoEnvIsolationRuleSpec" { + env := make(map[string]interface{}) + envList := make([]map[string]interface{}, 0) + + isolationValue := pr.GetValue().(import1.TwoEnvIsolationRuleSpec) + + env["first_isolation_group"] = isolationValue.FirstIsolationGroup + env["second_isolation_group"] = isolationValue.SecondIsolationGroup + + envList = append(envList, env) + + isolationRuleSpec["two_env_isolation_rule_spec"] = envList + + isolationRuleSpecList = append(isolationRuleSpecList, isolationRuleSpec) + + return isolationRuleSpecList + } + if *pr.ObjectType_ == "microseg.v4.config.ApplicationRuleSpec" { + app := make(map[string]interface{}) + appList := make([]map[string]interface{}, 0) + + appRuleValue := pr.GetValue().(import1.ApplicationRuleSpec) + + if appRuleValue.SecuredGroupCategoryReferences != nil { + app["secured_group_category_references"] = appRuleValue.SecuredGroupCategoryReferences + } + if appRuleValue.SrcAllowSpec != nil { + app["src_allow_spec"] = flattenAllowType(appRuleValue.SrcAllowSpec) + } + if appRuleValue.DestAllowSpec != nil { + app["dest_allow_spec"] = flattenAllowType(appRuleValue.DestAllowSpec) + } + if appRuleValue.SrcCategoryReferences != nil { + app["src_category_references"] = appRuleValue.SrcCategoryReferences + } + if appRuleValue.DestCategoryReferences != nil { + app["dest_category_references"] = appRuleValue.DestCategoryReferences + } + if appRuleValue.SrcSubnet != nil { + app["src_subnet"] = flattenIPv4AddressMicroSegList(appRuleValue.SrcSubnet) + } + if appRuleValue.DestSubnet != nil { + app["dest_subnet"] = flattenIPv4AddressMicroSegList(appRuleValue.DestSubnet) + } + if appRuleValue.SrcAddressGroupReferences != nil { + app["src_address_group_references"] = appRuleValue.SrcAddressGroupReferences + } + if appRuleValue.DestAddressGroupReferences != nil { + app["dest_address_group_references"] = appRuleValue.DestAddressGroupReferences + } + if appRuleValue.ServiceGroupReferences != nil { + app["service_group_references"] = appRuleValue.ServiceGroupReferences + } + if appRuleValue.IsAllProtocolAllowed != nil { + app["is_all_protocol_allowed"] = appRuleValue.IsAllProtocolAllowed + } + if appRuleValue.TcpServices != nil { + app["tcp_services"] = flattenTCPPortRangeSpec(appRuleValue.TcpServices) + } + if appRuleValue.UdpServices != nil { + app["udp_services"] = flattenUDPPortRangeSpec(appRuleValue.UdpServices) + } + if appRuleValue.IcmpServices != nil { + app["icmp_services"] = flattenIcmpTypeCodeSpec(appRuleValue.IcmpServices) + } + if appRuleValue.NetworkFunctionChainReference != nil { + app["network_function_chain_reference"] = appRuleValue.NetworkFunctionChainReference + } + + appList = append(appList, app) + + appRuleSpec["application_rule_spec"] = appList + + appRuleSpecList = append(appRuleSpecList, appRuleSpec) + return appRuleSpecList + } + + intra := make(map[string]interface{}) + intraList := make([]map[string]interface{}, 0) + + intraRuleValue := pr.GetValue().(import1.IntraEntityGroupRuleSpec) + + if intraRuleValue.SecuredGroupAction != nil { + intra["secured_group_action"] = flattenIntraEntityGroupRuleAction(intraRuleValue.SecuredGroupAction) + } + if intraRuleValue.SecuredGroupCategoryReferences != nil { + intra["secured_group_category_references"] = intraRuleValue.SecuredGroupCategoryReferences + } + + intraList = append(intraList, intra) + + intraRuleSpec["intra_entity_group_rule_spec"] = intraList + intraRuleSpecList = append(intraRuleSpecList, intraRuleSpec) + + return intraRuleSpecList + } + return nil +} + +func flattenIPv4AddressMicroSegList(pr *config.IPv4Address) []interface{} { + if pr != nil { + ipv4 := make([]interface{}, 0) + + ip := make(map[string]interface{}) + + ip["value"] = pr.Value + ip["prefix_length"] = pr.PrefixLength + + ipv4 = append(ipv4, ip) + + return ipv4 + } + return nil +} + +func flattenAllowType(pr *import1.AllowType) string { + const two, three = 2, 3 + if pr != nil { + if *pr == import1.AllowType(two) { + return "ALL" + } + if *pr == import1.AllowType(three) { + return "NONE" + } + } + return "UNKNOWN" +} + +func flattenPolicyState(pr *import1.SecurityPolicyState) string { + const two, three, four = 2, 3, 4 + if pr != nil { + if *pr == import1.SecurityPolicyState(two) { + return "SAVE" + } + if *pr == import1.SecurityPolicyState(three) { + return "MONITOR" + } + if *pr == import1.SecurityPolicyState(four) { + return "ENFORCE" + } + } + return "UNKNOWN" +} + +func flattenRuleType(pr *import1.RuleType) string { + const two, three, four, five = 2, 3, 4, 5 + if pr != nil { + if *pr == import1.RuleType(two) { + return "QUARANTINE" + } + if *pr == import1.RuleType(three) { + return "TWO_ENV_ISOLATION" + } + if *pr == import1.RuleType(four) { + return "APPLICATION" + } + if *pr == import1.RuleType(five) { + return "ENFORCE" + } + } + return "UNKNOWN" +} + +func flattenSecurityPolicyType(pr *import1.SecurityPolicyType) string { + const two, three, four = 2, 3, 4 + if pr != nil { + if *pr == import1.SecurityPolicyType(two) { + return "QUARANTINE" + } + if *pr == import1.SecurityPolicyType(three) { + return "ISOLATION" + } + if *pr == import1.SecurityPolicyType(four) { + return "APPLICATION" + } + } + return "UNKNOWN" +} + +func flattenSecurityPolicyScope(pr *import1.SecurityPolicyScope) string { + if pr != nil { + const two, three, four = 2, 3, 4 + if *pr == import1.SecurityPolicyScope(two) { + return "ALL_VLAN" + } + if *pr == import1.SecurityPolicyScope(three) { + return "ALL_VPC" + } + if *pr == import1.SecurityPolicyScope(four) { + return "VPC_LIST" + } + } + return "UNKNOWN" +} + +func flattenIntraEntityGroupRuleAction(pr *import1.IntraEntityGroupRuleAction) string { + if pr != nil { + const two, three = 2, 3 + + if *pr == import1.IntraEntityGroupRuleAction(two) { + return "ALLOW" + } + if *pr == import1.IntraEntityGroupRuleAction(three) { + return "DENY" + } + } + return "UNKNOWN" +} diff --git a/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policy_v2_test.go b/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policy_v2_test.go new file mode 100644 index 000000000..2718f6a1e --- /dev/null +++ b/nutanix/services/v2/networkingv2/data_source_nutanix_network_security_policy_v2_test.go @@ -0,0 +1,43 @@ +package networkingv2_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" +) + +const datasourceNameNsp = "data.nutanix_network_security_policy_v2.test" + +func TestAccNutanixNSPDataSourceV2_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccNspDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(datasourceNameNsp, "name"), + resource.TestCheckResourceAttrSet(datasourceNameNsp, "links.#"), + resource.TestCheckResourceAttrSet(datasourceNameNsp, "state"), + resource.TestCheckResourceAttrSet(datasourceNameNsp, "rules.#"), + resource.TestCheckResourceAttrSet(datasourceNameNsp, "rules.0.spec.#"), + resource.TestCheckResourceAttrSet(datasourceNameNsp, "rules.0.type"), + resource.TestCheckResourceAttrSet(datasourceNameNsp, "is_system_defined"), + ), + }, + }, + }) +} + +func testAccNspDataSourceConfig() string { + return ` + + data "nutanix_network_security_policies_v2" "test" { } + + data "nutanix_network_security_policy_v2" "test" { + ext_id = data.nutanix_network_security_policies_v2.test.network_policies.0.ext_id + depends_on = [data.nutanix_network_security_policies_v2.test] + } + ` +} diff --git a/nutanix/services/v2/networkingv2/resource_nutanix_network_security_policies_v2.go b/nutanix/services/v2/networkingv2/resource_nutanix_network_security_policies_v2.go new file mode 100644 index 000000000..4e72e75ca --- /dev/null +++ b/nutanix/services/v2/networkingv2/resource_nutanix_network_security_policies_v2.go @@ -0,0 +1,868 @@ +package networkingv2 + +import ( + "context" + "encoding/json" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + config "github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4/models/common/v1/config" + import1 "github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4/models/microseg/v4/config" + import4 "github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4/models/prism/v4/config" + import2 "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func ResourceNutanixNetworkSecurityPolicyV2() *schema.Resource { + return &schema.Resource{ + CreateContext: ResourceNutanixNetworkSecurityPolicyV2Create, + ReadContext: ResourceNutanixNetworkSecurityPolicyV2Read, + UpdateContext: ResourceNutanixNetworkSecurityPolicyV2Update, + DeleteContext: ResourceNutanixNetworkSecurityPolicyV2Delete, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"QUARANTINE", "ISOLATION", "APPLICATION"}, false), + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "state": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"SAVE", "MONITOR", "ENFORCE"}, false), + }, + "rules": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"QUARANTINE", "TWO_ENV_ISOLATION", "APPLICATION", "INTRA_GROUP"}, false), + }, + "spec": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "two_env_isolation_rule_spec": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "first_isolation_group": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "second_isolation_group": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "application_rule_spec": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secured_group_category_references": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "src_allow_spec": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"ALL", "NONE"}, false), + }, + "dest_allow_spec": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"ALL", "NONE"}, false), + }, + "src_category_references": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "dest_category_references": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "src_subnet": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "prefix_length": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + }, + }, + }, + "dest_subnet": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "prefix_length": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + }, + }, + }, + "src_address_group_references": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "dest_address_group_references": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "service_group_references": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "is_all_protocol_allowed": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "tcp_services": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_port": { + Type: schema.TypeInt, + Required: true, + }, + "end_port": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + "udp_services": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_port": { + Type: schema.TypeInt, + Required: true, + }, + "end_port": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + "icmp_services": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_all_allowed": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "type": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "code": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + }, + }, + }, + "network_function_chain_reference": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + }, + }, + }, + "intra_entity_group_rule_spec": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secured_group_action": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "secured_group_category_references": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + "links": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + }, + "rel": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + "is_ipv6_traffic_allowed": { + Type: schema.TypeBool, + Optional: true, + }, + "is_hitlog_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + "scope": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"ALL_VLAN", "ALL_VPC", "VPC_LIST"}, false), + }, + "vpc_reference": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "secured_groups": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "last_update_time": { + Type: schema.TypeString, + Computed: true, + }, + "creation_time": { + Type: schema.TypeString, + Computed: true, + }, + "is_system_defined": { + Type: schema.TypeBool, + Computed: true, + }, + "created_by": { + Type: schema.TypeString, + Computed: true, + }, + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + }, + "rel": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func ResourceNutanixNetworkSecurityPolicyV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).MicroSegAPI + + spec := import1.NetworkSecurityPolicy{} + + if name, ok := d.GetOk("name"); ok { + spec.Name = utils.StringPtr(name.(string)) + } + if types, ok := d.GetOk("type"); ok { + const two, three, four = 2, 3, 4 + subMap := map[string]interface{}{ + "QUARANTINE": two, + "ISOLATION": three, + "APPLICATION": four, + } + pInt := subMap[types.(string)] + p := import1.SecurityPolicyType(pInt.(int)) + spec.Type = &p + } + if desc, ok := d.GetOk("description"); ok { + spec.Description = utils.StringPtr(desc.(string)) + } + if state, ok := d.GetOk("state"); ok { + const two, three, four = 2, 3, 4 + subMap := map[string]interface{}{ + "SAVE": two, + "MONITOR": three, + "ENFORCE": four, + } + pInt := subMap[state.(string)] + p := import1.SecurityPolicyState(pInt.(int)) + spec.State = &p + } + if rules, ok := d.GetOk("rules"); ok { + spec.Rules = expandNetworkSecurityPolicyRule(rules.([]interface{})) + } + if isipv6, ok := d.GetOk("is_ipv6_traffic_allowed"); ok { + spec.IsIpv6TrafficAllowed = utils.BoolPtr(isipv6.(bool)) + } + if ishitlog, ok := d.GetOk("is_hitlog_enabled"); ok { + spec.IsHitlogEnabled = utils.BoolPtr(ishitlog.(bool)) + } + if scope, ok := d.GetOk("scope"); ok { + const two, three, four = 2, 3, 4 + subMap := map[string]interface{}{ + "ALL_VLAN": two, + "ALL_VPC": three, + "VPC_LIST": four, + } + pInt := subMap[scope.(string)] + p := import1.SecurityPolicyScope(pInt.(int)) + spec.Scope = &p + } + if vpcRef, ok := d.GetOk("vpc_reference"); ok { + spec.VpcReferences = expandStringList(vpcRef.([]interface{})) + } + + log.Println("HELLLLLOOOOOO") + aJSON, _ := json.Marshal(spec) + fmt.Printf("JSON Print - \n%s\n", string(aJSON)) + + resp, err := conn.NetworkingSecurityInstance.CreateNetworkSecurityPolicy(&spec) + if err != nil { + return diag.Errorf("error while creating network security policy: %v", err) + } + + TaskRef := resp.Data.GetValue().(import4.TaskReference) + taskUUID := TaskRef.ExtId + + // calling group API to poll for completion of task + + taskconn := meta.(*conns.Client).PrismAPI + // Wait for the Network security policy to be available + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroupFunc(ctx, taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("error waiting for network security policy (%s) to create: %s", utils.StringValue(taskUUID), errWaitTask) + } + + // Get UUID from TASK API + + resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) + if err != nil { + return diag.Errorf("error while fetching vpc UUID : %v", err) + } + rUUID := resourceUUID.Data.GetValue().(import2.Task) + + uuid := rUUID.EntitiesAffected[0].ExtId + d.SetId(*uuid) + + return ResourceNutanixNetworkSecurityPolicyV2Read(ctx, d, meta) +} + +func ResourceNutanixNetworkSecurityPolicyV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).MicroSegAPI + + resp, err := conn.NetworkingSecurityInstance.GetNetworkSecurityPolicyById(utils.StringPtr((d.Id()))) + if err != nil { + return diag.Errorf("error while fetching network security policy: %v", err) + } + getResp := resp.Data.GetValue().(import1.NetworkSecurityPolicy) + + if err := d.Set("name", getResp.Name); err != nil { + return diag.FromErr(err) + } + if err := d.Set("type", flattenSecurityPolicyType(getResp.Type)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("description", getResp.Description); err != nil { + return diag.FromErr(err) + } + if err := d.Set("state", flattenPolicyState(getResp.State)); err != nil { + return diag.FromErr(err) + } + + // after creating role, operations saved in remote in different order than local + if len(getResp.Rules) > 0 { + // read the remote operations and local operations list + remoteOperations := flattenNetworkSecurityPolicyRule(getResp.Rules) + localOperations := expandNetworkSecurityPolicyRule(d.Get("rules").([]interface{})) + + // final result for checking if operations are different + diff := false + + // convert local operations to string slice + localOperationsStr := make([]string, len(localOperations)) + for i, v := range localOperations { + localOperationsStr[i] = (flattenRuleType(v.Type)) + } + + log.Printf("[DEBUG] localOperationsStr: %v", localOperationsStr) + + // check if remote operations are different from local operations + for _, operation := range remoteOperations { + opsType := operation.(map[string]interface{})["type"] + offset := indexOf(localOperationsStr, opsType.(string)) + + if offset == -1 { + log.Printf("[DEBUG] Rules %v not found in local rules", operation) + diff = true + break + } + } + + // if operations are different, update local operations + if diff { + log.Printf("[DEBUG] Rules are different. Updating local rules") + if err := d.Set("rules", flattenNetworkSecurityPolicyRule(getResp.Rules)); err != nil { + return diag.FromErr(err) + } + } else { + // if operations are same, do not update local operations + log.Printf("[DEBUG] Rules are same. Not updating local rules") + } + } + + if err := d.Set("is_ipv6_traffic_allowed", getResp.IsIpv6TrafficAllowed); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_hitlog_enabled", getResp.IsHitlogEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("scope", flattenSecurityPolicyScope(getResp.Scope)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("vpc_reference", getResp.VpcReferences); err != nil { + return diag.FromErr(err) + } + if err := d.Set("secured_groups", utils.StringSlice(getResp.SecuredGroups)); err != nil { + return diag.FromErr(err) + } + if getResp.CreationTime != nil { + t := getResp.CreationTime + if err := d.Set("creation_time", t.String()); err != nil { + return diag.FromErr(err) + } + } + if getResp.LastUpdateTime != nil { + t := getResp.LastUpdateTime + if err := d.Set("last_update_time", t.String()); err != nil { + return diag.FromErr(err) + } + } + if err := d.Set("is_system_defined", getResp.IsSystemDefined); err != nil { + return diag.FromErr(err) + } + if err := d.Set("created_by", getResp.CreatedBy); err != nil { + return diag.FromErr(err) + } + if err := d.Set("tenant_id", getResp.TenantId); err != nil { + return diag.FromErr(err) + } + if err := d.Set("links", flattenLinksMicroSeg(getResp.Links)); err != nil { + return diag.FromErr(err) + } + return nil +} + +func ResourceNutanixNetworkSecurityPolicyV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).MicroSegAPI + + updatedSpec := import1.NetworkSecurityPolicy{} + + resp, err := conn.NetworkingSecurityInstance.GetNetworkSecurityPolicyById(utils.StringPtr((d.Id()))) + if err != nil { + return diag.Errorf("error while fetching network security : %v", err) + } + + updatedSpec = resp.Data.GetValue().(import1.NetworkSecurityPolicy) + + if d.HasChange("name") { + updatedSpec.Name = utils.StringPtr(d.Get("name").(string)) + } + if d.HasChange("type") { + state := d.Get("type") + const two, three, four = 2, 3, 4 + subMap := map[string]interface{}{ + "QUARANTINE": two, + "ISOLATION": three, + "APPLICATION": four, + } + pInt := subMap[state.(string)] + p := import1.SecurityPolicyType(pInt.(int)) + updatedSpec.Type = &p + } + if d.HasChange("description") { + updatedSpec.Description = utils.StringPtr(d.Get("description").(string)) + } + if d.HasChange("rules") { + updatedSpec.Rules = expandNetworkSecurityPolicyRule(d.Get("rules").([]interface{})) + } + if d.HasChange("state") { + const two, three, four = 2, 3, 4 + subMap := map[string]interface{}{ + "SAVE": two, + "MONITOR": three, + "ENFORCE": four, + } + pInt := subMap[d.Get("state").(string)] + p := import1.SecurityPolicyState(pInt.(int)) + updatedSpec.State = &p + } + if d.HasChange("is_ipv6_traffic_allowed") { + updatedSpec.IsIpv6TrafficAllowed = utils.BoolPtr(d.Get("is_ipv6_traffic_allowed").(bool)) + } + if d.HasChange("is_hitlog_enabled") { + updatedSpec.IsHitlogEnabled = utils.BoolPtr(d.Get("is_hitlog_enabled").(bool)) + } + if d.HasChange("scope") { + const two, three, four = 2, 3, 4 + subMap := map[string]interface{}{ + "ALL_VLAN": two, + "ALL_VPC": three, + "VPC_LIST": four, + } + pInt := subMap[d.Get("scope").(string)] + p := import1.SecurityPolicyScope(pInt.(int)) + updatedSpec.Scope = &p + } + if d.HasChange("vpc_reference") { + updatedSpec.VpcReferences = expandStringList(d.Get("vpc_reference").([]interface{})) + } + + updatedResp, err := conn.NetworkingSecurityInstance.UpdateNetworkSecurityPolicyById(utils.StringPtr(d.Id()), &updatedSpec) + if err != nil { + return diag.Errorf("error while updating network security: %v", err) + } + + TaskRef := updatedResp.Data.GetValue().(import4.TaskReference) + taskUUID := TaskRef.ExtId + + // calling group API to poll for completion of task + + taskconn := meta.(*conns.Client).PrismAPI + // Wait for the Service Group to be available + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroupFunc(ctx, taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("error waiting for network security (%s) to update: %s", utils.StringValue(taskUUID), errWaitTask) + } + return ResourceNutanixNetworkSecurityPolicyV2Read(ctx, d, meta) +} + +func ResourceNutanixNetworkSecurityPolicyV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).MicroSegAPI + + resp, err := conn.NetworkingSecurityInstance.DeleteNetworkSecurityPolicyById(utils.StringPtr(d.Id())) + if err != nil { + return diag.Errorf("error while deleting network security: %v", err) + } + + TaskRef := resp.Data.GetValue().(import4.TaskReference) + taskUUID := TaskRef.ExtId + + // calling group API to poll for completion of task + + taskconn := meta.(*conns.Client).PrismAPI + // Wait for the Service Group to be available + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroupFunc(ctx, taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("error waiting for network security (%s) to delete: %s", utils.StringValue(taskUUID), errWaitTask) + } + return nil +} + +func expandNetworkSecurityPolicyRule(pr []interface{}) []import1.NetworkSecurityPolicyRule { + if len(pr) > 0 { + nets := make([]import1.NetworkSecurityPolicyRule, len(pr)) + + for k, v := range pr { + val := v.(map[string]interface{}) + net := import1.NetworkSecurityPolicyRule{} + + if desc, ok := val["description"]; ok { + net.Description = utils.StringPtr(desc.(string)) + } + if ty, ok := val["type"]; ok { + const two, three, four, five = 2, 3, 4, 5 + subMap := map[string]interface{}{ + "QUARANTINE": two, + "TWO_ENV_ISOLATION": three, + "APPLICATION": four, + "INTRA_GROUP": five, + } + pInt := subMap[ty.(string)] + p := import1.RuleType(pInt.(int)) + net.Type = &p + } + if spec, ok := val["spec"]; ok { + net.Spec = expandOneOfNetworkSecurityPolicyRuleSpec(spec) + } + nets[k] = net + } + return nets + } + return nil +} + +func expandOneOfNetworkSecurityPolicyRuleSpec(pr interface{}) *import1.OneOfNetworkSecurityPolicyRuleSpec { + if pr != nil { + prI := pr.([]interface{}) + val := prI[0].(map[string]interface{}) + policyRules := &import1.OneOfNetworkSecurityPolicyRuleSpec{} + + if isolation, ok := val["two_env_isolation_rule_spec"]; ok && len(isolation.([]interface{})) > 0 { + iso := import1.NewTwoEnvIsolationRuleSpec() + + isoI := isolation.([]interface{}) + isoVal := isoI[0].(map[string]interface{}) + + if firstIso, ok := isoVal["first_isolation_group"]; ok && len(firstIso.([]interface{})) > 0 { + iso.FirstIsolationGroup = expandStringList(firstIso.([]interface{})) + } + if secIso, ok := isoVal["second_isolation_group"]; ok && len(secIso.([]interface{})) > 0 { + iso.SecondIsolationGroup = expandStringList(secIso.([]interface{})) + } + policyRules.SetValue(*iso) + } + + if appRule, ok := val["application_rule_spec"]; ok && len(appRule.([]interface{})) > 0 { + app := import1.NewApplicationRuleSpec() + + appI := appRule.([]interface{}) + appVal := appI[0].(map[string]interface{}) + + if secGroup, ok := appVal["secured_group_category_references"]; ok && len(secGroup.([]interface{})) > 0 { + app.SecuredGroupCategoryReferences = expandStringList(secGroup.([]interface{})) + } + if srcAllow, ok := appVal["src_allow_spec"]; ok && len(srcAllow.(string)) > 0 { + const two, three = 2, 3 + subMap := map[string]interface{}{ + "ALL": two, + "NONE": three, + } + pInt := subMap[srcAllow.(string)] + p := import1.AllowType(pInt.(int)) + app.SrcAllowSpec = &p + } + if denyAllow, ok := appVal["dest_allow_spec"]; ok && len(denyAllow.(string)) > 0 { + const two, three = 2, 3 + subMap := map[string]interface{}{ + "ALL": two, + "NONE": three, + } + pInt := subMap[denyAllow.(string)] + p := import1.AllowType(pInt.(int)) + app.DestAllowSpec = &p + } + if srcCatRef, ok := appVal["src_category_references"]; ok && len(srcCatRef.([]interface{})) > 0 { + app.SrcCategoryReferences = expandStringList(srcCatRef.([]interface{})) + } + if destCatRef, ok := appVal["dest_category_references"]; ok && len(destCatRef.([]interface{})) > 0 { + app.DestCategoryReferences = expandStringList(destCatRef.([]interface{})) + } + if srcSubnet, ok := appVal["src_subnet"]; ok && len(srcSubnet.([]interface{})) > 0 { + app.SrcSubnet = expandIPv4AddressMicroseg(srcSubnet) + } + if destSubnet, ok := appVal["dest_subnet"]; ok && len(destSubnet.([]interface{})) > 0 { + app.DestSubnet = expandIPv4AddressMicroseg(destSubnet) + } + if srcAddGrpRef, ok := appVal["src_address_group_references"]; ok && len(srcAddGrpRef.([]interface{})) > 0 { + app.SrcAddressGroupReferences = expandStringList(srcAddGrpRef.([]interface{})) + } + if destAddGrpRef, ok := appVal["dest_address_group_references"]; ok && len(destAddGrpRef.([]interface{})) > 0 { + app.DestAddressGroupReferences = expandStringList(destAddGrpRef.([]interface{})) + } + if serviceGrpRef, ok := appVal["service_group_references"]; ok && len(serviceGrpRef.([]interface{})) > 0 { + app.ServiceGroupReferences = expandStringList(serviceGrpRef.([]interface{})) + } + if allProto, ok := appVal["is_all_protocol_allowed"]; ok { + app.IsAllProtocolAllowed = utils.BoolPtr(allProto.(bool)) + } + + if tcp, ok := appVal["tcp_services"]; ok && len(tcp.([]interface{})) > 0 { + app.TcpServices = expandTCPPortRangeSpec(tcp.([]interface{})) + } + if udp, ok := appVal["udp_services"]; ok && len(udp.([]interface{})) > 0 { + app.UdpServices = expandUDPPortRangeSpec(udp.([]interface{})) + } + if icmp, ok := appVal["icmp_services"]; ok && len(icmp.([]interface{})) > 0 { + app.IcmpServices = expandIcmpTypeCodeSpec(icmp.([]interface{})) + } + if netFuncChain, ok := appVal["network_function_chain_reference"]; ok && len(netFuncChain.(string)) > 0 { + app.NetworkFunctionChainReference = utils.StringPtr(netFuncChain.(string)) + } + policyRules.SetValue(*app) + } + + if intraGroup, ok := val["intra_entity_group_rule_spec"]; ok && len(intraGroup.([]interface{})) > 0 { + intra := import1.NewIntraEntityGroupRuleSpec() + + intraI := intraGroup.([]interface{}) + intraVal := intraI[0].(map[string]interface{}) + + if secGroup, ok := intraVal["secured_group_category_references"]; ok && len(secGroup.([]interface{})) > 0 { + intra.SecuredGroupCategoryReferences = expandStringList(secGroup.([]interface{})) + } + if secGroupAction, ok := intraVal["secured_group_action"]; ok && len(secGroupAction.(string)) > 0 { + const two, three = 2, 3 + subMap := map[string]interface{}{ + "ALLOW": two, + "DENY": three, + } + pInt := subMap[secGroupAction.(string)] + p := import1.IntraEntityGroupRuleAction(pInt.(int)) + intra.SecuredGroupAction = &p + } + policyRules.SetValue(*intra) + } + return policyRules + } + return nil +} + +func expandIPv4AddressMicroseg(pr interface{}) *config.IPv4Address { + if pr != nil { + ipv4 := &config.IPv4Address{} + prI := pr.([]interface{}) + val := prI[0].(map[string]interface{}) + + if value, ok := val["value"]; ok { + ipv4.Value = utils.StringPtr(value.(string)) + } + if prefix, ok := val["prefix_length"]; ok { + ipv4.PrefixLength = utils.IntPtr(prefix.(int)) + } + return ipv4 + } + return nil +} + +func indexOf(slice []string, target string) int { + for i, v := range slice { + if v == target { + return i + } + } + return -1 +} diff --git a/nutanix/services/v2/networkingv2/resource_nutanix_network_security_policies_v2_test.go b/nutanix/services/v2/networkingv2/resource_nutanix_network_security_policies_v2_test.go new file mode 100644 index 000000000..22f18ab5b --- /dev/null +++ b/nutanix/services/v2/networkingv2/resource_nutanix_network_security_policies_v2_test.go @@ -0,0 +1,192 @@ +package networkingv2_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" +) + +const resourceNameNs = "nutanix_network_security_policy_v2.test" + +func TestAccNutanixNetworkSecurityV2_Basic(t *testing.T) { + r := acctest.RandInt() + name := fmt.Sprintf("test-nsp-%d", r) + desc := "test nsp description" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testNetworkSecurityConfig(name, desc), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceNameNs, "name", name), + resource.TestCheckResourceAttr(resourceNameNs, "description", desc), + resource.TestCheckResourceAttr(resourceNameNs, "state", "SAVE"), + resource.TestCheckResourceAttrSet(resourceNameNs, "links.#"), + resource.TestCheckResourceAttr(resourceNameNs, "type", "ISOLATION"), + resource.TestCheckResourceAttr(resourceNameNs, "rules.0.type", "TWO_ENV_ISOLATION"), + ), + }, + }, + }) +} + +func TestAccNutanixNetworkSecurityV2_WithRules(t *testing.T) { + r := acctest.RandInt() + name := fmt.Sprintf("test-nsp-%d", r) + desc := "test nsp description" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testNetworkSecurityConfigWithRules(name, desc), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceNameNs, "name", name), + resource.TestCheckResourceAttr(resourceNameNs, "description", desc), + resource.TestCheckResourceAttr(resourceNameNs, "state", "SAVE"), + resource.TestCheckResourceAttrSet(resourceNameNs, "links.#"), + resource.TestCheckResourceAttr(resourceNameNs, "type", "APPLICATION"), + resource.TestCheckResourceAttr(resourceNameNs, "rules.#", "3"), + resource.TestCheckResourceAttrSet(resourceNameNs, "vpc_reference.#"), + resource.TestCheckResourceAttr(resourceNameNs, "is_hitlog_enabled", "false"), + ), + }, + }, + }) +} + +func testNetworkSecurityConfig(name, desc string) string { + return fmt.Sprintf(` + + resource "nutanix_network_security_policy_v2" "test" { + name = "%[1]s" + description = "%[2]s" + state = "SAVE" + type = "ISOLATION" + rules{ + type = "TWO_ENV_ISOLATION" + spec{ + two_env_isolation_rule_spec{ + first_isolation_group = [ + "46f433d5-016d-5b11-a75f-5d0f44da7fd5", + ] + second_isolation_group = [ + "3da8c2d5-b2dd-5395-ab26-5f2cc87acbe1", + ] + } + } + } + is_hitlog_enabled = true + } +`, name, desc) +} + +func testNetworkSecurityConfigWithRules(name, desc string) string { + return fmt.Sprintf(` + data "nutanix_clusters" "clusters" {} + + locals { + cluster0 = data.nutanix_clusters.clusters.entities[0].metadata.uuid + } + + resource "nutanix_subnet_v2" "test" { + name = "terraform-test-subnet-vpc-%[1]s" + description = "test subnet description" + cluster_reference = local.cluster0 + subnet_type = "VLAN" + network_id = 112 + is_external = true + ip_config { + ipv4 { + ip_subnet { + ip { + value = "192.168.0.0" + } + prefix_length = 24 + } + default_gateway_ip { + value = "192.168.0.1" + } + pool_list{ + start_ip { + value = "192.168.0.20" + } + end_ip { + value = "192.168.0.30" + } + } + } + } + depends_on = [data.nutanix_clusters.clusters] + } + + resource "nutanix_vpc_v2" "test" { + name = "vpc_%[1]s" + description = "vpc %[2]s" + external_subnets{ + subnet_reference = nutanix_subnet_v2.test.id + } + depends_on = [nutanix_subnet_v2.test] + } + resource "nutanix_network_security_policy_v2" "test" { + name = "%[1]s" + description = "%[2]s" + type = "APPLICATION" + state = "SAVE" + rules{ + description = "test" + type = "APPLICATION" + spec{ + application_rule_spec{ + secured_group_category_references = [ + "c2b7fb4f-4386-5deb-b3fd-354a2f2210b0", + "c805f2d2-010f-59f6-82b2-d286c35dc8cd" + ] + src_category_references = [ + "bbc3555a-133b-5348-9764-bfff196e84e4" + ] + is_all_protocol_allowed = true + } + } + } + rules{ + description = "test22" + type = "APPLICATION" + spec{ + application_rule_spec{ + secured_group_category_references = [ + "c2b7fb4f-4386-5deb-b3fd-354a2f2210b0", + "c805f2d2-010f-59f6-82b2-d286c35dc8cd" + ] + dest_category_references = [ + "7bb4b92a-e6bd-5866-8ad4-8f3ab5886c33" + ] + is_all_protocol_allowed = true + } + } + } + rules{ + type = "INTRA_GROUP" + spec{ + intra_entity_group_rule_spec{ + secured_group_category_references = [ + "c2b7fb4f-4386-5deb-b3fd-354a2f2210b0", + "c805f2d2-010f-59f6-82b2-d286c35dc8cd" + ] + secured_group_action = "ALLOW" + } + } + } + + vpc_reference = [ + nutanix_vpc_v2.test.id + ] + is_hitlog_enabled = false + depends_on = [nutanix_vpc_v2.test] + } + `, name, desc) +} diff --git a/website/docs/d/network_security_policies_v2.html.markdown b/website/docs/d/network_security_policies_v2.html.markdown new file mode 100644 index 000000000..3d77bc711 --- /dev/null +++ b/website/docs/d/network_security_policies_v2.html.markdown @@ -0,0 +1,119 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_network_security_policies_v2" +sidebar_current: "docs-nutanix-datasource-network_security_policies_v4" +description: |- + List all the Network Security Policies +--- + +# nutanix_network_security_policies_v2 + +Gets a list of Network Security Policies. + + +### Example + +```hcl + + data "nutanix_network_security_policies_v2" "test" { } + + data "nutanix_network_security_policies_v2" "test" { + filter = "name eq '{{ NSP name }}'" + } + +``` + + +## Argument Reference + +The following arguments are supported: + +## Argument Reference + +The following arguments are supported: + +* `page`: (Optional) A URL query parameter that specifies the page number of the result set. It must be a positive integer between 0 and the maximum number of pages that are available for that resource. Any number out of this range might lead to no results. +* `limit`: (Optional) A URL query parameter that specifies the total number of records returned in the result set. Must be a positive integer between 1 and 100. Any number out of this range will lead to a validation error. If the limit is not provided, a default value of 50 records will be returned in the result set. +* `filter`: (Optional) A URL query parameter that allows clients to filter a collection of resources. +* `order_by`: (Optional) A URL query parameter that allows clients to specify the sort criteria for the returned list of objects. Resources can be sorted in ascending order using asc or descending order using desc. If asc or desc are not specified, the resources will be sorted in ascending order by default +* `select`: (Optional) A URL query parameter that allows clients to request a specific set of properties for each entity or complex type. + +* `network_policies`: List of network policies. + + +## network_policies + +The following attributes are exported: + +* `ext_id`: Network security policy UUID. +* `name`: Name of the Flow Network Security Policy. +* `type`: Defines the type of rules that can be used in a policy. +* `description`: A user defined annotation for a policy. +* `state`: Whether the policy is applied or monitored; can be omitted or set null to save the policy without applying or monitoring it. +* `rules`: A list of rules that form a policy. For isolation policies, use isolation rules; for application or quarantine policies, use application rules. +* `is_ipv6_traffic_allowed`: If Ipv6 Traffic is allowed. +* `is_hitlog_enabled`: If Hitlog is enabled. +* `scope`: Defines the scope of the policy. Currently, only ALL_VLAN and VPC_LIST are supported. If scope is not provided, the default is set based on whether vpcReferences field is provided or not. +* `vpc_reference`: A list of external ids for VPCs, used only when the scope of policy is a list of VPCs. +* `secured_groups`: Uuids of the secured groups in the NSP. +* `last_update_time`: last updated time +* `creation_time`: creation time of NSP +* `is_system_defined`: Is system defined NSP +* `created_by`: created by. +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. + +### rules +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `description`: A user defined annotation for a rule. +* `type`: The type for a rule - the value chosen here restricts which specification can be chosen. +* `spec`: Spec for rules. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. + + +### spec +* `two_env_isolation_rule_spec`: Two Environment Isolation Rule Spec. +* `application_rule_spec`: Application Rule Spec. +* `intra_entity_group_rule_spec`: Intra entity group Rule Spec + + +### two_env_isolation_rule_spec +* `first_isolation_group`: Denotes the first group of category uuids that will be used in an isolation policy. +* `second_isolation_group`: Denotes the second group of category uuids that will be used in an isolation policy. + + +### application_rule_spec +* `secured_group_category_references`: A set of network endpoints which is protected by a Network Security Policy and defined as a list of categories. +* `src_allow_spec`: A specification to how allow mode traffic should be applied, either ALL or NONE. +* `dest_allow_spec`: A specification to how allow mode traffic should be applied, either ALL or NONE. +* `src_category_references`: List of categories that define a set of network endpoints as inbound. +* `dest_category_references`: List of categories that define a set of network endpoints as outbound. +* `src_subnet`: source subnet value +* `dest_subnet`: destination subnet value +* `src_address_group_references`: A list of address group references. +* `dest_address_group_references`: A list of address group references. +* `service_group_references`: A list of service group references. +* `is_all_protocol_allowed`: Denotes if rule allows traffic for all protocol. +* `tcp_services`: tcp services +* `udp_services`: udp services +* `icmp_services`: icmp services +* `network_function_chain_reference`: A reference to the network function chain in the rule. + + +### intra_entity_group_rule_spec +* `secured_group_action`: List of secured group action. +* `secured_group_category_references`: A specification to whether traffic between intra secured group entities should be allowed or denied. + + +### tcp_services, tcp_services +* `start_port`: start port +* `end_port`: end port + + +### icmp_services +* `is_all_allowed`: Set this field to true if both Type and Code is ANY. +* `type`: Icmp service Type. Ignore this field if Type has to be ANY. +* `code`: Icmp service Code. Ignore this field if Code has to be ANY. + + +See detailed information in [Nutanix Security Policies v4](https://developers.nutanix.com/api-reference?namespace=microseg&version=v4.0.b1). \ No newline at end of file diff --git a/website/docs/d/network_security_policy_v2.html.markdown b/website/docs/d/network_security_policy_v2.html.markdown new file mode 100644 index 000000000..60d10a731 --- /dev/null +++ b/website/docs/d/network_security_policy_v2.html.markdown @@ -0,0 +1,105 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_network_security_policy_v2" +sidebar_current: "docs-nutanix-datasource-network_security_policy_v4" +description: |- + Get a Network Security Policy +--- + +# nutanix_network_security_policy_v2 + +Get a Network Security Policy by ExtID + + +### Example + +```hcl + + data "nutanix_network_security_policy_v2" "test" { + ext_id = "{{ network security policy uuid }}" + } + +``` + +## Argument Reference + +The following arguments are supported: + +* `ext_id`: (Required) Network security policy UUID. + + +## Attribute Reference + +The following attributes are exported: + +* `name`: Name of the Flow Network Security Policy. +* `type`: Defines the type of rules that can be used in a policy. +* `description`: A user defined annotation for a policy. +* `state`: Whether the policy is applied or monitored; can be omitted or set null to save the policy without applying or monitoring it. +* `rules`: A list of rules that form a policy. For isolation policies, use isolation rules; for application or quarantine policies, use application rules. +* `is_ipv6_traffic_allowed`: If Ipv6 Traffic is allowed. +* `is_hitlog_enabled`: If Hitlog is enabled. +* `scope`: Defines the scope of the policy. Currently, only ALL_VLAN and VPC_LIST are supported. If scope is not provided, the default is set based on whether vpcReferences field is provided or not. +* `vpc_reference`: A list of external ids for VPCs, used only when the scope of policy is a list of VPCs. +* `secured_groups`: Uuids of the secured groups in the NSP. +* `last_update_time`: last updated time +* `creation_time`: creation time of NSP +* `is_system_defined`: Is system defined NSP +* `created_by`: created by. +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. + +### rules +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `description`: A user defined annotation for a rule. +* `type`: The type for a rule - the value chosen here restricts which specification can be chosen. +* `spec`: Spec for rules. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. + + +### spec +* `two_env_isolation_rule_spec`: Two Environment Isolation Rule Spec. +* `application_rule_spec`: Application Rule Spec. +* `intra_entity_group_rule_spec`: Intra entity group Rule Spec + + +### two_env_isolation_rule_spec +* `first_isolation_group`: Denotes the first group of category uuids that will be used in an isolation policy. +* `second_isolation_group`: Denotes the second group of category uuids that will be used in an isolation policy. + + +### application_rule_spec +* `secured_group_category_references`: A set of network endpoints which is protected by a Network Security Policy and defined as a list of categories. +* `src_allow_spec`: A specification to how allow mode traffic should be applied, either ALL or NONE. +* `dest_allow_spec`: A specification to how allow mode traffic should be applied, either ALL or NONE. +* `src_category_references`: List of categories that define a set of network endpoints as inbound. +* `dest_category_references`: List of categories that define a set of network endpoints as outbound. +* `src_subnet`: source subnet value +* `dest_subnet`: destination subnet value +* `src_address_group_references`: A list of address group references. +* `dest_address_group_references`: A list of address group references. +* `service_group_references`: A list of service group references. +* `is_all_protocol_allowed`: Denotes if rule allows traffic for all protocol. +* `tcp_services`: tcp services +* `udp_services`: udp services +* `icmp_services`: icmp services +* `network_function_chain_reference`: A reference to the network function chain in the rule. + + +### intra_entity_group_rule_spec +* `secured_group_action`: List of secured group action. +* `secured_group_category_references`: A specification to whether traffic between intra secured group entities should be allowed or denied. + + +### tcp_services, tcp_services +* `start_port`: start port +* `end_port`: end port + + +### icmp_services +* `is_all_allowed`: Set this field to true if both Type and Code is ANY. +* `type`: Icmp service Type. Ignore this field if Type has to be ANY. +* `code`: Icmp service Code. Ignore this field if Code has to be ANY. + + +See detailed information in [Nutanix Security Policy v4](https://developers.nutanix.com/api-reference?namespace=microseg&version=v4.0.b1). \ No newline at end of file diff --git a/website/docs/r/address_group_v2.html.markdown b/website/docs/r/address_group_v2.html.markdown new file mode 100644 index 000000000..8fe0e8829 --- /dev/null +++ b/website/docs/r/address_group_v2.html.markdown @@ -0,0 +1,58 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_address_groups_v4" +sidebar_current: "docs-nutanix-resource-address-groups-v4" +description: |- + This operation submits a request to create a address group based on the input parameters. +--- + +# nutanix_address_group + +Create an Address Group + +## Example Usage + +``` hcl + resource "nutanix_address_groups_v4" "test" { + name = "{{ name }}" + description = "{{ desc }}" + ipv4_addresses{ + value = "10.0.0.0" + prefix_length = 24 + } + } +``` + + +## Argument Reference + +The following arguments are supported: + +* `name`: - (Required) Name of the Address group +* `description`: - (Optional) Description of the Address group +* `ipv4_addresses`: - (Optional) List of CIDR blocks in the Address Group. +* `ip_ranges`: - (Optional) List of IP range containing start and end IP. + + +### ipv4_addresses +* `value`: (Optional) ip of address +* `prefix_length`: (Optional) The prefix length of the network to which this host IPv4 address belongs. + + +### ip_ranges +* `start_ip`: (Required) start ip +* `end_ip`: (Required) end ip + + +## Attributes Reference + +The following attributes are exported: + +* `ext_id`: address group uuid. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity. +* `policy_references`: Reference to policy associated with Address Group. +* `created_by`: created by. + + +See detailed information in [Nutanix Address Groups V4](https://developers.nutanix.com/api-reference?namespace=microseg&version=v4.0.b1). diff --git a/website/docs/r/network_security_policy_v2.html.markdown b/website/docs/r/network_security_policy_v2.html.markdown new file mode 100644 index 000000000..7a60e6f84 --- /dev/null +++ b/website/docs/r/network_security_policy_v2.html.markdown @@ -0,0 +1,122 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_network_security_policy_v2" +sidebar_current: "docs-nutanix-resource-network-security-policy-v4" +description: |- + Create a Network Security Policy +--- + +# nutanix_network_security_policy_v2 + +Create a Network Security Policy + +## Example + +```hcl + resource "nutanix_network_security_policy_v2" "test" { + name = "{{ name }}" + description = "{{ desc }}" + state = "SAVE" + type = "ISOLATION" + rules{ + type = "TWO_ENV_ISOLATION" + spec{ + two_env_isolation_rule_spec{ + first_isolation_group = [ + "{{ uuids}}", + ] + second_isolation_group = [ + "{{ uuids }}", + ] + } + } + } + is_hitlog_enabled = true + } + +``` + + +## Argument Reference + +The following arguments are supported: + +* `name`: (Required) Name of the Flow Network Security Policy. +* `type`: (Required) Defines the type of rules that can be used in a policy. Acceptables values are "QUARANTINE", "ISOLATION", "APPLICATION". +* `description`: (Optional) A user defined annotation for a policy. +* `state`: (Optional) Whether the policy is applied or monitored; can be omitted or set null to save the policy without applying or monitoring it. Acceptables values are "SAVE", "MONITOR", "ENFORCE". +* `rules`: (Optional) A list of rules that form a policy. For isolation policies, use isolation rules; for application or quarantine policies, use application rules. +* `is_ipv6_traffic_allowed`: (Optional) If Ipv6 Traffic is allowed. +* `is_hitlog_enabled`: (Optional) If Hitlog is enabled. +* `scope`: Defines the scope of the policy. Currently, only ALL_VLAN and VPC_LIST are supported. If scope is not provided, the default is set based on whether vpcReferences field is provided or not. +* `vpc_reference`: (Optional) A list of external ids for VPCs, used only when the scope of policy is a list of VPCs. + + +### rules +* `description`: (Optional) A user defined annotation for a rule. +* `type`: (Required) The type for a rule - the value chosen here restricts which specification can be chosen. Acceptables values are "QUARANTINE", "TWO_ENV_ISOLATION", "APPLICATION", "INTRA_GROUP". +* `spec`: (Required) Spec for rules. + + +### spec +One of below rules spec. +* `two_env_isolation_rule_spec`: (Optional) Two Environment Isolation Rule Spec. +* `application_rule_spec`: (Optional) Application Rule Spec. +* `intra_entity_group_rule_spec`: (Optional) Intra entity group Rule Spec + + +### two_env_isolation_rule_spec +* `first_isolation_group`: (Required) Denotes the first group of category uuids that will be used in an isolation policy. +* `second_isolation_group`: (Required) Denotes the second group of category uuids that will be used in an isolation policy. + + +### application_rule_spec +* `secured_group_category_references`: (Required) A set of network endpoints which is protected by a Network Security Policy and defined as a list of categories. +* `src_allow_spec`: (Optional) A specification to how allow mode traffic should be applied, either ALL or NONE. +* `dest_allow_spec`: (Optional) A specification to how allow mode traffic should be applied, either ALL or NONE. +* `src_category_references`: (Optional) List of categories that define a set of network endpoints as inbound. +* `dest_category_references`: (Optional) List of categories that define a set of network endpoints as outbound. +* `src_subnet`: (Optional) source subnet value +* `dest_subnet`: (Optional) destination subnet value +* `src_address_group_references`: (Optional) A list of address group references. +* `dest_address_group_references`: (Optional) A list of address group references. +* `service_group_references`: (Optional) A list of service group references. +* `is_all_protocol_allowed`: (Optional) Denotes if rule allows traffic for all protocol. +* `tcp_services`: (Optional) tcp services +* `udp_services`: (Optional) udp services +* `icmp_services`: (Optional) icmp services +* `network_function_chain_reference`: (Optional) A reference to the network function chain in the rule. + + +### intra_entity_group_rule_spec +* `secured_group_action`: (Required) List of secured group action. +* `secured_group_category_references`: (Required) A specification to whether traffic between intra secured group entities should be allowed or denied. + + +### tcp_services, tcp_services +* `start_port`: (Required) start port +* `end_port`: (Required) end port + + +### icmp_services +* `is_all_allowed`: (Optional) Set this field to true if both Type and Code is ANY. +* `type`: (Optional) Icmp service Type. Ignore this field if Type has to be ANY. +* `code`: (Optional) Icmp service Code. Ignore this field if Code has to be ANY. + + +## Attributes Reference + +The following attributes are exported: + +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `secured_groups`: Uuids of the secured groups in the NSP. +* `is_system_defined`: Is system defined NSP +* `created_by`: created by. +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity +* `last_update_time`: last updated time +* `creation_time`: creation time of NSP + + + +See detailed information in [Nutanix Security Policy v4](https://developers.nutanix.com/api-reference?namespace=microseg&version=v4.0.b1). \ No newline at end of file diff --git a/website/docs/r/pbrs_v2.html.markdown b/website/docs/r/pbrs_v2.html.markdown index 0b29c366a..b18d85b8a 100644 --- a/website/docs/r/pbrs_v2.html.markdown +++ b/website/docs/r/pbrs_v2.html.markdown @@ -1,7 +1,7 @@ --- layout: "nutanix" page_title: "NUTANIX: nutanix_pbr_v2" -sidebar_current: "docs-nutanix-resource-pbr-v4" +sidebar_current: "docs-nutanix-resource-pbr-v2" description: |- Create Routing Policy within VPCs . --- diff --git a/website/docs/r/service_groups_v2.html.markdown b/website/docs/r/service_groups_v2.html.markdown new file mode 100644 index 000000000..e9f8ecb8a --- /dev/null +++ b/website/docs/r/service_groups_v2.html.markdown @@ -0,0 +1,64 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_service_groups_v4" +sidebar_current: "docs-nutanix-resource-service-groups-v4" +description: |- + This operation submits a request to create a service group based on the input parameters. +--- + +# nutanix_service_group + +Create an service Group + +## Example Usage + +``` hcl + resource "nutanix_service_groups_v4" "test" { + name = "{{ name }}" + description = "{{ desc }}" + tcp_services { + start_port = "232" + end_port = "232" + } + udp_services { + start_port = "232" + end_port = "232" + } + } +``` + + +## Argument Reference + +The following arguments are supported: + +* `name`: (Required) Name of the service group +* `description`: (Optional) Description of the service group +* `tcp_services`: (Optional) List of TCP ports in the service. +* `udp_services`: (Optional) List of UDP ports in the service. +* `icmp_services`: (Optional) Icmp Type Code List. + + +### tcp_services, udp_services +* `start_port`: (Required) start port +* `end_port`: (Required) end port + +### icmp_services +* `type`: (Optional) Icmp service Type. Ignore this field if Type has to be ANY. +* `code`: (Optional) Icmp service Code. Ignore this field if Code has to be ANY +* `is_all_allowed`: (Optional) Set this field to true if both Type and Code is ANY. Default is False. + + +## Attributes Reference + +The following attributes are exported: + +* `ext_id`: address group uuid. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity. +* `policy_references`: Reference to policy associated with Address Group. +* `created_by`: created by. +* `is_system_defined`: Service Group is system defined or not. + + +See detailed information in [Nutanix Address Groups V4](https://developers.nutanix.com/api-reference?namespace=microseg&version=v4.0.b1).