From 77752a331284e044949ad07de48fb34045e9811f Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 24 Jun 2021 14:40:19 +0800 Subject: [PATCH 01/12] New Resource: azurerm_signalr_service_network_acl --- .../internal/services/signalr/registration.go | 3 +- .../signalr_service_network_acl_resource.go | 441 ++++++++++++++++++ ...gnalr_service_network_acl_resource_test.go | 208 +++++++++ .../signalr_service_network_acl.html.markdown | 149 ++++++ 4 files changed, 800 insertions(+), 1 deletion(-) create mode 100644 azurerm/internal/services/signalr/signalr_service_network_acl_resource.go create mode 100644 azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go create mode 100644 website/docs/r/signalr_service_network_acl.html.markdown diff --git a/azurerm/internal/services/signalr/registration.go b/azurerm/internal/services/signalr/registration.go index 721218b003ad..abba5c6df855 100644 --- a/azurerm/internal/services/signalr/registration.go +++ b/azurerm/internal/services/signalr/registration.go @@ -28,6 +28,7 @@ func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { return map[string]*pluginsdk.Resource{ - "azurerm_signalr_service": resourceArmSignalRService(), + "azurerm_signalr_service": resourceArmSignalRService(), + "azurerm_signalr_service_network_acl": resourceArmSignalRServiceNetworkACL(), } } diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go new file mode 100644 index 000000000000..48c67a1f8041 --- /dev/null +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -0,0 +1,441 @@ +package signalr + +import ( + "fmt" + "time" + + "github.com/Azure/azure-sdk-for-go/services/signalr/mgmt/2020-05-01/signalr" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" + networkValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/signalr/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/signalr/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceSignalRServiceNetworkACLCreateUpdate, + Read: resourceSignalRServiceNetworkACLRead, + Update: resourceSignalRServiceNetworkACLCreateUpdate, + Delete: resourceSignalRServiceNetworkACLDelete, + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(30 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(30 * time.Minute), + Delete: pluginsdk.DefaultTimeout(30 * time.Minute), + }, + + Importer: pluginsdk.DefaultImporter(), + + Schema: map[string]*pluginsdk.Schema{ + "signalr_service_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ServiceID, + }, + + "network_acl": { + Type: pluginsdk.TypeList, + Required: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "default_action": { + Type: pluginsdk.TypeString, + Optional: true, + Default: string(signalr.Deny), + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.Allow), + string(signalr.Deny), + }, false), + }, + + "private_endpoint": { + Type: pluginsdk.TypeSet, + Optional: true, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: networkValidate.PrivateLinkName, + }, + + // API response includes the `Trace` type but it isn't in rest api client. + // https://github.com/Azure/azure-rest-api-specs/issues/14923 + "allowed_request_types": { + Type: pluginsdk.TypeSet, + Optional: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.ClientConnection), + string(signalr.RESTAPI), + string(signalr.ServerConnection), + "Trace", + }, false), + }, + }, + + "denied_request_types": { + Type: pluginsdk.TypeSet, + Optional: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.ClientConnection), + string(signalr.RESTAPI), + string(signalr.ServerConnection), + "Trace", + }, false), + }, + }, + }, + }, + }, + + "public_network": { + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + // API response includes the `Trace` type but it isn't in rest api client. + // https://github.com/Azure/azure-rest-api-specs/issues/14923 + "allowed_request_types": { + Type: pluginsdk.TypeSet, + Optional: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.ClientConnection), + string(signalr.RESTAPI), + string(signalr.ServerConnection), + "Trace", + }, false), + }, + }, + + "denied_request_types": { + Type: pluginsdk.TypeSet, + Optional: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.ClientConnection), + string(signalr.RESTAPI), + string(signalr.ServerConnection), + "Trace", + }, false), + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func resourceSignalRServiceNetworkACLCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).SignalR.Client + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.ServiceID(d.Get("signalr_service_id").(string)) + if err != nil { + return err + } + + locks.ByName(id.SignalRName, "azurerm_signalr_service") + defer locks.UnlockByName(id.SignalRName, "azurerm_signalr_service") + + resp, err := client.Get(ctx, id.ResourceGroup, id.SignalRName) + if err != nil { + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + parameters := resp + + networkAcl := d.Get("network_acl").([]interface{}) + parameters.Properties.NetworkACLs = expandSignalRServiceNetworkACL(networkAcl) + + if networkACL := parameters.Properties.NetworkACLs; networkACL != nil { + if publicNetwork := networkACL.PublicNetwork; publicNetwork != nil { + if publicNetwork.Allow != nil && publicNetwork.Deny != nil { + return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `public_network`") + } + + if networkACL.DefaultAction == signalr.Allow && publicNetwork.Allow != nil { + return fmt.Errorf("when `default_action` is `Allow` for `public_network`, `allowed_request_types` cannot be specified") + } else if networkACL.DefaultAction == signalr.Deny && publicNetwork.Deny != nil { + return fmt.Errorf("when `default_action` is `Deny` for `public_network`, `denied_request_types` cannot be specified") + } + } + + for _, v := range *networkACL.PrivateEndpoints { + if v.Allow != nil && v.Deny != nil { + return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `private_endpoint`") + } + + if networkACL.DefaultAction == signalr.Allow && v.Allow != nil { + return fmt.Errorf("when `default_action` is `Allow` for `private_endpoint`, `allowed_request_types` cannot be specified") + } else if networkACL.DefaultAction == signalr.Deny && v.Deny != nil { + return fmt.Errorf("when `default_action` is `Deny` for `private_endpoint`, `denied_request_types` cannot be specified") + } + } + } + + future, err := client.Update(ctx, id.ResourceGroup, id.SignalRName, ¶meters) + if err != nil { + return fmt.Errorf("creating/updating NetworkACL for %s: %v", id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for completion of creating/updating NetworkACL for %s: %v", id, err) + } + + d.SetId(id.ID()) + + return resourceSignalRServiceNetworkACLRead(d, meta) +} + +func resourceSignalRServiceNetworkACLRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).SignalR.Client + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.ServiceID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.SignalRName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + d.Set("signalr_service_id", id.ID()) + + if properties := resp.Properties; properties != nil { + if err := d.Set("network_acl", flattenSignalRServiceNetworkACL(properties.NetworkACLs)); err != nil { + return fmt.Errorf("setting `network_acl`: %+v", err) + } + } + + return nil +} + +func resourceSignalRServiceNetworkACLDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).SignalR.Client + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.ServiceID(d.Id()) + if err != nil { + return err + } + + locks.ByName(id.SignalRName, "azurerm_signalr_service") + defer locks.UnlockByName(id.SignalRName, "azurerm_signalr_service") + + resp, err := client.Get(ctx, id.ResourceGroup, id.SignalRName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + // Since this isn't a real object, just modifying an existing object + // "Delete" doesn't really make sense it should really be a "Revert to Default" + // So instead of the Delete func actually deleting the SignalR Service I am + // making it reset the NetworkACL of the SignalR Service to its default state + parameters := resp + parameters.Properties.NetworkACLs = nil + + future, err := client.Update(ctx, id.ResourceGroup, id.SignalRName, ¶meters) + if err != nil { + return fmt.Errorf("removing NetworkACL from %s: %v", id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for completion of removing NetworkACL from %s: %v", id, err) + } + + return nil +} + +func expandSignalRServiceNetworkACL(input []interface{}) *signalr.NetworkACLs { + if len(input) == 0 { + return nil + } + + v := input[0].(map[string]interface{}) + + return &signalr.NetworkACLs{ + DefaultAction: signalr.ACLAction(v["default_action"].(string)), + PublicNetwork: expandSignalRServicePublicNetwork(v["public_network"].([]interface{})), + PrivateEndpoints: expandSignalRServicePrivateEndpoint(v["private_endpoint"].(*pluginsdk.Set).List()), + } +} + +func expandSignalRServicePublicNetwork(input []interface{}) *signalr.NetworkACL { + if len(input) == 0 { + return nil + } + + v := input[0].(map[string]interface{}) + + result := signalr.NetworkACL{} + + if allowedRequestTypes := v["allowed_request_types"].(*pluginsdk.Set).List(); len(allowedRequestTypes) != 0 { + allowedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(allowedRequestTypes)) { + allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) + } + result.Allow = &allowedRTs + } + + if deniedRequestTypes := v["denied_request_types"].(*pluginsdk.Set).List(); len(deniedRequestTypes) != 0 { + deniedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(deniedRequestTypes)) { + deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) + } + result.Deny = &deniedRTs + } + + return &result +} + +func expandSignalRServicePrivateEndpoint(input []interface{}) *[]signalr.PrivateEndpointACL { + results := make([]signalr.PrivateEndpointACL, 0) + + for _, item := range input { + v := item.(map[string]interface{}) + + result := signalr.PrivateEndpointACL{ + Name: utils.String(v["name"].(string)), + } + + if allowedRequestTypes := v["allowed_request_types"].(*pluginsdk.Set).List(); len(allowedRequestTypes) != 0 { + allowRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(allowedRequestTypes)) { + allowRTs = append(allowRTs, (signalr.RequestType)(item)) + } + result.Allow = &allowRTs + } + + if deniedRequestTypes := v["denied_request_types"].(*pluginsdk.Set).List(); len(deniedRequestTypes) != 0 { + deniedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(deniedRequestTypes)) { + deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) + } + result.Deny = &deniedRTs + } + + results = append(results, result) + } + + return &results +} + +func flattenSignalRServiceNetworkACL(input *signalr.NetworkACLs) []interface{} { + if input == nil { + return make([]interface{}, 0) + } + + var defaultAction signalr.ACLAction + if input.DefaultAction != "" { + defaultAction = input.DefaultAction + } + + return []interface{}{ + map[string]interface{}{ + "default_action": defaultAction, + "public_network": flattenSignalRServicePublicNetwork(input.PublicNetwork), + "private_endpoint": flattenSignalRServicePrivateEndpoint(input.PrivateEndpoints), + }, + } +} + +func flattenSignalRServicePublicNetwork(input *signalr.NetworkACL) []interface{} { + if input == nil { + return make([]interface{}, 0) + } + + allowRequestTypes := make([]string, 0) + if input.Allow != nil { + for _, item := range *input.Allow { + allowRequestTypes = append(allowRequestTypes, (string)(item)) + } + } + allow := utils.FlattenStringSlice(&allowRequestTypes) + + deniedRequestTypes := make([]string, 0) + if input.Deny != nil { + for _, item := range *input.Deny { + deniedRequestTypes = append(deniedRequestTypes, (string)(item)) + } + } + deny := utils.FlattenStringSlice(&deniedRequestTypes) + + return []interface{}{ + map[string]interface{}{ + "allowed_request_types": allow, + "denied_request_types": deny, + }, + } +} + +func flattenSignalRServicePrivateEndpoint(input *[]signalr.PrivateEndpointACL) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range *input { + var name string + if item.Name != nil { + name = *item.Name + } + + allowedRequestTypes := make([]string, 0) + if item.Allow != nil { + for _, item := range *item.Allow { + allowedRequestTypes = append(allowedRequestTypes, (string)(item)) + } + } + allow := utils.FlattenStringSlice(&allowedRequestTypes) + + deniedRequestTypes := make([]string, 0) + if item.Deny != nil { + for _, item := range *item.Deny { + deniedRequestTypes = append(deniedRequestTypes, (string)(item)) + } + } + deny := utils.FlattenStringSlice(&deniedRequestTypes) + + results = append(results, map[string]interface{}{ + "name": name, + "allowed_request_types": allow, + "denied_request_types": deny, + }) + } + + return results +} diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go new file mode 100644 index 000000000000..a36ff5b88614 --- /dev/null +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go @@ -0,0 +1,208 @@ +package signalr_test + +import ( + "context" + "fmt" + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/signalr/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +type SignalRServiceNetworkACLResource struct{} + +func TestAccSignalRServiceNetworkACL_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_signalr_service_network_acl", "test") + r := SignalRServiceNetworkACLResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccSignalRServiceNetworkACL_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_signalr_service_network_acl", "test") + r := SignalRServiceNetworkACLResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccSignalRServiceNetworkACL_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_signalr_service_network_acl", "test") + r := SignalRServiceNetworkACLResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccSignalRServiceNetworkACL_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_signalr_service_network_acl", "test") + r := SignalRServiceNetworkACLResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (r SignalRServiceNetworkACLResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := parse.ServiceID(state.ID) + if err != nil { + return nil, err + } + + resp, err := client.SignalR.Client.Get(ctx, id.ResourceGroup, id.SignalRName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return utils.Bool(false), nil + } + return nil, fmt.Errorf("retrieving %q %+v", id, err) + } + + return utils.Bool(resp.Properties != nil && resp.Properties.NetworkACLs != nil), nil +} + +func (r SignalRServiceNetworkACLResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_signalr_service_network_acl" "test" { + signalr_service_id = azurerm_signalr_service.test.id + + network_acl { + default_action = "Deny" + + public_network { + allowed_request_types = ["ClientConnection"] + } + } +} +`, r.template(data)) +} + +func (r SignalRServiceNetworkACLResource) requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_signalr_service_network_acl" "import" { + signalr_service_id = azurerm_signalr_service_network_acl.test.signalr_service_id + network_acl = azurerm_signalr_service_network_acl.test.network_acl +} +`, r.basic(data)) +} + +func (r SignalRServiceNetworkACLResource) complete(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_network" "test" { + name = "acctest-vnet-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + address_space = ["10.5.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "acctest-subnet-%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.5.2.0/24"] + + enforce_private_link_endpoint_network_policies = true +} + +resource "azurerm_private_endpoint" "test" { + name = "acctest-pe-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + subnet_id = azurerm_subnet.test.id + + private_service_connection { + name = "psc-sig-test" + is_manual_connection = false + private_connection_resource_id = azurerm_signalr_service.test.id + subresource_names = ["signalr"] + } +} + +resource "azurerm_signalr_service_network_acl" "test" { + signalr_service_id = azurerm_signalr_service.test.id + + network_acl { + default_action = "Allow" + + public_network { + denied_request_types = ["ClientConnection"] + } + } +} +`, r.template(data), data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func (r SignalRServiceNetworkACLResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-signalr-%d" + location = "%s" +} + +resource "azurerm_signalr_service" "test" { + name = "acctest-signalr-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + sku { + name = "Standard_S1" + capacity = 1 + } +} + `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} diff --git a/website/docs/r/signalr_service_network_acl.html.markdown b/website/docs/r/signalr_service_network_acl.html.markdown new file mode 100644 index 000000000000..03acf4c66e61 --- /dev/null +++ b/website/docs/r/signalr_service_network_acl.html.markdown @@ -0,0 +1,149 @@ +--- +subcategory: "Messaging" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_signalr_service_network_acl" +description: |- + Manages the Network ACL for a SignalR service. +--- + +# azurerm_signalr_service_network_acl + +Manages the Network ACL for a SignalR service. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_signalr_service" "example" { + name = "example-signalr" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + sku { + name = "Standard_S1" + capacity = 1 + } +} + +resource "azurerm_virtual_network" "example" { + name = "example-vnet" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + address_space = ["10.5.0.0/16"] +} + +resource "azurerm_subnet" "example" { + name = "example-subnet" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name + address_prefixes = ["10.5.2.0/24"] + + enforce_private_link_endpoint_network_policies = true +} + +resource "azurerm_private_endpoint" "example" { + name = "example-privateendpoint" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + subnet_id = azurerm_subnet.example.id + + private_service_connection { + name = "psc-sig-test" + is_manual_connection = false + private_connection_resource_id = azurerm_signalr_service.example.id + subresource_names = ["signalr"] + } +} + +resource "azurerm_signalr_service_network_acl" "example" { + signalr_service_id = azurerm_signalr_service.example.id + + network_acl { + default_action = "Deny" + + public_network { + allowed_request_types = ["ClientConnection"] + } + + private_endpoint { + name = azurerm_private_endpoint.example.name + allowed_request_types = ["ServerConnection"] + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `signalr_service_id` - (Required) The ID of the SignalR service. Changing this forces a new resource to be created. + +* `network_acl` - (Required) A `network_acl` block as documented below. + +--- + +A `network_acl` block supports the following: + +* `default_action` - (Optional) The default action when no other rule matches. Possible values are `Allow` and `Deny`. Defaults to `Deny`. + +* `public_network` - (Optional) A `public_network` block as defined below. + +* `private_endpoint` - (Optional) A `private_endpoint` block as defined below. + +--- + +A `public_network` block supports the following: + +**Note:** `allowed_request_types` and `denied_request_types` cannot be set together. + +* `allowed_request_types` - (Optional) The allowed request types. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. + +**Note:** When `default_action` is `Allow`, `allowed_request_types`cannot be set. + +* `denied_request_types` - (Optional) The denied request types. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. + +**Note:** When `default_action` is `Deny`, `denied_request_types`cannot be set. + +--- + +A `private_endpoint` block supports the following: + +* `name` - (Required) The name of the Private Endpoint which is based on the SignalR service. + +**Note:** `allowed_request_types` and `denied_request_types` cannot be set together. + +* `allowed_request_types` - (Optional) The allowed request types. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. + +**Note:** When `default_action` is `Allow`, `allowed_request_types`cannot be set. + +* `denied_request_types` - (Optional) The denied request types. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. + +**Note:** When `default_action` is `Deny`, `denied_request_types`cannot be set. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the SignalR service. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Network ACL of the SignalR service +* `read` - (Defaults to 5 minutes) Used when retrieving the Network ACL of the SignalR service +* `update` - (Defaults to 30 minutes) Used when updating the Network ACL of the SignalR service +* `delete` - (Defaults to 30 minutes) Used when deleting the Network ACL of the SignalR service + +## Import + +Network ACLs for a SignalR service can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_signalr_service_network_acl.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.SignalRService/SignalR/signalr1 +``` From 738bd89fd433079f3b8dc60394f0ba8371425c40 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 25 Jun 2021 09:16:44 +0800 Subject: [PATCH 02/12] update code --- .../signalr_service_network_acl_resource.go | 179 ++++++++++-------- ...gnalr_service_network_acl_resource_test.go | 23 +-- .../signalr_service_network_acl.html.markdown | 4 +- 3 files changed, 115 insertions(+), 91 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go index 48c67a1f8041..abfae9e0b8c1 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -62,10 +62,10 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { Computed: true, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "name": { + "id": { Type: pluginsdk.TypeString, Required: true, - ValidateFunc: networkValidate.PrivateLinkName, + ValidateFunc: networkValidate.PrivateEndpointID, }, // API response includes the `Trace` type but it isn't in rest api client. @@ -111,8 +111,9 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { // API response includes the `Trace` type but it isn't in rest api client. // https://github.com/Azure/azure-rest-api-specs/issues/14923 "allowed_request_types": { - Type: pluginsdk.TypeSet, - Optional: true, + Type: pluginsdk.TypeSet, + Optional: true, + ConflictsWith: []string{"network_acl.0.public_network.0.denied_request_types"}, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, ValidateFunc: validation.StringInSlice([]string{ @@ -125,8 +126,9 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { }, "denied_request_types": { - Type: pluginsdk.TypeSet, - Optional: true, + Type: pluginsdk.TypeSet, + Optional: true, + ConflictsWith: []string{"network_acl.0.public_network.0.allowed_request_types"}, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, ValidateFunc: validation.StringInSlice([]string{ @@ -167,31 +169,28 @@ func resourceSignalRServiceNetworkACLCreateUpdate(d *pluginsdk.ResourceData, met parameters := resp - networkAcl := d.Get("network_acl").([]interface{}) - parameters.Properties.NetworkACLs = expandSignalRServiceNetworkACL(networkAcl) + if props := resp.Properties; props != nil { + parameters.Properties.NetworkACLs = expandSignalRServiceNetworkACL(d.Get("network_acl").([]interface{}), props.PrivateEndpointConnections) - if networkACL := parameters.Properties.NetworkACLs; networkACL != nil { - if publicNetwork := networkACL.PublicNetwork; publicNetwork != nil { - if publicNetwork.Allow != nil && publicNetwork.Deny != nil { - return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `public_network`") + if networkACL := parameters.Properties.NetworkACLs; networkACL != nil { + if publicNetwork := networkACL.PublicNetwork; publicNetwork != nil { + if networkACL.DefaultAction == signalr.Allow && len(*publicNetwork.Allow) != 0 { + return fmt.Errorf("when `default_action` is `Allow` for `public_network`, `allowed_request_types` cannot be specified") + } else if networkACL.DefaultAction == signalr.Deny && len(*publicNetwork.Deny) != 0 { + return fmt.Errorf("when `default_action` is `Deny` for `public_network`, `denied_request_types` cannot be specified") + } } - if networkACL.DefaultAction == signalr.Allow && publicNetwork.Allow != nil { - return fmt.Errorf("when `default_action` is `Allow` for `public_network`, `allowed_request_types` cannot be specified") - } else if networkACL.DefaultAction == signalr.Deny && publicNetwork.Deny != nil { - return fmt.Errorf("when `default_action` is `Deny` for `public_network`, `denied_request_types` cannot be specified") - } - } - - for _, v := range *networkACL.PrivateEndpoints { - if v.Allow != nil && v.Deny != nil { - return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `private_endpoint`") - } + for _, v := range *networkACL.PrivateEndpoints { + if len(*v.Allow) != 0 && len(*v.Deny) != 0 { + return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `private_endpoint`") + } - if networkACL.DefaultAction == signalr.Allow && v.Allow != nil { - return fmt.Errorf("when `default_action` is `Allow` for `private_endpoint`, `allowed_request_types` cannot be specified") - } else if networkACL.DefaultAction == signalr.Deny && v.Deny != nil { - return fmt.Errorf("when `default_action` is `Deny` for `private_endpoint`, `denied_request_types` cannot be specified") + if networkACL.DefaultAction == signalr.Allow && len(*v.Allow) != 0 { + return fmt.Errorf("when `default_action` is `Allow` for `private_endpoint`, `allowed_request_types` cannot be specified") + } else if networkACL.DefaultAction == signalr.Deny && len(*v.Deny) != 0 { + return fmt.Errorf("when `default_action` is `Deny` for `private_endpoint`, `denied_request_types` cannot be specified") + } } } } @@ -231,8 +230,8 @@ func resourceSignalRServiceNetworkACLRead(d *pluginsdk.ResourceData, meta interf d.Set("signalr_service_id", id.ID()) - if properties := resp.Properties; properties != nil { - if err := d.Set("network_acl", flattenSignalRServiceNetworkACL(properties.NetworkACLs)); err != nil { + if props := resp.Properties; props != nil { + if err := d.Set("network_acl", flattenSignalRServiceNetworkACL(props.NetworkACLs, props.PrivateEndpointConnections)); err != nil { return fmt.Errorf("setting `network_acl`: %+v", err) } } @@ -261,26 +260,49 @@ func resourceSignalRServiceNetworkACLDelete(d *pluginsdk.ResourceData, meta inte return fmt.Errorf("retrieving %s: %+v", *id, err) } - // Since this isn't a real object, just modifying an existing object - // "Delete" doesn't really make sense it should really be a "Revert to Default" - // So instead of the Delete func actually deleting the SignalR Service I am - // making it reset the NetworkACL of the SignalR Service to its default state + // As this isn't a real object, so it has to update NetworkACL to default settings for the delete operation parameters := resp - parameters.Properties.NetworkACLs = nil + + requestTypes := signalr.PossibleRequestTypeValues() + requestTypes = append(requestTypes, "Trace") + + networkACL := &signalr.NetworkACLs{ + DefaultAction: signalr.Deny, + PublicNetwork: &signalr.NetworkACL{ + Allow: &requestTypes, + }, + } + + if resp.Properties != nil && resp.Properties.NetworkACLs != nil && resp.Properties.NetworkACLs.PrivateEndpoints != nil { + privateEndpoints := make([]signalr.PrivateEndpointACL, 0) + for _, item := range *resp.Properties.NetworkACLs.PrivateEndpoints { + if item.Name != nil { + privateEndpoints = append(privateEndpoints, signalr.PrivateEndpointACL{ + Allow: &requestTypes, + Name: item.Name, + }) + } + } + networkACL.PrivateEndpoints = &privateEndpoints + } + + if parameters.Properties != nil { + parameters.Properties.NetworkACLs = networkACL + } future, err := client.Update(ctx, id.ResourceGroup, id.SignalRName, ¶meters) if err != nil { - return fmt.Errorf("removing NetworkACL from %s: %v", id, err) + return fmt.Errorf("reverting NetworkACL to default settings for %s: %v", id, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for completion of removing NetworkACL from %s: %v", id, err) + return fmt.Errorf("waiting for completion of reverting NetworkACL to default settings for %s: %v", id, err) } return nil } -func expandSignalRServiceNetworkACL(input []interface{}) *signalr.NetworkACLs { +func expandSignalRServiceNetworkACL(input []interface{}, privateEndpointConnections *[]signalr.PrivateEndpointConnection) *signalr.NetworkACLs { if len(input) == 0 { return nil } @@ -290,7 +312,7 @@ func expandSignalRServiceNetworkACL(input []interface{}) *signalr.NetworkACLs { return &signalr.NetworkACLs{ DefaultAction: signalr.ACLAction(v["default_action"].(string)), PublicNetwork: expandSignalRServicePublicNetwork(v["public_network"].([]interface{})), - PrivateEndpoints: expandSignalRServicePrivateEndpoint(v["private_endpoint"].(*pluginsdk.Set).List()), + PrivateEndpoints: expandSignalRServicePrivateEndpoint(v["private_endpoint"].(*pluginsdk.Set).List(), privateEndpointConnections), } } @@ -301,60 +323,60 @@ func expandSignalRServicePublicNetwork(input []interface{}) *signalr.NetworkACL v := input[0].(map[string]interface{}) - result := signalr.NetworkACL{} - - if allowedRequestTypes := v["allowed_request_types"].(*pluginsdk.Set).List(); len(allowedRequestTypes) != 0 { - allowedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(allowedRequestTypes)) { - allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) - } - result.Allow = &allowedRTs + allowedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { + allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) } - if deniedRequestTypes := v["denied_request_types"].(*pluginsdk.Set).List(); len(deniedRequestTypes) != 0 { - deniedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(deniedRequestTypes)) { - deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) - } - result.Deny = &deniedRTs + deniedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(v["denied_request_types"].(*pluginsdk.Set).List())) { + deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) } - return &result + return &signalr.NetworkACL{ + Allow: &allowedRTs, + Deny: &deniedRTs, + } } -func expandSignalRServicePrivateEndpoint(input []interface{}) *[]signalr.PrivateEndpointACL { +func expandSignalRServicePrivateEndpoint(input []interface{}, privateEndpointConnections *[]signalr.PrivateEndpointConnection) *[]signalr.PrivateEndpointACL { results := make([]signalr.PrivateEndpointACL, 0) for _, item := range input { v := item.(map[string]interface{}) - result := signalr.PrivateEndpointACL{ - Name: utils.String(v["name"].(string)), + privateEndpointId := v["id"].(string) + privateEndpointConnectionName := "" + if privateEndpointConnections != nil { + for _, privateEndpointConnection := range *privateEndpointConnections { + if privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil && privateEndpointId == *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID && privateEndpointConnection.Name != nil { + privateEndpointConnectionName = *privateEndpointConnection.Name + break + } + } } - if allowedRequestTypes := v["allowed_request_types"].(*pluginsdk.Set).List(); len(allowedRequestTypes) != 0 { - allowRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(allowedRequestTypes)) { - allowRTs = append(allowRTs, (signalr.RequestType)(item)) - } - result.Allow = &allowRTs + allowedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { + allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) } - if deniedRequestTypes := v["denied_request_types"].(*pluginsdk.Set).List(); len(deniedRequestTypes) != 0 { - deniedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(deniedRequestTypes)) { - deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) - } - result.Deny = &deniedRTs + deniedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(v["denied_request_types"].(*pluginsdk.Set).List())) { + deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) } - results = append(results, result) + results = append(results, signalr.PrivateEndpointACL{ + Allow: &allowedRTs, + Deny: &deniedRTs, + Name: utils.String(privateEndpointConnectionName), + }) } return &results } -func flattenSignalRServiceNetworkACL(input *signalr.NetworkACLs) []interface{} { +func flattenSignalRServiceNetworkACL(input *signalr.NetworkACLs, privateEndpointConnections *[]signalr.PrivateEndpointConnection) []interface{} { if input == nil { return make([]interface{}, 0) } @@ -368,7 +390,7 @@ func flattenSignalRServiceNetworkACL(input *signalr.NetworkACLs) []interface{} { map[string]interface{}{ "default_action": defaultAction, "public_network": flattenSignalRServicePublicNetwork(input.PublicNetwork), - "private_endpoint": flattenSignalRServicePrivateEndpoint(input.PrivateEndpoints), + "private_endpoint": flattenSignalRServicePrivateEndpoint(input.PrivateEndpoints, privateEndpointConnections), }, } } @@ -402,16 +424,21 @@ func flattenSignalRServicePublicNetwork(input *signalr.NetworkACL) []interface{} } } -func flattenSignalRServicePrivateEndpoint(input *[]signalr.PrivateEndpointACL) []interface{} { +func flattenSignalRServicePrivateEndpoint(input *[]signalr.PrivateEndpointACL, privateEndpointConnections *[]signalr.PrivateEndpointConnection) []interface{} { results := make([]interface{}, 0) if input == nil { return results } for _, item := range *input { - var name string - if item.Name != nil { - name = *item.Name + var privateEndpointId string + if privateEndpointConnections != nil { + for _, privateEndpointConnection := range *privateEndpointConnections { + if item.Name != nil && privateEndpointConnection.Name != nil && *item.Name == *privateEndpointConnection.Name && privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil { + privateEndpointId = *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID + break + } + } } allowedRequestTypes := make([]string, 0) @@ -431,7 +458,7 @@ func flattenSignalRServicePrivateEndpoint(input *[]signalr.PrivateEndpointACL) [ deny := utils.FlattenStringSlice(&deniedRequestTypes) results = append(results, map[string]interface{}{ - "name": name, + "id": privateEndpointId, "allowed_request_types": allow, "denied_request_types": deny, }) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go index a36ff5b88614..c037d4992c4b 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go @@ -23,7 +23,7 @@ func TestAccSignalRServiceNetworkACL_basic(t *testing.T) { { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Deny"), ), }, data.ImportStep(), @@ -38,7 +38,7 @@ func TestAccSignalRServiceNetworkACL_requiresImport(t *testing.T) { { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Deny"), ), }, data.RequiresImportErrorStep(r.requiresImport), @@ -53,7 +53,7 @@ func TestAccSignalRServiceNetworkACL_complete(t *testing.T) { { Config: r.complete(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Allow"), ), }, data.ImportStep(), @@ -68,42 +68,39 @@ func TestAccSignalRServiceNetworkACL_update(t *testing.T) { { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Deny"), ), }, data.ImportStep(), { Config: r.complete(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Allow"), ), }, data.ImportStep(), { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Deny"), ), }, data.ImportStep(), }) } -func (r SignalRServiceNetworkACLResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { +func (r SignalRServiceNetworkACLResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.ServiceID(state.ID) if err != nil { return nil, err } - resp, err := client.SignalR.Client.Get(ctx, id.ResourceGroup, id.SignalRName) + _, err = clients.SignalR.Client.Get(ctx, id.ResourceGroup, id.SignalRName) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return utils.Bool(false), nil - } - return nil, fmt.Errorf("retrieving %q %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %v", id.String(), err) } - return utils.Bool(resp.Properties != nil && resp.Properties.NetworkACLs != nil), nil + return utils.Bool(false), nil } func (r SignalRServiceNetworkACLResource) basic(data acceptance.TestData) string { diff --git a/website/docs/r/signalr_service_network_acl.html.markdown b/website/docs/r/signalr_service_network_acl.html.markdown index 03acf4c66e61..b1539c33a034 100644 --- a/website/docs/r/signalr_service_network_acl.html.markdown +++ b/website/docs/r/signalr_service_network_acl.html.markdown @@ -70,7 +70,7 @@ resource "azurerm_signalr_service_network_acl" "example" { } private_endpoint { - name = azurerm_private_endpoint.example.name + id = azurerm_private_endpoint.example.id allowed_request_types = ["ServerConnection"] } } @@ -113,7 +113,7 @@ A `public_network` block supports the following: A `private_endpoint` block supports the following: -* `name` - (Required) The name of the Private Endpoint which is based on the SignalR service. +* `id` - (Required) The ID of the Private Endpoint which is based on the SignalR service. **Note:** `allowed_request_types` and `denied_request_types` cannot be set together. From 593d7e0975438358cb54b17d4b21e4d760ffa075 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 25 Jun 2021 09:51:47 +0800 Subject: [PATCH 03/12] update code --- .../signalr/signalr_service_network_acl_resource.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go index abfae9e0b8c1..c80f706f988e 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -57,7 +57,7 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { }, "private_endpoint": { - Type: pluginsdk.TypeSet, + Type: pluginsdk.TypeList, Optional: true, Computed: true, Elem: &pluginsdk.Resource{ @@ -73,6 +73,7 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { "allowed_request_types": { Type: pluginsdk.TypeSet, Optional: true, + Computed: true, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, ValidateFunc: validation.StringInSlice([]string{ @@ -113,6 +114,7 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { "allowed_request_types": { Type: pluginsdk.TypeSet, Optional: true, + Computed: true, ConflictsWith: []string{"network_acl.0.public_network.0.denied_request_types"}, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, @@ -312,7 +314,7 @@ func expandSignalRServiceNetworkACL(input []interface{}, privateEndpointConnecti return &signalr.NetworkACLs{ DefaultAction: signalr.ACLAction(v["default_action"].(string)), PublicNetwork: expandSignalRServicePublicNetwork(v["public_network"].([]interface{})), - PrivateEndpoints: expandSignalRServicePrivateEndpoint(v["private_endpoint"].(*pluginsdk.Set).List(), privateEndpointConnections), + PrivateEndpoints: expandSignalRServicePrivateEndpoint(v["private_endpoint"].([]interface{}), privateEndpointConnections), } } From 77043ef45eb76e6976e8cef95a0ba2d9ce987e94 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 25 Jun 2021 10:08:44 +0800 Subject: [PATCH 04/12] update code --- .../signalr/signalr_service_network_acl_resource.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go index c80f706f988e..abfae9e0b8c1 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -57,7 +57,7 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { }, "private_endpoint": { - Type: pluginsdk.TypeList, + Type: pluginsdk.TypeSet, Optional: true, Computed: true, Elem: &pluginsdk.Resource{ @@ -73,7 +73,6 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { "allowed_request_types": { Type: pluginsdk.TypeSet, Optional: true, - Computed: true, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, ValidateFunc: validation.StringInSlice([]string{ @@ -114,7 +113,6 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { "allowed_request_types": { Type: pluginsdk.TypeSet, Optional: true, - Computed: true, ConflictsWith: []string{"network_acl.0.public_network.0.denied_request_types"}, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, @@ -314,7 +312,7 @@ func expandSignalRServiceNetworkACL(input []interface{}, privateEndpointConnecti return &signalr.NetworkACLs{ DefaultAction: signalr.ACLAction(v["default_action"].(string)), PublicNetwork: expandSignalRServicePublicNetwork(v["public_network"].([]interface{})), - PrivateEndpoints: expandSignalRServicePrivateEndpoint(v["private_endpoint"].([]interface{}), privateEndpointConnections), + PrivateEndpoints: expandSignalRServicePrivateEndpoint(v["private_endpoint"].(*pluginsdk.Set).List(), privateEndpointConnections), } } From d1cbce3c723c60287ad45be7b54fb2ad40618737 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 25 Jun 2021 10:16:32 +0800 Subject: [PATCH 05/12] update code --- .../services/signalr/signalr_service_network_acl_resource.go | 3 +-- website/docs/r/signalr_service_network_acl.html.markdown | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go index abfae9e0b8c1..8a01d1070f3f 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -48,8 +48,7 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { Schema: map[string]*pluginsdk.Schema{ "default_action": { Type: pluginsdk.TypeString, - Optional: true, - Default: string(signalr.Deny), + Required: true, ValidateFunc: validation.StringInSlice([]string{ string(signalr.Allow), string(signalr.Deny), diff --git a/website/docs/r/signalr_service_network_acl.html.markdown b/website/docs/r/signalr_service_network_acl.html.markdown index b1539c33a034..9a38c4254659 100644 --- a/website/docs/r/signalr_service_network_acl.html.markdown +++ b/website/docs/r/signalr_service_network_acl.html.markdown @@ -89,7 +89,7 @@ The following arguments are supported: A `network_acl` block supports the following: -* `default_action` - (Optional) The default action when no other rule matches. Possible values are `Allow` and `Deny`. Defaults to `Deny`. +* `default_action` - (Required) The default action when no other rule matches. Possible values are `Allow` and `Deny`. * `public_network` - (Optional) A `public_network` block as defined below. From 916ce3f22b0ea1fc294076c6771ee1ec6abd4dc6 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 25 Jun 2021 12:55:57 +0800 Subject: [PATCH 06/12] update code --- ...gnalr_service_network_acl_resource_test.go | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go index c037d4992c4b..af6fb2c5d9ae 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/Azure/azure-sdk-for-go/services/signalr/mgmt/2020-05-01/signalr" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" @@ -23,7 +24,7 @@ func TestAccSignalRServiceNetworkACL_basic(t *testing.T) { { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Deny"), + check.That(data.ResourceName).ExistsInAzure(r), ), }, data.ImportStep(), @@ -38,7 +39,7 @@ func TestAccSignalRServiceNetworkACL_requiresImport(t *testing.T) { { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Deny"), + check.That(data.ResourceName).ExistsInAzure(r), ), }, data.RequiresImportErrorStep(r.requiresImport), @@ -53,7 +54,7 @@ func TestAccSignalRServiceNetworkACL_complete(t *testing.T) { { Config: r.complete(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Allow"), + check.That(data.ResourceName).ExistsInAzure(r), ), }, data.ImportStep(), @@ -68,21 +69,21 @@ func TestAccSignalRServiceNetworkACL_update(t *testing.T) { { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Deny"), + check.That(data.ResourceName).ExistsInAzure(r), ), }, data.ImportStep(), { Config: r.complete(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Allow"), + check.That(data.ResourceName).ExistsInAzure(r), ), }, data.ImportStep(), { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).Key("network_acl.0.default_action").HasValue("Deny"), + check.That(data.ResourceName).ExistsInAzure(r), ), }, data.ImportStep(), @@ -95,12 +96,19 @@ func (r SignalRServiceNetworkACLResource) Exists(ctx context.Context, clients *c return nil, err } - _, err = clients.SignalR.Client.Get(ctx, id.ResourceGroup, id.SignalRName) + resp, err := clients.SignalR.Client.Get(ctx, id.ResourceGroup, id.SignalRName) if err != nil { return nil, fmt.Errorf("retrieving %s: %v", id.String(), err) } - return utils.Bool(false), nil + requestTypes := signalr.PossibleRequestTypeValues() + requestTypes = append(requestTypes, "Trace") + + if resp.Properties != nil && resp.Properties.NetworkACLs != nil && resp.Properties.NetworkACLs.DefaultAction == signalr.Deny && resp.Properties.NetworkACLs.PublicNetwork != nil && len(*resp.Properties.NetworkACLs.PublicNetwork.Allow) == len(requestTypes) { + return utils.Bool(false), nil + } + + return utils.Bool(true), nil } func (r SignalRServiceNetworkACLResource) basic(data acceptance.TestData) string { @@ -127,7 +135,14 @@ func (r SignalRServiceNetworkACLResource) requiresImport(data acceptance.TestDat resource "azurerm_signalr_service_network_acl" "import" { signalr_service_id = azurerm_signalr_service_network_acl.test.signalr_service_id - network_acl = azurerm_signalr_service_network_acl.test.network_acl + + network_acl { + default_action = azurerm_signalr_service_network_acl.test.network_acl.0.default_action + + public_network { + allowed_request_types = azurerm_signalr_service_network_acl.test.network_acl.0.public_network.0.allowed_request_types + } + } } `, r.basic(data)) } @@ -175,6 +190,11 @@ resource "azurerm_signalr_service_network_acl" "test" { public_network { denied_request_types = ["ClientConnection"] } + + private_endpoint { + id = azurerm_private_endpoint.test.id + denied_request_types = ["ClientConnection"] + } } } `, r.template(data), data.RandomInteger, data.RandomInteger, data.RandomInteger) From 6b1b3807ee8c8aa2f961306b249568c51ecc78b6 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Sun, 27 Jun 2021 10:11:13 +0800 Subject: [PATCH 07/12] update code --- .../signalr_service_network_acl_resource.go | 96 ++++++++++--------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go index 8a01d1070f3f..9211855bc0f0 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -180,14 +180,14 @@ func resourceSignalRServiceNetworkACLCreateUpdate(d *pluginsdk.ResourceData, met } } - for _, v := range *networkACL.PrivateEndpoints { - if len(*v.Allow) != 0 && len(*v.Deny) != 0 { + for _, privateEndpoint := range *networkACL.PrivateEndpoints { + if len(*privateEndpoint.Allow) != 0 && len(*privateEndpoint.Deny) != 0 { return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `private_endpoint`") } - if networkACL.DefaultAction == signalr.Allow && len(*v.Allow) != 0 { + if networkACL.DefaultAction == signalr.Allow && len(*privateEndpoint.Allow) != 0 { return fmt.Errorf("when `default_action` is `Allow` for `private_endpoint`, `allowed_request_types` cannot be specified") - } else if networkACL.DefaultAction == signalr.Deny && len(*v.Deny) != 0 { + } else if networkACL.DefaultAction == signalr.Deny && len(*privateEndpoint.Deny) != 0 { return fmt.Errorf("when `default_action` is `Deny` for `private_endpoint`, `denied_request_types` cannot be specified") } } @@ -340,36 +340,37 @@ func expandSignalRServicePublicNetwork(input []interface{}) *signalr.NetworkACL func expandSignalRServicePrivateEndpoint(input []interface{}, privateEndpointConnections *[]signalr.PrivateEndpointConnection) *[]signalr.PrivateEndpointACL { results := make([]signalr.PrivateEndpointACL, 0) + if len(input) == 0 || len(*privateEndpointConnections) == 0 { + return &results + } for _, item := range input { v := item.(map[string]interface{}) privateEndpointId := v["id"].(string) - privateEndpointConnectionName := "" - if privateEndpointConnections != nil { - for _, privateEndpointConnection := range *privateEndpointConnections { - if privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil && privateEndpointId == *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID && privateEndpointConnection.Name != nil { - privateEndpointConnectionName = *privateEndpointConnection.Name - break + for _, privateEndpointConnection := range *privateEndpointConnections { + if privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil && privateEndpointId == *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID && privateEndpointConnection.Name != nil { + privateEndpointConnectionName := *privateEndpointConnection.Name + + allowedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { + allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) } - } - } - allowedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { - allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) - } + deniedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(v["denied_request_types"].(*pluginsdk.Set).List())) { + deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) + } - deniedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(v["denied_request_types"].(*pluginsdk.Set).List())) { - deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) - } + results = append(results, signalr.PrivateEndpointACL{ + Allow: &allowedRTs, + Deny: &deniedRTs, + Name: utils.String(privateEndpointConnectionName), + }) - results = append(results, signalr.PrivateEndpointACL{ - Allow: &allowedRTs, - Deny: &deniedRTs, - Name: utils.String(privateEndpointConnectionName), - }) + break + } + } } return &results @@ -435,32 +436,33 @@ func flattenSignalRServicePrivateEndpoint(input *[]signalr.PrivateEndpointACL, p for _, privateEndpointConnection := range *privateEndpointConnections { if item.Name != nil && privateEndpointConnection.Name != nil && *item.Name == *privateEndpointConnection.Name && privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil { privateEndpointId = *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID - break - } - } - } - allowedRequestTypes := make([]string, 0) - if item.Allow != nil { - for _, item := range *item.Allow { - allowedRequestTypes = append(allowedRequestTypes, (string)(item)) - } - } - allow := utils.FlattenStringSlice(&allowedRequestTypes) + allowedRequestTypes := make([]string, 0) + if item.Allow != nil { + for _, item := range *item.Allow { + allowedRequestTypes = append(allowedRequestTypes, (string)(item)) + } + } + allow := utils.FlattenStringSlice(&allowedRequestTypes) + + deniedRequestTypes := make([]string, 0) + if item.Deny != nil { + for _, item := range *item.Deny { + deniedRequestTypes = append(deniedRequestTypes, (string)(item)) + } + } + deny := utils.FlattenStringSlice(&deniedRequestTypes) + + results = append(results, map[string]interface{}{ + "id": privateEndpointId, + "allowed_request_types": allow, + "denied_request_types": deny, + }) - deniedRequestTypes := make([]string, 0) - if item.Deny != nil { - for _, item := range *item.Deny { - deniedRequestTypes = append(deniedRequestTypes, (string)(item)) + break + } } } - deny := utils.FlattenStringSlice(&deniedRequestTypes) - - results = append(results, map[string]interface{}{ - "id": privateEndpointId, - "allowed_request_types": allow, - "denied_request_types": deny, - }) } return results From 9390ae64d3b8f9a136acbfb1cd619f635da19cf8 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Sun, 27 Jun 2021 12:08:36 +0800 Subject: [PATCH 08/12] update code --- ...gnalr_service_network_acl_resource_test.go | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go index af6fb2c5d9ae..c9066ff23799 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go @@ -31,21 +31,6 @@ func TestAccSignalRServiceNetworkACL_basic(t *testing.T) { }) } -func TestAccSignalRServiceNetworkACL_requiresImport(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_signalr_service_network_acl", "test") - r := SignalRServiceNetworkACLResource{} - - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.RequiresImportErrorStep(r.requiresImport), - }) -} - func TestAccSignalRServiceNetworkACL_complete(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_signalr_service_network_acl", "test") r := SignalRServiceNetworkACLResource{} @@ -129,24 +114,6 @@ resource "azurerm_signalr_service_network_acl" "test" { `, r.template(data)) } -func (r SignalRServiceNetworkACLResource) requiresImport(data acceptance.TestData) string { - return fmt.Sprintf(` -%s - -resource "azurerm_signalr_service_network_acl" "import" { - signalr_service_id = azurerm_signalr_service_network_acl.test.signalr_service_id - - network_acl { - default_action = azurerm_signalr_service_network_acl.test.network_acl.0.default_action - - public_network { - allowed_request_types = azurerm_signalr_service_network_acl.test.network_acl.0.public_network.0.allowed_request_types - } - } -} -`, r.basic(data)) -} - func (r SignalRServiceNetworkACLResource) complete(data acceptance.TestData) string { return fmt.Sprintf(` %s From fc36f29afed8e6bf07ddba6389e2a45e354f1cfe Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Sun, 27 Jun 2021 18:22:55 +0800 Subject: [PATCH 09/12] update code --- .../signalr_service_network_acl_resource.go | 162 +++++++++--------- 1 file changed, 78 insertions(+), 84 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go index 9211855bc0f0..0433ce3f74b8 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -58,7 +58,6 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { "private_endpoint": { Type: pluginsdk.TypeSet, Optional: true, - Computed: true, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "id": { @@ -103,7 +102,6 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { "public_network": { Type: pluginsdk.TypeList, Optional: true, - Computed: true, MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ @@ -169,29 +167,27 @@ func resourceSignalRServiceNetworkACLCreateUpdate(d *pluginsdk.ResourceData, met parameters := resp if props := resp.Properties; props != nil { - parameters.Properties.NetworkACLs = expandSignalRServiceNetworkACL(d.Get("network_acl").([]interface{}), props.PrivateEndpointConnections) - - if networkACL := parameters.Properties.NetworkACLs; networkACL != nil { - if publicNetwork := networkACL.PublicNetwork; publicNetwork != nil { - if networkACL.DefaultAction == signalr.Allow && len(*publicNetwork.Allow) != 0 { - return fmt.Errorf("when `default_action` is `Allow` for `public_network`, `allowed_request_types` cannot be specified") - } else if networkACL.DefaultAction == signalr.Deny && len(*publicNetwork.Deny) != 0 { - return fmt.Errorf("when `default_action` is `Deny` for `public_network`, `denied_request_types` cannot be specified") - } - } + networkACL := expandSignalRServiceNetworkACL(d.Get("network_acl").([]interface{}), props.PrivateEndpointConnections) - for _, privateEndpoint := range *networkACL.PrivateEndpoints { - if len(*privateEndpoint.Allow) != 0 && len(*privateEndpoint.Deny) != 0 { - return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `private_endpoint`") - } + if networkACL.DefaultAction == signalr.Allow && len(*networkACL.PublicNetwork.Allow) != 0 { + return fmt.Errorf("when `default_action` is `Allow` for `public_network`, `allowed_request_types` cannot be specified") + } else if networkACL.DefaultAction == signalr.Deny && len(*networkACL.PublicNetwork.Deny) != 0 { + return fmt.Errorf("when `default_action` is `Deny` for `public_network`, `denied_request_types` cannot be specified") + } - if networkACL.DefaultAction == signalr.Allow && len(*privateEndpoint.Allow) != 0 { - return fmt.Errorf("when `default_action` is `Allow` for `private_endpoint`, `allowed_request_types` cannot be specified") - } else if networkACL.DefaultAction == signalr.Deny && len(*privateEndpoint.Deny) != 0 { - return fmt.Errorf("when `default_action` is `Deny` for `private_endpoint`, `denied_request_types` cannot be specified") - } + for _, privateEndpoint := range *networkACL.PrivateEndpoints { + if len(*privateEndpoint.Allow) != 0 && len(*privateEndpoint.Deny) != 0 { + return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `private_endpoint`") + } + + if networkACL.DefaultAction == signalr.Allow && len(*privateEndpoint.Allow) != 0 { + return fmt.Errorf("when `default_action` is `Allow` for `private_endpoint`, `allowed_request_types` cannot be specified") + } else if networkACL.DefaultAction == signalr.Deny && len(*privateEndpoint.Deny) != 0 { + return fmt.Errorf("when `default_action` is `Deny` for `private_endpoint`, `denied_request_types` cannot be specified") } } + + parameters.Properties.NetworkACLs = networkACL } future, err := client.Update(ctx, id.ResourceGroup, id.SignalRName, ¶meters) @@ -302,10 +298,6 @@ func resourceSignalRServiceNetworkACLDelete(d *pluginsdk.ResourceData, meta inte } func expandSignalRServiceNetworkACL(input []interface{}, privateEndpointConnections *[]signalr.PrivateEndpointConnection) *signalr.NetworkACLs { - if len(input) == 0 { - return nil - } - v := input[0].(map[string]interface{}) return &signalr.NetworkACLs{ @@ -316,20 +308,19 @@ func expandSignalRServiceNetworkACL(input []interface{}, privateEndpointConnecti } func expandSignalRServicePublicNetwork(input []interface{}) *signalr.NetworkACL { - if len(input) == 0 { - return nil - } + allowedRTs := make([]signalr.RequestType, 0) + deniedRTs := make([]signalr.RequestType, 0) - v := input[0].(map[string]interface{}) + if len(input) != 0 { + v := input[0].(map[string]interface{}) - allowedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { - allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) - } + for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { + allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) + } - deniedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(v["denied_request_types"].(*pluginsdk.Set).List())) { - deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) + for _, item := range *(utils.ExpandStringSlice(v["denied_request_types"].(*pluginsdk.Set).List())) { + deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) + } } return &signalr.NetworkACL{ @@ -340,36 +331,40 @@ func expandSignalRServicePublicNetwork(input []interface{}) *signalr.NetworkACL func expandSignalRServicePrivateEndpoint(input []interface{}, privateEndpointConnections *[]signalr.PrivateEndpointConnection) *[]signalr.PrivateEndpointACL { results := make([]signalr.PrivateEndpointACL, 0) - if len(input) == 0 || len(*privateEndpointConnections) == 0 { - return &results - } - - for _, item := range input { - v := item.(map[string]interface{}) - privateEndpointId := v["id"].(string) + if privateEndpointConnections != nil { for _, privateEndpointConnection := range *privateEndpointConnections { - if privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil && privateEndpointId == *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID && privateEndpointConnection.Name != nil { - privateEndpointConnectionName := *privateEndpointConnection.Name + result := signalr.PrivateEndpointACL{ + Allow: &[]signalr.RequestType{}, + Deny: &[]signalr.RequestType{}, + } - allowedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { - allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) - } + if privateEndpointConnection.Name != nil { + result.Name = utils.String(*privateEndpointConnection.Name) + } - deniedRTs := make([]signalr.RequestType, 0) - for _, item := range *(utils.ExpandStringSlice(v["denied_request_types"].(*pluginsdk.Set).List())) { - deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) - } + for _, item := range input { + v := item.(map[string]interface{}) + privateEndpointId := v["id"].(string) - results = append(results, signalr.PrivateEndpointACL{ - Allow: &allowedRTs, - Deny: &deniedRTs, - Name: utils.String(privateEndpointConnectionName), - }) + if privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil && privateEndpointId == *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID { + allowedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { + allowedRTs = append(allowedRTs, (signalr.RequestType)(item)) + } + result.Allow = &allowedRTs - break + deniedRTs := make([]signalr.RequestType, 0) + for _, item := range *(utils.ExpandStringSlice(v["denied_request_types"].(*pluginsdk.Set).List())) { + deniedRTs = append(deniedRTs, (signalr.RequestType)(item)) + } + result.Deny = &deniedRTs + + break + } } + + results = append(results, result) } } @@ -396,7 +391,7 @@ func flattenSignalRServiceNetworkACL(input *signalr.NetworkACLs, privateEndpoint } func flattenSignalRServicePublicNetwork(input *signalr.NetworkACL) []interface{} { - if input == nil { + if input == nil || (input.Allow != nil && input.Deny != nil && len(*input.Allow) == 0 && len(*input.Deny) == 0) { return make([]interface{}, 0) } @@ -431,35 +426,34 @@ func flattenSignalRServicePrivateEndpoint(input *[]signalr.PrivateEndpointACL, p } for _, item := range *input { - var privateEndpointId string - if privateEndpointConnections != nil { - for _, privateEndpointConnection := range *privateEndpointConnections { - if item.Name != nil && privateEndpointConnection.Name != nil && *item.Name == *privateEndpointConnection.Name && privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil { - privateEndpointId = *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID - - allowedRequestTypes := make([]string, 0) - if item.Allow != nil { - for _, item := range *item.Allow { - allowedRequestTypes = append(allowedRequestTypes, (string)(item)) + if item.Allow != nil && item.Deny != nil && (len(*item.Allow) != 0 || len(*item.Deny) != 0) { + if privateEndpointConnections != nil { + for _, privateEndpointConnection := range *privateEndpointConnections { + if item.Name != nil && privateEndpointConnection.Name != nil && *item.Name == *privateEndpointConnection.Name && privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil { + allowedRequestTypes := make([]string, 0) + if item.Allow != nil { + for _, item := range *item.Allow { + allowedRequestTypes = append(allowedRequestTypes, (string)(item)) + } } - } - allow := utils.FlattenStringSlice(&allowedRequestTypes) + allow := utils.FlattenStringSlice(&allowedRequestTypes) - deniedRequestTypes := make([]string, 0) - if item.Deny != nil { - for _, item := range *item.Deny { - deniedRequestTypes = append(deniedRequestTypes, (string)(item)) + deniedRequestTypes := make([]string, 0) + if item.Deny != nil { + for _, item := range *item.Deny { + deniedRequestTypes = append(deniedRequestTypes, (string)(item)) + } } - } - deny := utils.FlattenStringSlice(&deniedRequestTypes) + deny := utils.FlattenStringSlice(&deniedRequestTypes) - results = append(results, map[string]interface{}{ - "id": privateEndpointId, - "allowed_request_types": allow, - "denied_request_types": deny, - }) + results = append(results, map[string]interface{}{ + "id": *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID, + "allowed_request_types": allow, + "denied_request_types": deny, + }) - break + break + } } } } From 75c3e3b794a4e6dacec2e9c8296505d66f9b46b7 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Sun, 27 Jun 2021 20:16:10 +0800 Subject: [PATCH 10/12] update code --- .../signalr_service_network_acl_resource.go | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go index 0433ce3f74b8..3751a3dd6407 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -311,7 +311,7 @@ func expandSignalRServicePublicNetwork(input []interface{}) *signalr.NetworkACL allowedRTs := make([]signalr.RequestType, 0) deniedRTs := make([]signalr.RequestType, 0) - if len(input) != 0 { + if len(input) != 0 && input[0] != nil { v := input[0].(map[string]interface{}) for _, item := range *(utils.ExpandStringSlice(v["allowed_request_types"].(*pluginsdk.Set).List())) { @@ -391,7 +391,7 @@ func flattenSignalRServiceNetworkACL(input *signalr.NetworkACLs, privateEndpoint } func flattenSignalRServicePublicNetwork(input *signalr.NetworkACL) []interface{} { - if input == nil || (input.Allow != nil && input.Deny != nil && len(*input.Allow) == 0 && len(*input.Deny) == 0) { + if input == nil { return make([]interface{}, 0) } @@ -426,34 +426,32 @@ func flattenSignalRServicePrivateEndpoint(input *[]signalr.PrivateEndpointACL, p } for _, item := range *input { - if item.Allow != nil && item.Deny != nil && (len(*item.Allow) != 0 || len(*item.Deny) != 0) { - if privateEndpointConnections != nil { - for _, privateEndpointConnection := range *privateEndpointConnections { - if item.Name != nil && privateEndpointConnection.Name != nil && *item.Name == *privateEndpointConnection.Name && privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil { - allowedRequestTypes := make([]string, 0) - if item.Allow != nil { - for _, item := range *item.Allow { - allowedRequestTypes = append(allowedRequestTypes, (string)(item)) - } + if privateEndpointConnections != nil { + for _, privateEndpointConnection := range *privateEndpointConnections { + if item.Name != nil && privateEndpointConnection.Name != nil && *item.Name == *privateEndpointConnection.Name && privateEndpointConnection.PrivateEndpointConnectionProperties != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint != nil && privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID != nil { + allowedRequestTypes := make([]string, 0) + if item.Allow != nil { + for _, item := range *item.Allow { + allowedRequestTypes = append(allowedRequestTypes, (string)(item)) } - allow := utils.FlattenStringSlice(&allowedRequestTypes) + } + allow := utils.FlattenStringSlice(&allowedRequestTypes) - deniedRequestTypes := make([]string, 0) - if item.Deny != nil { - for _, item := range *item.Deny { - deniedRequestTypes = append(deniedRequestTypes, (string)(item)) - } + deniedRequestTypes := make([]string, 0) + if item.Deny != nil { + for _, item := range *item.Deny { + deniedRequestTypes = append(deniedRequestTypes, (string)(item)) } - deny := utils.FlattenStringSlice(&deniedRequestTypes) + } + deny := utils.FlattenStringSlice(&deniedRequestTypes) - results = append(results, map[string]interface{}{ - "id": *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID, - "allowed_request_types": allow, - "denied_request_types": deny, - }) + results = append(results, map[string]interface{}{ + "id": *privateEndpointConnection.PrivateEndpointConnectionProperties.PrivateEndpoint.ID, + "allowed_request_types": allow, + "denied_request_types": deny, + }) - break - } + break } } } From 465af57986fda5592c3cf32950b296844ff9d8a8 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Tue, 6 Jul 2021 20:07:10 +0800 Subject: [PATCH 11/12] update code --- .../signalr_service_network_acl_resource.go | 225 ++++++++---------- ...gnalr_service_network_acl_resource_test.go | 118 +++++++-- .../signalr_service_network_acl.html.markdown | 43 ++-- 3 files changed, 220 insertions(+), 166 deletions(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go index 3751a3dd6407..005e876cd5c1 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource.go @@ -40,103 +40,94 @@ func resourceArmSignalRServiceNetworkACL() *pluginsdk.Resource { ValidateFunc: validate.ServiceID, }, - "network_acl": { + "default_action": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.Allow), + string(signalr.Deny), + }, false), + }, + + "public_network": { Type: pluginsdk.TypeList, Required: true, MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "default_action": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(signalr.Allow), - string(signalr.Deny), - }, false), + // API response includes the `Trace` type but it isn't in rest api client. + // https://github.com/Azure/azure-rest-api-specs/issues/14923 + "allowed_request_types": { + Type: pluginsdk.TypeSet, + Optional: true, + ConflictsWith: []string{"public_network.0.denied_request_types"}, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.ClientConnection), + string(signalr.RESTAPI), + string(signalr.ServerConnection), + "Trace", + }, false), + }, + }, + + "denied_request_types": { + Type: pluginsdk.TypeSet, + Optional: true, + ConflictsWith: []string{"public_network.0.allowed_request_types"}, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.ClientConnection), + string(signalr.RESTAPI), + string(signalr.ServerConnection), + "Trace", + }, false), + }, + }, + }, + }, + }, + + "private_endpoint": { + Type: pluginsdk.TypeSet, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "id": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: networkValidate.PrivateEndpointID, }, - "private_endpoint": { + // API response includes the `Trace` type but it isn't in rest api client. + // https://github.com/Azure/azure-rest-api-specs/issues/14923 + "allowed_request_types": { Type: pluginsdk.TypeSet, Optional: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "id": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: networkValidate.PrivateEndpointID, - }, - - // API response includes the `Trace` type but it isn't in rest api client. - // https://github.com/Azure/azure-rest-api-specs/issues/14923 - "allowed_request_types": { - Type: pluginsdk.TypeSet, - Optional: true, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - string(signalr.ClientConnection), - string(signalr.RESTAPI), - string(signalr.ServerConnection), - "Trace", - }, false), - }, - }, - - "denied_request_types": { - Type: pluginsdk.TypeSet, - Optional: true, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - string(signalr.ClientConnection), - string(signalr.RESTAPI), - string(signalr.ServerConnection), - "Trace", - }, false), - }, - }, - }, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.ClientConnection), + string(signalr.RESTAPI), + string(signalr.ServerConnection), + "Trace", + }, false), }, }, - "public_network": { - Type: pluginsdk.TypeList, + "denied_request_types": { + Type: pluginsdk.TypeSet, Optional: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - // API response includes the `Trace` type but it isn't in rest api client. - // https://github.com/Azure/azure-rest-api-specs/issues/14923 - "allowed_request_types": { - Type: pluginsdk.TypeSet, - Optional: true, - ConflictsWith: []string{"network_acl.0.public_network.0.denied_request_types"}, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - string(signalr.ClientConnection), - string(signalr.RESTAPI), - string(signalr.ServerConnection), - "Trace", - }, false), - }, - }, - - "denied_request_types": { - Type: pluginsdk.TypeSet, - Optional: true, - ConflictsWith: []string{"network_acl.0.public_network.0.allowed_request_types"}, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - string(signalr.ClientConnection), - string(signalr.RESTAPI), - string(signalr.ServerConnection), - "Trace", - }, false), - }, - }, - }, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(signalr.ClientConnection), + string(signalr.RESTAPI), + string(signalr.ServerConnection), + "Trace", + }, false), }, }, }, @@ -167,7 +158,14 @@ func resourceSignalRServiceNetworkACLCreateUpdate(d *pluginsdk.ResourceData, met parameters := resp if props := resp.Properties; props != nil { - networkACL := expandSignalRServiceNetworkACL(d.Get("network_acl").([]interface{}), props.PrivateEndpointConnections) + networkACL := &signalr.NetworkACLs{ + DefaultAction: signalr.ACLAction(d.Get("default_action").(string)), + PublicNetwork: expandSignalRServicePublicNetwork(d.Get("public_network").([]interface{})), + } + + if v, ok := d.GetOk("private_endpoint"); ok { + networkACL.PrivateEndpoints = expandSignalRServicePrivateEndpoint(v.(*pluginsdk.Set).List(), props.PrivateEndpointConnections) + } if networkACL.DefaultAction == signalr.Allow && len(*networkACL.PublicNetwork.Allow) != 0 { return fmt.Errorf("when `default_action` is `Allow` for `public_network`, `allowed_request_types` cannot be specified") @@ -175,15 +173,17 @@ func resourceSignalRServiceNetworkACLCreateUpdate(d *pluginsdk.ResourceData, met return fmt.Errorf("when `default_action` is `Deny` for `public_network`, `denied_request_types` cannot be specified") } - for _, privateEndpoint := range *networkACL.PrivateEndpoints { - if len(*privateEndpoint.Allow) != 0 && len(*privateEndpoint.Deny) != 0 { - return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `private_endpoint`") - } + if networkACL.PrivateEndpoints != nil { + for _, privateEndpoint := range *networkACL.PrivateEndpoints { + if len(*privateEndpoint.Allow) != 0 && len(*privateEndpoint.Deny) != 0 { + return fmt.Errorf("`allowed_request_types` and `denied_request_types` cannot be set together for `private_endpoint`") + } - if networkACL.DefaultAction == signalr.Allow && len(*privateEndpoint.Allow) != 0 { - return fmt.Errorf("when `default_action` is `Allow` for `private_endpoint`, `allowed_request_types` cannot be specified") - } else if networkACL.DefaultAction == signalr.Deny && len(*privateEndpoint.Deny) != 0 { - return fmt.Errorf("when `default_action` is `Deny` for `private_endpoint`, `denied_request_types` cannot be specified") + if networkACL.DefaultAction == signalr.Allow && len(*privateEndpoint.Allow) != 0 { + return fmt.Errorf("when `default_action` is `Allow` for `private_endpoint`, `allowed_request_types` cannot be specified") + } else if networkACL.DefaultAction == signalr.Deny && len(*privateEndpoint.Deny) != 0 { + return fmt.Errorf("when `default_action` is `Deny` for `private_endpoint`, `denied_request_types` cannot be specified") + } } } @@ -226,8 +226,14 @@ func resourceSignalRServiceNetworkACLRead(d *pluginsdk.ResourceData, meta interf d.Set("signalr_service_id", id.ID()) if props := resp.Properties; props != nil { - if err := d.Set("network_acl", flattenSignalRServiceNetworkACL(props.NetworkACLs, props.PrivateEndpointConnections)); err != nil { - return fmt.Errorf("setting `network_acl`: %+v", err) + d.Set("default_action", props.NetworkACLs.DefaultAction) + + if err := d.Set("public_network", flattenSignalRServicePublicNetwork(props.NetworkACLs.PublicNetwork)); err != nil { + return fmt.Errorf("setting `public_network`: %+v", err) + } + + if err := d.Set("private_endpoint", flattenSignalRServicePrivateEndpoint(props.NetworkACLs.PrivateEndpoints, props.PrivateEndpointConnections)); err != nil { + return fmt.Errorf("setting `private_endpoint`: %+v", err) } } @@ -297,16 +303,6 @@ func resourceSignalRServiceNetworkACLDelete(d *pluginsdk.ResourceData, meta inte return nil } -func expandSignalRServiceNetworkACL(input []interface{}, privateEndpointConnections *[]signalr.PrivateEndpointConnection) *signalr.NetworkACLs { - v := input[0].(map[string]interface{}) - - return &signalr.NetworkACLs{ - DefaultAction: signalr.ACLAction(v["default_action"].(string)), - PublicNetwork: expandSignalRServicePublicNetwork(v["public_network"].([]interface{})), - PrivateEndpoints: expandSignalRServicePrivateEndpoint(v["private_endpoint"].(*pluginsdk.Set).List(), privateEndpointConnections), - } -} - func expandSignalRServicePublicNetwork(input []interface{}) *signalr.NetworkACL { allowedRTs := make([]signalr.RequestType, 0) deniedRTs := make([]signalr.RequestType, 0) @@ -371,25 +367,6 @@ func expandSignalRServicePrivateEndpoint(input []interface{}, privateEndpointCon return &results } -func flattenSignalRServiceNetworkACL(input *signalr.NetworkACLs, privateEndpointConnections *[]signalr.PrivateEndpointConnection) []interface{} { - if input == nil { - return make([]interface{}, 0) - } - - var defaultAction signalr.ACLAction - if input.DefaultAction != "" { - defaultAction = input.DefaultAction - } - - return []interface{}{ - map[string]interface{}{ - "default_action": defaultAction, - "public_network": flattenSignalRServicePublicNetwork(input.PublicNetwork), - "private_endpoint": flattenSignalRServicePrivateEndpoint(input.PrivateEndpoints, privateEndpointConnections), - }, - } -} - func flattenSignalRServicePublicNetwork(input *signalr.NetworkACL) []interface{} { if input == nil { return make([]interface{}, 0) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go index c9066ff23799..10acd6842913 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go @@ -65,6 +65,13 @@ func TestAccSignalRServiceNetworkACL_update(t *testing.T) { ), }, data.ImportStep(), + { + Config: r.multiplePrivateEndpoints(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( @@ -102,13 +109,10 @@ func (r SignalRServiceNetworkACLResource) basic(data acceptance.TestData) string resource "azurerm_signalr_service_network_acl" "test" { signalr_service_id = azurerm_signalr_service.test.id + default_action = "Deny" - network_acl { - default_action = "Deny" - - public_network { - allowed_request_types = ["ClientConnection"] - } + public_network { + allowed_request_types = ["ClientConnection"] } } `, r.template(data)) @@ -150,23 +154,105 @@ resource "azurerm_private_endpoint" "test" { resource "azurerm_signalr_service_network_acl" "test" { signalr_service_id = azurerm_signalr_service.test.id + default_action = "Allow" - network_acl { - default_action = "Allow" - - public_network { - denied_request_types = ["ClientConnection"] - } + public_network { + denied_request_types = ["ClientConnection"] + } - private_endpoint { - id = azurerm_private_endpoint.test.id - denied_request_types = ["ClientConnection"] - } + private_endpoint { + id = azurerm_private_endpoint.test.id + denied_request_types = ["ClientConnection"] } } `, r.template(data), data.RandomInteger, data.RandomInteger, data.RandomInteger) } +func (r SignalRServiceNetworkACLResource) multiplePrivateEndpoints(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_network" "test" { + name = "acctest-vnet-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + address_space = ["10.5.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "acctest-subnet-%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.5.2.0/24"] + + enforce_private_link_endpoint_network_policies = true +} + +resource "azurerm_private_endpoint" "test" { + name = "acctest-pe-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + subnet_id = azurerm_subnet.test.id + + private_service_connection { + name = "psc-sig-test" + is_manual_connection = false + private_connection_resource_id = azurerm_signalr_service.test.id + subresource_names = ["signalr"] + } +} + +resource "azurerm_virtual_network" "test2" { + name = "acctest-vnet2-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + address_space = ["10.5.0.0/16"] +} + +resource "azurerm_subnet" "test2" { + name = "acctest-subnet2-%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test2.name + address_prefixes = ["10.5.2.0/24"] + + enforce_private_link_endpoint_network_policies = true +} + +resource "azurerm_private_endpoint" "test2" { + name = "acctest-pe2-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + subnet_id = azurerm_subnet.test2.id + + private_service_connection { + name = "psc-sig-test2" + is_manual_connection = false + private_connection_resource_id = azurerm_signalr_service.test.id + subresource_names = ["signalr"] + } +} + +resource "azurerm_signalr_service_network_acl" "test" { + signalr_service_id = azurerm_signalr_service.test.id + default_action = "Allow" + + public_network { + denied_request_types = ["ClientConnection"] + } + + private_endpoint { + id = azurerm_private_endpoint.test.id + denied_request_types = ["ClientConnection"] + } + + private_endpoint { + id = azurerm_private_endpoint.test2.id + denied_request_types = ["ServerConnection"] + } +} +`, r.template(data), data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + func (r SignalRServiceNetworkACLResource) template(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/website/docs/r/signalr_service_network_acl.html.markdown b/website/docs/r/signalr_service_network_acl.html.markdown index 9a38c4254659..7e6e27ccaa63 100644 --- a/website/docs/r/signalr_service_network_acl.html.markdown +++ b/website/docs/r/signalr_service_network_acl.html.markdown @@ -61,18 +61,15 @@ resource "azurerm_private_endpoint" "example" { resource "azurerm_signalr_service_network_acl" "example" { signalr_service_id = azurerm_signalr_service.example.id + default_action = "Deny" - network_acl { - default_action = "Deny" - - public_network { - allowed_request_types = ["ClientConnection"] - } + public_network { + allowed_request_types = ["ClientConnection"] + } - private_endpoint { - id = azurerm_private_endpoint.example.id - allowed_request_types = ["ServerConnection"] - } + private_endpoint { + id = azurerm_private_endpoint.example.id + allowed_request_types = ["ServerConnection"] } } ``` @@ -83,15 +80,9 @@ The following arguments are supported: * `signalr_service_id` - (Required) The ID of the SignalR service. Changing this forces a new resource to be created. -* `network_acl` - (Required) A `network_acl` block as documented below. - ---- +* `default_action` - (Required) The default action to control the network access when no other rule matches. Possible values are `Allow` and `Deny`. -A `network_acl` block supports the following: - -* `default_action` - (Required) The default action when no other rule matches. Possible values are `Allow` and `Deny`. - -* `public_network` - (Optional) A `public_network` block as defined below. +* `public_network` - (Required) A `public_network` block as defined below. * `private_endpoint` - (Optional) A `private_endpoint` block as defined below. @@ -99,32 +90,32 @@ A `network_acl` block supports the following: A `public_network` block supports the following: -**Note:** `allowed_request_types` and `denied_request_types` cannot be set together. - -* `allowed_request_types` - (Optional) The allowed request types. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. +* `allowed_request_types` - (Optional) The allowed request types for the public network. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. **Note:** When `default_action` is `Allow`, `allowed_request_types`cannot be set. -* `denied_request_types` - (Optional) The denied request types. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. +* `denied_request_types` - (Optional) The denied request types for the public network. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. **Note:** When `default_action` is `Deny`, `denied_request_types`cannot be set. +**Note:** `allowed_request_types` and `denied_request_types` cannot be set together. + --- A `private_endpoint` block supports the following: * `id` - (Required) The ID of the Private Endpoint which is based on the SignalR service. -**Note:** `allowed_request_types` and `denied_request_types` cannot be set together. - -* `allowed_request_types` - (Optional) The allowed request types. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. +* `allowed_request_types` - (Optional) The allowed request types for the Private Endpoint Connection. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. **Note:** When `default_action` is `Allow`, `allowed_request_types`cannot be set. -* `denied_request_types` - (Optional) The denied request types. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. +* `denied_request_types` - (Optional) The denied request types for the Private Endpoint Connection. Possible values are `ClientConnection`, `ServerConnection`, `RESTAPI` and `Trace`. **Note:** When `default_action` is `Deny`, `denied_request_types`cannot be set. +**Note:** `allowed_request_types` and `denied_request_types` cannot be set together. + ## Attributes Reference In addition to the Arguments listed above - the following Attributes are exported: From c21e893eaec5314f846fb3f8ff19871114f4a0c0 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Tue, 20 Jul 2021 15:02:07 +0800 Subject: [PATCH 12/12] update code --- ...gnalr_service_network_acl_resource_test.go | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go index 10acd6842913..c08b9ddd8fbc 100644 --- a/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go +++ b/azurerm/internal/services/signalr/signalr_service_network_acl_resource_test.go @@ -58,6 +58,28 @@ func TestAccSignalRServiceNetworkACL_update(t *testing.T) { ), }, data.ImportStep(), + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccSignalRServiceNetworkACL_updateMultiplePrivateEndpoints(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_signalr_service_network_acl", "test") + r := SignalRServiceNetworkACLResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ { Config: r.complete(data), Check: acceptance.ComposeTestCheckFunc( @@ -73,7 +95,7 @@ func TestAccSignalRServiceNetworkACL_update(t *testing.T) { }, data.ImportStep(), { - Config: r.basic(data), + Config: r.complete(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ),