Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_servicebus_namespace - add support for network_rule_set #23057

Merged
merged 5 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ func resourceServiceBusNamespaceNetworkRuleSet() *pluginsdk.Resource {
Update: resourceServiceBusNamespaceNetworkRuleSetCreateUpdate,
Delete: resourceServiceBusNamespaceNetworkRuleSetDelete,

DeprecationMessage: "The `azurerm_servicebus_namespace_network_rule_set` resource is deprecated and will be removed in version 4.0 of the AzureRM provider. Please use `network_rule_set` inside the `azurerm_servicebus_namespace` resource instead.",

Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
_, err := namespaces.ParseNamespaceID(id)
return err
Expand Down
188 changes: 188 additions & 0 deletions internal/services/servicebus/servicebus_namespace_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/features"
keyVaultParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/parse"
keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/servicebus/migration"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/servicebus/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tags"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/suppress"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts"
"github.com/hashicorp/terraform-provider-azurerm/utils"
Expand Down Expand Up @@ -175,6 +177,68 @@ func resourceServiceBusNamespace() *pluginsdk.Resource {
ForceNew: true,
},

"network_rule_set": {
Type: pluginsdk.TypeList,
Optional: true,
Computed: !features.FourPointOhBeta(),
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"default_action": {
Type: pluginsdk.TypeString,
Optional: true,
Default: string(namespaces.DefaultActionAllow),
ValidateFunc: validation.StringInSlice([]string{
string(namespaces.DefaultActionAllow),
string(namespaces.DefaultActionDeny),
}, false),
},

"public_network_access_enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: true,
},

"ip_rules": {
Type: pluginsdk.TypeSet,
Optional: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},

"trusted_services_allowed": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: false,
},

"network_rules": {
Type: pluginsdk.TypeSet,
Optional: true,
Set: networkRuleHash,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"subnet_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: commonids.ValidateSubnetID,
// The subnet ID returned from the service will have `resourceGroup/{resourceGroupName}` all in lower cases...
DiffSuppressFunc: suppress.CaseDifference,
},
"ignore_missing_vnet_service_endpoint": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: false,
},
},
},
},
},
},
},

"endpoint": {
Type: pluginsdk.TypeString,
Computed: true,
Expand Down Expand Up @@ -277,6 +341,25 @@ func resourceServiceBusNamespaceCreateUpdate(d *pluginsdk.ResourceData, meta int
}

d.SetId(id.ID())

if d.HasChange("network_rule_set") {
oldNetworkRuleSet, newNetworkRuleSet := d.GetChange("network_rule_set")
// if the network rule set has been removed from config, reset it instead as there is no way to remove a rule set
if len(oldNetworkRuleSet.([]interface{})) == 1 && len(newNetworkRuleSet.([]interface{})) == 0 {
log.Printf("[DEBUG] Resetting Network Rule Set associated with %s..", id)
if err = resetNetworkRuleSetForNamespace(ctx, client, id); err != nil {
return err
}
log.Printf("[DEBUG] Reset the Existing Network Rule Set associated with %s", id)
} else {
log.Printf("[DEBUG] Creating the Network Rule Set associated with %s..", id)
if err = createNetworkRuleSetForNamespace(ctx, client, id, newNetworkRuleSet.([]interface{})); err != nil {
return err
}
log.Printf("[DEBUG] Created the Network Rule Set associated with %s", id)
}
}

return resourceServiceBusNamespaceRead(d, meta)
}

Expand Down Expand Up @@ -366,6 +449,18 @@ func resourceServiceBusNamespaceRead(d *pluginsdk.ResourceData, meta interface{}
d.Set("default_secondary_key", keysModel.SecondaryKey)
}
}

networkRuleSet, err := client.GetNetworkRuleSet(ctx, *id)
if err != nil {
return fmt.Errorf("retrieving network rule set %s: %+v", *id, err)
}

if model := networkRuleSet.Model; model != nil {
if props := model.Properties; props != nil {
d.Set("network_rule_set", flattenServiceBusNamespaceNetworkRuleSet(*props))
}
}

return nil
}

Expand Down Expand Up @@ -490,3 +585,96 @@ func servicebusTLSVersionDiff(ctx context.Context, d *pluginsdk.ResourceDiff, _
}
return
}

func createNetworkRuleSetForNamespace(ctx context.Context, client *namespaces.NamespacesClient, id namespaces.NamespaceId, input []interface{}) error {
if len(input) < 1 || input[0] == nil {
return nil
}
item := input[0].(map[string]interface{})

defaultAction := namespaces.DefaultAction(item["default_action"].(string))
vnetRule := expandServiceBusNamespaceVirtualNetworkRules(item["network_rules"].(*pluginsdk.Set).List())
ipRule := expandServiceBusNamespaceIPRules(item["ip_rules"].(*pluginsdk.Set).List())
publicNetworkAcc := "Disabled"
if item["public_network_access_enabled"].(bool) {
publicNetworkAcc = "Enabled"
}

// API doesn't accept "Deny" to be set for "default_action" if no "ip_rules" or "network_rules" is defined and returns no error message to the user
if defaultAction == namespaces.DefaultActionDeny && vnetRule == nil && ipRule == nil {
return fmt.Errorf(" The `default_action` of `network_rule_set` can only be set to `Allow` if no `ip_rules` or `network_rules` is set")
}

publicNetworkAccess := namespaces.PublicNetworkAccessFlag(publicNetworkAcc)

parameters := namespaces.NetworkRuleSet{
Properties: &namespaces.NetworkRuleSetProperties{
DefaultAction: &defaultAction,
VirtualNetworkRules: vnetRule,
IPRules: ipRule,
PublicNetworkAccess: &publicNetworkAccess,
TrustedServiceAccessEnabled: utils.Bool(item["trusted_services_allowed"].(bool)),
},
}

if _, err := client.CreateOrUpdateNetworkRuleSet(ctx, id, parameters); err != nil {
return fmt.Errorf("creating/updating %s: %+v", id, err)
}

return nil
}

func resetNetworkRuleSetForNamespace(ctx context.Context, client *namespaces.NamespacesClient, id namespaces.NamespaceId) error {
defaultAction := namespaces.DefaultActionAllow
parameters := namespaces.NetworkRuleSet{
Properties: &namespaces.NetworkRuleSetProperties{
DefaultAction: &defaultAction,
},
}

if _, err := client.CreateOrUpdateNetworkRuleSet(ctx, id, parameters); err != nil {
return fmt.Errorf("resetting %s: %+v", id, err)
}

return nil
}

func flattenServiceBusNamespaceNetworkRuleSet(networkRuleSet namespaces.NetworkRuleSetProperties) []interface{} {
defaultAction := ""
if v := networkRuleSet.DefaultAction; v != nil {
defaultAction = string(*v)
}
publicNetworkAccess := namespaces.PublicNetworkAccessFlagEnabled
if v := networkRuleSet.PublicNetworkAccess; v != nil {
publicNetworkAccess = *v
}

trustedServiceEnabled := false
if networkRuleSet.TrustedServiceAccessEnabled != nil {
trustedServiceEnabled = *networkRuleSet.TrustedServiceAccessEnabled
}

networkRules := flattenServiceBusNamespaceVirtualNetworkRules(networkRuleSet.VirtualNetworkRules)
ipRules := flattenServiceBusNamespaceIPRules(networkRuleSet.IPRules)

// only set network rule set if the values are different than what they are defaulted to during namespace creation
// this has to wait until 4.0 due to `azurerm_servicebus_namespace_network_rule_set` which forces `network_rule_set` to be Optional/Computed
if features.FourPointOhBeta() {
if defaultAction == string(namespaces.DefaultActionAllow) &&
publicNetworkAccess == namespaces.PublicNetworkAccessFlagEnabled &&
!trustedServiceEnabled &&
len(networkRules) == 0 &&
len(ipRules) == 0 {

return []interface{}{}
}
}

return []interface{}{map[string]interface{}{
"default_action": defaultAction,
"trusted_services_allowed": trustedServiceEnabled,
"public_network_access_enabled": publicNetworkAccess == namespaces.PublicNetworkAccessFlagEnabled,
"network_rules": pluginsdk.NewSet(networkRuleHash, networkRules),
"ip_rules": ipRules,
}}
}
Loading
Loading