Skip to content

Commit aa7cf8f

Browse files
committed
remove ForceNew attribute from stateful_rule field and its children
1 parent bebe732 commit aa7cf8f

2 files changed

Lines changed: 223 additions & 15 deletions

File tree

aws/resource_aws_networkfirewall_rule_group.go

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,26 +170,22 @@ func resourceAwsNetworkFirewallRuleGroup() *schema.Resource {
170170
"stateful_rule": {
171171
Type: schema.TypeSet,
172172
Optional: true,
173-
ForceNew: true,
174173
Elem: &schema.Resource{
175174
Schema: map[string]*schema.Schema{
176175
"action": {
177176
Type: schema.TypeString,
178177
Required: true,
179-
ForceNew: true,
180178
ValidateFunc: validation.StringInSlice(networkfirewall.StatefulAction_Values(), false),
181179
},
182180
"header": {
183181
Type: schema.TypeList,
184182
Required: true,
185183
MaxItems: 1,
186-
ForceNew: true,
187184
Elem: &schema.Resource{
188185
Schema: map[string]*schema.Schema{
189186
"destination": {
190187
Type: schema.TypeString,
191188
Required: true,
192-
ForceNew: true,
193189
ValidateFunc: validation.Any(
194190
validateIpv4CIDRNetworkAddress,
195191
validation.StringInSlice([]string{networkfirewall.StatefulRuleDirectionAny}, false),
@@ -198,24 +194,20 @@ func resourceAwsNetworkFirewallRuleGroup() *schema.Resource {
198194
"destination_port": {
199195
Type: schema.TypeString,
200196
Required: true,
201-
ForceNew: true,
202197
},
203198
"direction": {
204199
Type: schema.TypeString,
205200
Required: true,
206-
ForceNew: true,
207201
ValidateFunc: validation.StringInSlice(networkfirewall.StatefulRuleDirection_Values(), false),
208202
},
209203
"protocol": {
210204
Type: schema.TypeString,
211205
Required: true,
212-
ForceNew: true,
213206
ValidateFunc: validation.StringInSlice(networkfirewall.StatefulRuleProtocol_Values(), false),
214207
},
215208
"source": {
216209
Type: schema.TypeString,
217210
Required: true,
218-
ForceNew: true,
219211
ValidateFunc: validation.Any(
220212
validateIpv4CIDRNetworkAddress,
221213
validation.StringInSlice([]string{networkfirewall.StatefulRuleDirectionAny}, false),
@@ -224,7 +216,6 @@ func resourceAwsNetworkFirewallRuleGroup() *schema.Resource {
224216
"source_port": {
225217
Type: schema.TypeString,
226218
Required: true,
227-
ForceNew: true,
228219
},
229220
},
230221
},
@@ -498,19 +489,20 @@ func resourceAwsNetworkFirewallRuleGroupUpdate(ctx context.Context, d *schema.Re
498489
log.Printf("[DEBUG] Updating NetworkFirewall Rule Group %s", arn)
499490

500491
if d.HasChanges("description", "rule_group", "rules", "type") {
492+
// Provide updated object with the currently configured fields
501493
input := &networkfirewall.UpdateRuleGroupInput{
502494
RuleGroupArn: aws.String(arn),
503495
Type: aws.String(d.Get("type").(string)),
504496
UpdateToken: aws.String(d.Get("update_token").(string)),
505497
}
506-
if d.HasChange("description") {
507-
input.Description = aws.String(d.Get("description").(string))
498+
if v, ok := d.GetOk("description"); ok {
499+
input.Description = aws.String(v.(string))
508500
}
509-
if d.HasChange("rule_group") {
510-
input.RuleGroup = expandNetworkFirewallRuleGroup(d.Get("rule_group").([]interface{}))
501+
if v, ok := d.GetOk("rule_group"); ok {
502+
input.RuleGroup = expandNetworkFirewallRuleGroup(v.([]interface{}))
511503
}
512-
if d.HasChange("rules") {
513-
input.Rules = aws.String(d.Get("rules").(string))
504+
if v, ok := d.GetOk("rules"); ok {
505+
input.Rules = aws.String(v.(string))
514506
}
515507

516508
_, err := conn.UpdateRuleGroupWithContext(ctx, input)

aws/resource_aws_networkfirewall_rule_group_test.go

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ func TestAccAwsNetworkFirewallRuleGroup_basic_statefulRule(t *testing.T) {
145145
"header.0.source_port": "53",
146146
"rule_option.#": "1",
147147
}),
148+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*.rule_option.*", map[string]string{
149+
"keyword": "sid:1",
150+
}),
148151
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
149152
),
150153
},
@@ -432,6 +435,148 @@ func TestAccAwsNetworkFirewallRuleGroup_updateStatefulRule(t *testing.T) {
432435
"header.0.source_port": "1001",
433436
"rule_option.#": "1",
434437
}),
438+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*.rule_option.*", map[string]string{
439+
"keyword": "sid:1;rev:2",
440+
}),
441+
),
442+
},
443+
{
444+
ResourceName: resourceName,
445+
ImportState: true,
446+
ImportStateVerify: true,
447+
},
448+
},
449+
})
450+
}
451+
452+
func TestAccAwsNetworkFirewallRuleGroup_updateMultipleStatefulRules(t *testing.T) {
453+
rName := acctest.RandomWithPrefix("tf-acc-test")
454+
resourceName := "aws_networkfirewall_rule_group.test"
455+
456+
resource.ParallelTest(t, resource.TestCase{
457+
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAwsNetworkFirewall(t) },
458+
Providers: testAccProviders,
459+
CheckDestroy: testAccCheckAwsNetworkFirewallRuleGroupDestroy,
460+
Steps: []resource.TestStep{
461+
{
462+
Config: testAccNetworkFirewallRuleGroup_basic_statefulRule(rName),
463+
Check: resource.ComposeTestCheckFunc(
464+
testAccCheckAwsNetworkFirewallRuleGroupExists(resourceName),
465+
resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"),
466+
),
467+
},
468+
{
469+
Config: testAccNetworkFirewallRuleGroup_multipleStatefulRules(rName),
470+
Check: resource.ComposeTestCheckFunc(
471+
testAccCheckAwsNetworkFirewallRuleGroupExists(resourceName),
472+
resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "2"),
473+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{
474+
"action": networkfirewall.StatefulActionPass,
475+
"header.#": "1",
476+
"header.0.destination": "124.1.1.24/32",
477+
"header.0.destination_port": "53",
478+
"header.0.direction": networkfirewall.StatefulRuleDirectionAny,
479+
"header.0.protocol": networkfirewall.StatefulRuleProtocolTcp,
480+
"header.0.source": "1.2.3.4/32",
481+
"header.0.source_port": "53",
482+
"rule_option.#": "1",
483+
}),
484+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{
485+
"action": networkfirewall.StatefulActionAlert,
486+
"header.#": "1",
487+
"header.0.destination": networkfirewall.StatefulRuleDirectionAny,
488+
"header.0.destination_port": networkfirewall.StatefulRuleDirectionAny,
489+
"header.0.direction": networkfirewall.StatefulRuleDirectionAny,
490+
"header.0.protocol": networkfirewall.StatefulRuleProtocolIp,
491+
"header.0.source": networkfirewall.StatefulRuleDirectionAny,
492+
"header.0.source_port": networkfirewall.StatefulRuleDirectionAny,
493+
"rule_option.#": "1",
494+
}),
495+
),
496+
},
497+
{
498+
ResourceName: resourceName,
499+
ImportState: true,
500+
ImportStateVerify: true,
501+
},
502+
{
503+
Config: testAccNetworkFirewallRuleGroup_updateStatefulRule(rName),
504+
Check: resource.ComposeTestCheckFunc(
505+
testAccCheckAwsNetworkFirewallRuleGroupExists(resourceName),
506+
resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"),
507+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{
508+
"action": networkfirewall.StatefulActionDrop,
509+
"header.#": "1",
510+
"header.0.destination": "1.2.3.4/32",
511+
"header.0.destination_port": "1001",
512+
"header.0.direction": networkfirewall.StatefulRuleDirectionForward,
513+
"header.0.protocol": networkfirewall.StatefulRuleProtocolIp,
514+
"header.0.source": "124.1.1.24/32",
515+
"header.0.source_port": "1001",
516+
"rule_option.#": "1",
517+
}),
518+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*.rule_option.*", map[string]string{
519+
"keyword": "sid:1;rev:2",
520+
}),
521+
),
522+
},
523+
{
524+
ResourceName: resourceName,
525+
ImportState: true,
526+
ImportStateVerify: true,
527+
},
528+
},
529+
})
530+
}
531+
532+
// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/16868
533+
func TestAccAwsNetworkFirewallRuleGroup_statefulRule_action(t *testing.T) {
534+
rName := acctest.RandomWithPrefix("tf-acc-test")
535+
resourceName := "aws_networkfirewall_rule_group.test"
536+
537+
resource.ParallelTest(t, resource.TestCase{
538+
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAwsNetworkFirewall(t) },
539+
Providers: testAccProviders,
540+
CheckDestroy: testAccCheckAwsNetworkFirewallRuleGroupDestroy,
541+
Steps: []resource.TestStep{
542+
{
543+
Config: testAccNetworkFirewallRuleGroup_statefulRule_action(rName, networkfirewall.StatefulActionAlert),
544+
Check: resource.ComposeTestCheckFunc(
545+
testAccCheckAwsNetworkFirewallRuleGroupExists(resourceName),
546+
resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"),
547+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{
548+
"action": networkfirewall.StatefulActionAlert,
549+
}),
550+
),
551+
},
552+
{
553+
ResourceName: resourceName,
554+
ImportState: true,
555+
ImportStateVerify: true,
556+
},
557+
{
558+
Config: testAccNetworkFirewallRuleGroup_statefulRule_action(rName, networkfirewall.StatefulActionPass),
559+
Check: resource.ComposeTestCheckFunc(
560+
testAccCheckAwsNetworkFirewallRuleGroupExists(resourceName),
561+
resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"),
562+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{
563+
"action": networkfirewall.StatefulActionPass,
564+
}),
565+
),
566+
},
567+
{
568+
ResourceName: resourceName,
569+
ImportState: true,
570+
ImportStateVerify: true,
571+
},
572+
{
573+
Config: testAccNetworkFirewallRuleGroup_statefulRule_action(rName, networkfirewall.StatefulActionDrop),
574+
Check: resource.ComposeTestCheckFunc(
575+
testAccCheckAwsNetworkFirewallRuleGroupExists(resourceName),
576+
resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", "1"),
577+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule_group.0.rules_source.0.stateful_rule.*", map[string]string{
578+
"action": networkfirewall.StatefulActionDrop,
579+
}),
435580
),
436581
},
437582
{
@@ -794,6 +939,35 @@ resource "aws_networkfirewall_rule_group" "test" {
794939
`, rName)
795940
}
796941

942+
func testAccNetworkFirewallRuleGroup_statefulRule_action(rName, action string) string {
943+
return fmt.Sprintf(`
944+
resource "aws_networkfirewall_rule_group" "test" {
945+
capacity = 100
946+
name = %[1]q
947+
description = %[1]q
948+
type = "STATEFUL"
949+
rule_group {
950+
rules_source {
951+
stateful_rule {
952+
action = %q
953+
header {
954+
destination = "124.1.1.24/32"
955+
destination_port = 53
956+
direction = "ANY"
957+
protocol = "TCP"
958+
source = "1.2.3.4/32"
959+
source_port = 53
960+
}
961+
rule_option {
962+
keyword = "sid:1"
963+
}
964+
}
965+
}
966+
}
967+
}
968+
`, rName, action)
969+
}
970+
797971
func testAccNetworkFirewallRuleGroup_statefulRule_header(rName, dstPort, srcPort string) string {
798972
return fmt.Sprintf(`
799973
resource "aws_networkfirewall_rule_group" "test" {
@@ -841,10 +1015,52 @@ resource "aws_networkfirewall_rule_group" "test" {
8411015
source = "124.1.1.24/32"
8421016
source_port = 1001
8431017
}
1018+
rule_option {
1019+
keyword = "sid:1;rev:2"
1020+
}
1021+
}
1022+
}
1023+
}
1024+
}
1025+
`, rName)
1026+
}
1027+
1028+
func testAccNetworkFirewallRuleGroup_multipleStatefulRules(rName string) string {
1029+
return fmt.Sprintf(`
1030+
resource "aws_networkfirewall_rule_group" "test" {
1031+
capacity = 100
1032+
name = %[1]q
1033+
type = "STATEFUL"
1034+
rule_group {
1035+
rules_source {
1036+
stateful_rule {
1037+
action = "PASS"
1038+
header {
1039+
destination = "124.1.1.24/32"
1040+
destination_port = 53
1041+
direction = "ANY"
1042+
protocol = "TCP"
1043+
source = "1.2.3.4/32"
1044+
source_port = 53
1045+
}
8441046
rule_option {
8451047
keyword = "sid:1"
8461048
}
8471049
}
1050+
stateful_rule {
1051+
action = "ALERT"
1052+
header {
1053+
destination = "ANY"
1054+
destination_port = "ANY"
1055+
direction = "ANY"
1056+
protocol = "IP"
1057+
source = "ANY"
1058+
source_port = "ANY"
1059+
}
1060+
rule_option {
1061+
keyword = "sid:2"
1062+
}
1063+
}
8481064
}
8491065
}
8501066
}

0 commit comments

Comments
 (0)