Open kahawai-sre opened 1 year ago
@magodo or @tombuildsstuff any chance you can provide some brief review and feedback on this issue?
This duplicates to https://github.com/hashicorp/terraform/issues/32991, which shall be fixed once we migrate to the new plugin framework.
Thanks for taking the time to comment @magodo I see that particular issue can be worked around by downgrading the terraform binary to < v1.4, but that does not seem to help in this case. For example I see the same issue with e.g. v1.3.9. Questions:
@kahawai-sre I just found an old issue that asking the same thing: https://github.com/hashicorp/terraform-provider-azurerm/issues/5819. From my previous comment: https://github.com/hashicorp/terraform-provider-azurerm/issues/5819#issuecomment-589553259, the issue should still resides in the legacy SDK, and you can mitigate it by:
set the Default value for each optional string property inside security_rule schema
I've verified that works with TF v1.5.0 and the latest provider locally.
For the new plugin framework integration, is there a timeline for that?
Unfortunately, no.
Thanks @magodo - that works for me 👍
For reference I updated the defaults for each property to either "" (string) or [] (list(string)), and removed the try() handlers and this resolved the issue. Thanks again!
variable "nsgs" {
type = map(object({
name = string
location = string
resource_group_name = string
tags = optional(map(string))
security_rules = optional(list(object({
name = string
access = string
direction = string
priority = number
protocol = string
description = optional(string, "")
source_address_prefix = optional(string, "")
source_address_prefixes = optional(list(string), [])
source_application_security_group_ids = optional(list(string), [])
source_port_range = optional(string, "")
source_port_ranges = optional(list(string), [])
destination_address_prefix = optional(string, "")
destination_address_prefixes = optional(list(string), [])
destination_application_security_group_ids = optional(list(string), [])
destination_port_range = optional(string, "")
destination_port_ranges = optional(list(string), [])
})))
})) .... }
@tombuildsstuff and @metacpp please note that the same issue exists with "route" under _azurerm_routetable (inline routes). Specifically _next_hop_in_ipaddress is set by the provider/API to "" after apply for any routes that do not specify this. So if we delete an inline route, any routes that have not specified a value for next_hop_in_ip_address are deleted and recreated. In this instance we cannot implement the fix described for inline NSG rules above because - for some reason - a validation has been added to the provider preventing passing an empty string "" as the value for this property (refer https://github.com/hashicorp/terraform-provider-azurerm/issues/2736 for example). So, we do not specify, or pass null, but subsequently next_hop_in_ip_address is set to "" in the state file, and - as above - rule changes compare null with "" and then delete and recreate all routes where that optional property not used.
Given users are relying on inline NSG rules and routes - partly because it is documented as a viable method - and partly - at least for NSG rules - because the distinct _azurerm_network_securityrule option does not enforce drift detection for rules that might be made out of band, and in certain environments this breaks compliance controls. It would be great if this can be kept in mind for any future changes to either make the capability more robust (if needed) or at least not break current state described in the issue / fix above. i.e.:
Is there an existing issue for this?
Community Note
Terraform Version
1.5.3
AzureRM Provider Version
3.63.0
Affected Resource(s)/Data Source(s)
azurerm_network_security_group - inline security_rules
Terraform Configuration Files
Debug Output/Panic Output
Expected Behaviour
Initial apply works correctly - the NSG and inline rules are created as per var.nsgs.
If a rule is deleted from var.nsgs security_rules, for example "rule3", terraform plan/apply should show the only change being the deletion of rule3.
This behavior should be consistent irrespective of whether any of the rules contain properties with lists (e.g. "source_address_prefixes"), dynamic lookups, or basic strings.
Actual Behaviour
After the initial apply/deployment succeeds, If "rule3" is removed from the security_rules section of var.nsgs, and plan or apply run subsequently, plan shows rules other than "rule3" being deleted and re-created. Specifically, in the example provided, deleting rule3 from security_rules after initial apply, and doing a second plan/apply, shows "rule4" and "rule6" being deleted and re-created, but not rule5.
From my testing this only happens when the list of security_rules contains rules with fields of type list(string) e.g. "source_address_prefixes" and "destination_address_prefixes" in the examples above.
If the rules in var.nsgs contain only simple string-based properties (no properties with data type = list(string), any rule in the list can be removed, and plan or apply correctly shows just that rule being removed as would be expected.
Steps to Reproduce
Have I produced this issue through coding, or is it a known issue or bug?
Important Factoids
In this instance azurerm_network_security_rule is not a viable alternative because is does not track drift in rules created on an NSG outside of the terraform deployment, and that breaks compliance.
References
No response