Skip to content

Commit e2b1860

Browse files
authored
Merge pull request #25135 from teddylear/f-aws_networkfirewall_firewall_policy-add-stateless-rule-group-ref-override
feat: add override_action to aws_networkfirewall_firewall_policy
2 parents efe2563 + 9cbcfad commit e2b1860

File tree

7 files changed

+213
-122
lines changed

7 files changed

+213
-122
lines changed

.changelog/25135.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resource/aws_networkfirewall_firewall_policy: Add `firewall_policy.stateful_rule_group_reference.override` argument
3+
```

internal/service/networkfirewall/find.go

-14
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,6 @@ func FindFirewall(ctx context.Context, conn *networkfirewall.NetworkFirewall, ar
3535
return output, nil
3636
}
3737

38-
// FindFirewallPolicy returns the FirewallPolicyOutput from a call to DescribeFirewallPolicyWithContext
39-
// given the context and FindFirewallPolicy ARN.
40-
// Returns nil if the FindFirewallPolicy is not found.
41-
func FindFirewallPolicy(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeFirewallPolicyOutput, error) {
42-
input := &networkfirewall.DescribeFirewallPolicyInput{
43-
FirewallPolicyArn: aws.String(arn),
44-
}
45-
output, err := conn.DescribeFirewallPolicyWithContext(ctx, input)
46-
if err != nil {
47-
return nil, err
48-
}
49-
return output, nil
50-
}
51-
5238
// FindFirewallPolicyByNameAndARN returns the FirewallPolicyOutput from a call to DescribeFirewallPolicyWithContext
5339
// given the context and at least one of FirewallPolicyArn and FirewallPolicyName.
5440
func FindFirewallPolicyByNameAndARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, name string) (*networkfirewall.DescribeFirewallPolicyOutput, error) {

internal/service/networkfirewall/firewall_policy.go

+138-52
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package networkfirewall
22

33
import (
44
"context"
5-
"fmt"
65
"log"
76

87
"github.com/aws/aws-sdk-go/aws"
@@ -70,6 +69,20 @@ func ResourceFirewallPolicy() *schema.Resource {
7069
Optional: true,
7170
Elem: &schema.Resource{
7271
Schema: map[string]*schema.Schema{
72+
"override": {
73+
Type: schema.TypeList,
74+
MaxItems: 1,
75+
Optional: true,
76+
Elem: &schema.Resource{
77+
Schema: map[string]*schema.Schema{
78+
"action": {
79+
Type: schema.TypeString,
80+
Optional: true,
81+
ValidateFunc: validation.StringInSlice(networkfirewall.OverrideAction_Values(), false),
82+
},
83+
},
84+
},
85+
},
7386
"priority": {
7487
Type: schema.TypeInt,
7588
Optional: true,
@@ -143,6 +156,7 @@ func resourceFirewallPolicyCreate(ctx context.Context, d *schema.ResourceData, m
143156
conn := meta.(*conns.AWSClient).NetworkFirewallConn
144157
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
145158
tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{})))
159+
146160
name := d.Get("name").(string)
147161
input := &networkfirewall.CreateFirewallPolicyInput{
148162
FirewallPolicy: expandFirewallPolicy(d.Get("firewall_policy").([]interface{})),
@@ -157,14 +171,11 @@ func resourceFirewallPolicyCreate(ctx context.Context, d *schema.ResourceData, m
157171
input.Tags = Tags(tags.IgnoreAWS())
158172
}
159173

160-
log.Printf("[DEBUG] Creating NetworkFirewall Firewall Policy %s", name)
161-
174+
log.Printf("[DEBUG] Creating NetworkFirewall Firewall Policy: %s", input)
162175
output, err := conn.CreateFirewallPolicyWithContext(ctx, input)
176+
163177
if err != nil {
164-
return diag.FromErr(fmt.Errorf("error creating NetworkFirewall Firewall Policy (%s): %w", name, err))
165-
}
166-
if output == nil || output.FirewallPolicyResponse == nil {
167-
return diag.FromErr(fmt.Errorf("error creating NetworkFirewall Firewall Policy (%s): empty output", name))
178+
return diag.Errorf("creating NetworkFirewall Firewall Policy (%s): %s", name, err)
168179
}
169180

170181
d.SetId(aws.StringValue(output.FirewallPolicyResponse.FirewallPolicyArn))
@@ -177,23 +188,16 @@ func resourceFirewallPolicyRead(ctx context.Context, d *schema.ResourceData, met
177188
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
178189
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig
179190

180-
log.Printf("[DEBUG] Reading NetworkFirewall Firewall Policy %s", d.Id())
191+
output, err := FindFirewallPolicyByARN(ctx, conn, d.Id())
181192

182-
output, err := FindFirewallPolicy(ctx, conn, d.Id())
183-
if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) {
193+
if !d.IsNewResource() && tfresource.NotFound(err) {
184194
log.Printf("[WARN] NetworkFirewall Firewall Policy (%s) not found, removing from state", d.Id())
185195
d.SetId("")
186196
return nil
187197
}
188-
if err != nil {
189-
return diag.FromErr(fmt.Errorf("error reading NetworkFirewall Firewall Policy (%s): %w", d.Id(), err))
190-
}
191198

192-
if output == nil {
193-
return diag.FromErr(fmt.Errorf("error reading NetworkFirewall Firewall Policy (%s): empty output", d.Id()))
194-
}
195-
if output.FirewallPolicyResponse == nil {
196-
return diag.FromErr(fmt.Errorf("error reading NetworkFirewall Firewall Policy (%s): empty output.FirewallPolicyResponse", d.Id()))
199+
if err != nil {
200+
return diag.Errorf("reading NetworkFirewall Firewall Policy (%s): %s", d.Id(), err)
197201
}
198202

199203
resp := output.FirewallPolicyResponse
@@ -205,49 +209,51 @@ func resourceFirewallPolicyRead(ctx context.Context, d *schema.ResourceData, met
205209
d.Set("update_token", output.UpdateToken)
206210

207211
if err := d.Set("firewall_policy", flattenFirewallPolicy(policy)); err != nil {
208-
return diag.FromErr(fmt.Errorf("error setting firewall_policy: %w", err))
212+
return diag.Errorf("setting firewall_policy: %s", err)
209213
}
210214

211215
tags := KeyValueTags(resp.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig)
212216

213217
//lintignore:AWSR002
214218
if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
215-
return diag.FromErr(fmt.Errorf("error setting tags: %w", err))
219+
return diag.Errorf("setting tags: %s", err)
216220
}
217221

218222
if err := d.Set("tags_all", tags.Map()); err != nil {
219-
return diag.FromErr(fmt.Errorf("error setting tags_all: %w", err))
223+
return diag.Errorf("setting tags_all: %s", err)
220224
}
221225

222226
return nil
223227
}
224228

225229
func resourceFirewallPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
226230
conn := meta.(*conns.AWSClient).NetworkFirewallConn
227-
arn := d.Id()
228-
229-
log.Printf("[DEBUG] Updating NetworkFirewall Firewall Policy %s", arn)
230231

231232
if d.HasChanges("description", "firewall_policy") {
232233
input := &networkfirewall.UpdateFirewallPolicyInput{
233234
FirewallPolicy: expandFirewallPolicy(d.Get("firewall_policy").([]interface{})),
234-
FirewallPolicyArn: aws.String(arn),
235+
FirewallPolicyArn: aws.String(d.Id()),
235236
UpdateToken: aws.String(d.Get("update_token").(string)),
236237
}
238+
237239
// Only pass non-empty description values, else API request returns an InternalServiceError
238240
if v, ok := d.GetOk("description"); ok {
239241
input.Description = aws.String(v.(string))
240242
}
243+
244+
log.Printf("[DEBUG] Updating NetworkFirewall Firewall Policy: %s", input)
241245
_, err := conn.UpdateFirewallPolicyWithContext(ctx, input)
246+
242247
if err != nil {
243-
return diag.FromErr(fmt.Errorf("error updating NetworkFirewall Firewall Policy (%s) firewall_policy: %w", arn, err))
248+
return diag.Errorf("updating NetworkFirewall Firewall Policy (%s): %s", d.Id(), err)
244249
}
245250
}
246251

247252
if d.HasChange("tags_all") {
248253
o, n := d.GetChange("tags_all")
249-
if err := UpdateTags(conn, arn, o, n); err != nil {
250-
return diag.FromErr(fmt.Errorf("error updating NetworkFirewall Firewall Policy (%s) tags: %w", arn, err))
254+
255+
if err := UpdateTagsWithContext(ctx, conn, d.Id(), o, n); err != nil {
256+
return diag.Errorf("updating NetworkFirewall Firewall Policy (%s) tags: %s", d.Id(), err)
251257
}
252258
}
253259

@@ -257,42 +263,84 @@ func resourceFirewallPolicyUpdate(ctx context.Context, d *schema.ResourceData, m
257263
func resourceFirewallPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
258264
conn := meta.(*conns.AWSClient).NetworkFirewallConn
259265

260-
log.Printf("[DEBUG] Deleting NetworkFirewall Firewall Policy %s", d.Id())
266+
log.Printf("[DEBUG] Deleting NetworkFirewall Firewall Policy: %s", d.Id())
267+
_, err := tfresource.RetryWhenAWSErrMessageContainsContext(ctx, firewallPolicyTimeout, func() (interface{}, error) {
268+
return conn.DeleteFirewallPolicyWithContext(ctx, &networkfirewall.DeleteFirewallPolicyInput{
269+
FirewallPolicyArn: aws.String(d.Id()),
270+
})
271+
}, networkfirewall.ErrCodeInvalidOperationException, "Unable to delete the object because it is still in use")
261272

262-
input := &networkfirewall.DeleteFirewallPolicyInput{
263-
FirewallPolicyArn: aws.String(d.Id()),
273+
if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) {
274+
return nil
264275
}
265276

266-
err := resource.RetryContext(ctx, firewallPolicyTimeout, func() *resource.RetryError {
267-
_, err := conn.DeleteFirewallPolicyWithContext(ctx, input)
268-
if err != nil {
269-
if tfawserr.ErrMessageContains(err, networkfirewall.ErrCodeInvalidOperationException, "Unable to delete the object because it is still in use") {
270-
return resource.RetryableError(err)
271-
}
272-
return resource.NonRetryableError(err)
273-
}
274-
return nil
275-
})
277+
if err != nil {
278+
return diag.Errorf("deleting NetworkFirewall Firewall Policy (%s): %s", d.Id(), err)
279+
}
276280

277-
if tfresource.TimedOut(err) {
278-
_, err = conn.DeleteFirewallPolicyWithContext(ctx, input)
281+
if _, err := waitFirewallPolicyDeleted(ctx, conn, d.Id()); err != nil {
282+
return diag.Errorf("waiting for NetworkFirewall Firewall Policy (%s) delete: %s", d.Id(), err)
279283
}
280284

281-
if err != nil {
282-
if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) {
283-
return nil
285+
return nil
286+
}
287+
288+
func FindFirewallPolicyByARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeFirewallPolicyOutput, error) {
289+
input := &networkfirewall.DescribeFirewallPolicyInput{
290+
FirewallPolicyArn: aws.String(arn),
291+
}
292+
293+
output, err := conn.DescribeFirewallPolicyWithContext(ctx, input)
294+
295+
if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) {
296+
return nil, &resource.NotFoundError{
297+
LastError: err,
298+
LastRequest: input,
284299
}
285-
return diag.FromErr(fmt.Errorf("error deleting NetworkFirewall Firewall Policy (%s): %w", d.Id(), err))
286300
}
287301

288-
if _, err := waitFirewallPolicyDeleted(ctx, conn, d.Id()); err != nil {
289-
if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) {
290-
return nil
302+
if err != nil {
303+
return nil, err
304+
}
305+
306+
if output == nil || output.FirewallPolicyResponse == nil {
307+
return nil, tfresource.NewEmptyResultError(input)
308+
}
309+
310+
return output, nil
311+
}
312+
313+
func statusFirewallPolicy(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) resource.StateRefreshFunc {
314+
return func() (interface{}, string, error) {
315+
output, err := FindFirewallPolicyByARN(ctx, conn, arn)
316+
317+
if tfresource.NotFound(err) {
318+
return nil, "", nil
291319
}
292-
return diag.FromErr(fmt.Errorf("error waiting for NetworkFirewall Firewall Policy (%s) to delete: %w", d.Id(), err))
320+
321+
if err != nil {
322+
return nil, "", err
323+
}
324+
325+
return output, aws.StringValue(output.FirewallPolicyResponse.FirewallPolicyStatus), nil
293326
}
327+
}
294328

295-
return nil
329+
func waitFirewallPolicyDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeFirewallPolicyOutput, error) {
330+
stateConf := &resource.StateChangeConf{
331+
Pending: []string{networkfirewall.ResourceStatusDeleting},
332+
Target: []string{},
333+
Refresh: statusFirewallPolicy(ctx, conn, arn),
334+
Timeout: firewallPolicyTimeout,
335+
}
336+
337+
outputRaw, err := stateConf.WaitForStateContext(ctx)
338+
339+
if v, ok := outputRaw.(*networkfirewall.DescribeFirewallPolicyOutput); ok {
340+
return v, err
341+
}
342+
343+
return nil, err
296344
}
297345

298346
func expandStatefulEngineOptions(l []interface{}) *networkfirewall.StatefulEngineOptions {
@@ -310,6 +358,21 @@ func expandStatefulEngineOptions(l []interface{}) *networkfirewall.StatefulEngin
310358
return options
311359
}
312360

361+
func expandStatefulRuleGroupOverride(l []interface{}) *networkfirewall.StatefulRuleGroupOverride {
362+
if len(l) == 0 || l[0] == nil {
363+
return nil
364+
}
365+
366+
lRaw := l[0].(map[string]interface{})
367+
override := &networkfirewall.StatefulRuleGroupOverride{}
368+
369+
if v, ok := lRaw["action"].(string); ok && v != "" {
370+
override.SetAction(v)
371+
}
372+
373+
return override
374+
}
375+
313376
func expandStatefulRuleGroupReferences(l []interface{}) []*networkfirewall.StatefulRuleGroupReference {
314377
if len(l) == 0 || l[0] == nil {
315378
return nil
@@ -320,15 +383,22 @@ func expandStatefulRuleGroupReferences(l []interface{}) []*networkfirewall.State
320383
if !ok {
321384
continue
322385
}
386+
323387
reference := &networkfirewall.StatefulRuleGroupReference{}
324388
if v, ok := tfMap["priority"].(int); ok && v > 0 {
325389
reference.Priority = aws.Int64(int64(v))
326390
}
327391
if v, ok := tfMap["resource_arn"].(string); ok && v != "" {
328392
reference.ResourceArn = aws.String(v)
329393
}
394+
395+
if v, ok := tfMap["override"].([]interface{}); ok && len(v) > 0 {
396+
reference.Override = expandStatefulRuleGroupOverride(v)
397+
}
398+
330399
references = append(references, reference)
331400
}
401+
332402
return references
333403
}
334404

@@ -429,6 +499,18 @@ func flattenStatefulEngineOptions(options *networkfirewall.StatefulEngineOptions
429499
return []interface{}{m}
430500
}
431501

502+
func flattenStatefulRuleGroupOverride(override *networkfirewall.StatefulRuleGroupOverride) []interface{} {
503+
if override == nil {
504+
return []interface{}{}
505+
}
506+
507+
m := map[string]interface{}{
508+
"action": aws.StringValue(override.Action),
509+
}
510+
511+
return []interface{}{m}
512+
}
513+
432514
func flattenPolicyStatefulRuleGroupReference(l []*networkfirewall.StatefulRuleGroupReference) []interface{} {
433515
references := make([]interface{}, 0, len(l))
434516
for _, ref := range l {
@@ -438,6 +520,10 @@ func flattenPolicyStatefulRuleGroupReference(l []*networkfirewall.StatefulRuleGr
438520
if ref.Priority != nil {
439521
reference["priority"] = int(aws.Int64Value(ref.Priority))
440522
}
523+
if ref.Override != nil {
524+
reference["override"] = flattenStatefulRuleGroupOverride(ref.Override)
525+
}
526+
441527
references = append(references, reference)
442528
}
443529

0 commit comments

Comments
 (0)