diff --git a/.changelog/27102.txt b/.changelog/27102.txt new file mode 100644 index 000000000000..32cdba44fb98 --- /dev/null +++ b/.changelog/27102.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_networkfirewall_rule_group: Change `rule_group.rules_source.stateful_rule` from `TypeSet` to `TypeList` to preserve rule order +``` diff --git a/internal/service/networkfirewall/rule_group.go b/internal/service/networkfirewall/rule_group.go index 74d3927add39..dd4fd210bec3 100644 --- a/internal/service/networkfirewall/rule_group.go +++ b/internal/service/networkfirewall/rule_group.go @@ -136,7 +136,7 @@ func ResourceRuleGroup() *schema.Resource { Optional: true, }, "stateful_rule": { - Type: schema.TypeSet, + Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -799,8 +799,8 @@ func expandRuleGroup(l []interface{}) *networkfirewall.RuleGroup { if v, ok := rsMap["rules_string"].(string); ok && v != "" { rulesSource.RulesString = aws.String(v) } - if v, ok := rsMap["stateful_rule"].(*schema.Set); ok && v.Len() > 0 { - rulesSource.StatefulRules = expandStatefulRules(v.List()) + if v, ok := rsMap["stateful_rule"].([]interface{}); ok && len(v) > 0 { + rulesSource.StatefulRules = expandStatefulRules(v) } if v, ok := rsMap["stateless_rules_and_custom_actions"].([]interface{}); ok && len(v) > 0 && v[0] != nil { rulesSource.StatelessRulesAndCustomActions = expandStatelessRulesAndCustomActions(v) diff --git a/internal/service/networkfirewall/rule_group_test.go b/internal/service/networkfirewall/rule_group_test.go index aaf1e6909dac..81d7d5fdc2bf 100644 --- a/internal/service/networkfirewall/rule_group_test.go +++ b/internal/service/networkfirewall/rule_group_test.go @@ -167,18 +167,16 @@ func TestAccNetworkFirewallRuleGroup_Basic_statefulRule(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "rule_group.#", "1"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.#", "1"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionPass, - "header.#": "1", - "header.0.destination": "124.1.1.24/32", - "header.0.destination_port": "53", - "header.0.direction": networkfirewall.StatefulRuleDirectionAny, - "header.0.protocol": networkfirewall.StatefulRuleProtocolTcp, - "header.0.source": "1.2.3.4/32", - "header.0.source_port": "53", - "rule_option.#": "1", - }), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*.rule_option.*", map[string]string{ + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "124.1.1.24/32"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "53"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionAny), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolTcp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "1.2.3.4/32"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "53"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.*", map[string]string{ "keyword": "sid:1", }), resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.#", "0"), @@ -590,17 +588,15 @@ func TestAccNetworkFirewallRuleGroup_updateStatefulRule(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionDrop, - "header.#": "1", - "header.0.destination": "1.2.3.4/32", - "header.0.destination_port": "1001", - "header.0.direction": networkfirewall.StatefulRuleDirectionForward, - "header.0.protocol": networkfirewall.StatefulRuleProtocolIp, - "header.0.source": "124.1.1.24/32", - "header.0.source_port": "1001", - "rule_option.#": "1", - }), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionDrop), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "1.2.3.4/32"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "1001"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionForward), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolIp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "124.1.1.24/32"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "1001"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", "1"), ), }, { @@ -638,17 +634,15 @@ func TestAccNetworkFirewallRuleGroup_updateMultipleStatefulRules(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "2"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionPass, - "header.#": "1", - "header.0.destination": "124.1.1.24/32", - "header.0.destination_port": "53", - "header.0.direction": networkfirewall.StatefulRuleDirectionAny, - "header.0.protocol": networkfirewall.StatefulRuleProtocolTcp, - "header.0.source": "1.2.3.4/32", - "header.0.source_port": "53", - "rule_option.#": "1", - }), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "124.1.1.24/32"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "53"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionAny), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolTcp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "1.2.3.4/32"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "53"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ "action": networkfirewall.StatefulActionAlert, "header.#": "1", @@ -672,17 +666,15 @@ func TestAccNetworkFirewallRuleGroup_updateMultipleStatefulRules(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionDrop, - "header.#": "1", - "header.0.destination": "1.2.3.4/32", - "header.0.destination_port": "1001", - "header.0.direction": networkfirewall.StatefulRuleDirectionForward, - "header.0.protocol": networkfirewall.StatefulRuleProtocolIp, - "header.0.source": "124.1.1.24/32", - "header.0.source_port": "1001", - "rule_option.#": "1", - }), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionDrop), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "1.2.3.4/32"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "1001"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionForward), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolIp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "124.1.1.24/32"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "1001"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", "1"), ), }, { @@ -713,9 +705,7 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_action(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionAlert, - }), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionAlert), ), }, { @@ -728,9 +718,7 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_action(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionPass, - }), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), ), }, { @@ -743,9 +731,7 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_action(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionDrop, - }), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionDrop), ), }, { @@ -774,17 +760,15 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_header(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionPass, - "header.#": "1", - "header.0.destination": "ANY", - "header.0.destination_port": "1990", - "header.0.direction": networkfirewall.StatefulRuleDirectionAny, - "header.0.protocol": networkfirewall.StatefulRuleProtocolTcp, - "header.0.source": "ANY", - "header.0.source_port": "1994", - "rule_option.#": "1", - }), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "ANY"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "1990"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionAny), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolTcp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "ANY"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "1994"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", "1"), ), }, { @@ -797,17 +781,15 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_header(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{ - "action": networkfirewall.StatefulActionPass, - "header.#": "1", - "header.0.destination": "ANY", - "header.0.destination_port": "ANY", - "header.0.direction": networkfirewall.StatefulRuleDirectionAny, - "header.0.protocol": networkfirewall.StatefulRuleProtocolTcp, - "header.0.source": "ANY", - "header.0.source_port": "ANY", - "rule_option.#": "1", - }), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "ANY"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "ANY"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionAny), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolTcp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "ANY"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "ANY"), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", "1"), ), }, {