Skip to content

azurerm_eventhub_namespace - perpetual drift on network_rulesets.default_action when public_network_access_enabled = false #33100

Description

@AdmirMuric

Is there an existing issue for this?

  • I have searched the existing issues

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave comments along the lines of "+1", "me too" or "any updates", they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment and review the contribution guide to help.

Terraform Version

1.15.7

AzureRM Provider Version

4.69.0

Affected Resource(s)/Data Source(s)

azurerm_eventhub_namespace

Affected Location(s)

westeurope

Terraform Configuration Files

resource "azurerm_eventhub_namespace" "this" {
  name                = "my-mamepace"
  location            = "westeurope"
  resource_group_name = "my-resource-group"
  sku                 = "Standard"

  public_network_access_enabled = false

  network_rulesets {
    default_action                 = "Deny"
    public_network_access_enabled  = false
  }
}

Debug Output/Panic Output

# terraform plan (relevant excerpt)

  ~ resource "azurerm_eventhub_namespace" "this" {
        id   = "/subscriptions/xxxx/resourceGroups/my-resource-group/providers/Microsoft.EventHub/namespaces/my-mamepace"
        name = "my-mamepace"

      ~ network_rulesets {
          ~ default_action = "Allow" -> "Deny"
            # (4 unchanged attributes hidden)
        }
        # (16 unchanged attributes hidden)
    }

Expected Behaviour

With default_action = "Deny" configured in network_rulesets, the value should be persisted and read back consistently so that a subsequent terraform plan shows no changes (a clean/no-op plan).

Actual Behaviour

Every terraform plan/apply shows perpetual drift:

~ default_action = "Allow" -> "Deny"

When public_network_access_enabled = false, Azure normalizes defaultAction server-side to Allow (the field is inert while public access is disabled). Confirming directly against the API shows the normalized value:

az eventhubs namespace network-rule-set list \
  --namespace-name my-mamepace \
  --resource-group my-resource-group \
  --query defaultAction
# => "Allow"

The provider's read path flattens this returned value verbatim into state with no reconciliation against the configured value, so the diff never converges:

https://github.com/hashicorp/terraform-provider-azurerm/blob/main/internal/services/eventhub/eventhub_namespace_resource.go#L729-L739

// TODO: fix this

publicNetworkAccess := ruleset.Model.Properties.PublicNetworkAccess == nil || *ruleset.Model.Properties.PublicNetworkAccess != networkrulesets.PublicNetworkAccessFlagDisabled

return []interface{}{map[string]interface{}{
    "default_action": string(*ruleset.Model.Properties.DefaultAction),
    ...
}}, nil

The default_action schema also has no DiffSuppressFunc to absorb this normalization, unlike other fields in the same file (e.g. subnet_id uses suppress.CaseDifference, and virtual_network_rule was switched to TypeSet) that already compensate for the API returning values differently than sent.

Workaround: setting default_action = "Allow" aligns the config with the API's normalized value. This is safe because public access is already fully blocked by public_network_access_enabled = false.

Possible fix: add a DiffSuppressFunc on network_rulesets.default_action that suppresses changes when public_network_access_enabled = false, following the existing subnet_id precedent in this file.

Steps to Reproduce

  1. Create an azurerm_eventhub_namespace (Standard SKU) with public_network_access_enabled = false and a network_rulesets block containing default_action = "Deny" and public_network_access_enabled = false.
  2. Run terraform apply and let it complete successfully.
  3. Run terraform plan again.
  4. Observe the perpetual diff ~ default_action = "Allow" -> "Deny" that never converges.

Important Factoids

None

References

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions