terraform-provider-aws icon indicating copy to clipboard operation
terraform-provider-aws copied to clipboard

aws_wafv2_web_acl resource dependency wrong way around

Open waqarkhan3389 opened this issue 4 years ago • 13 comments

Terraform Version: 0.13.5 AWS provider version: v3.27.0 I have the following TF, when I run this after having run it before with a list of IP addresses it tries to delete the IP set before it removes the rule which was created including that IP set. I am unsure if this is due to me adding the for_each and making it a dynamic block though. In that case which config is correct? It results in the following error:

Error deleting WAFv2 IPSet: WAFAssociatedItemException: AWS WAF couldn’t perform the operation because your resource is being used by another resource or it’s associated with another resource.

resource "aws_wafv2_web_acl" "waf" {
  name        = "${local.name}-${var.environment}-WAF"
  description = "${local.name}-${var.environment}-WAF"
  scope       = "REGIONAL"

  default_action {
    allow {}
  }

  dynamic "rule" {
    for_each = var.waf_whitelist_ips != null ? [1] : []
    content {

           name     = "WAFWhitelistIPs"
           priority = 0

           action {
               allow {}
            }

           statement {
              
                  ip_set_reference_statement {
                   arn = aws_wafv2_ip_set.ipset[0].arn
                }
            }

           visibility_config {
               cloudwatch_metrics_enabled = true
               metric_name                = "${local.name}-${var.environment}-WHITELISTIps"
               sampled_requests_enabled   = true
            }
        }
  }

  rule {
    name     = "AWSManagedIpReputation"
    priority = 1

    override_action {
      none {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesAmazonIpReputationList"
        vendor_name = "AWS"
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "${local.name}-${var.environment}-WAF-IP-Bad-Rep"
      sampled_requests_enabled   = true
    }
  }

// WAF whitelist IP set
resource "aws_wafv2_ip_set" "ipset" {
  count = var.waf_whitelist_ips != null ? 1 : 0
  name = "WAFWhitelistIPs"
  scope = "REGIONAL"
  ip_address_version = "IPV4"
  addresses = var.waf_whitelist_ips
}

waqarkhan3389 avatar Feb 12 '21 19:02 waqarkhan3389

Hi @waqark3389 , thank you for creating this issue. I'm unable to reproduce on my end unfortunately with the complete config you've provided, the dynamic block seems to work as I'd expect. Would you be able to provide any debug logs to further investigate the error?

anGie44 avatar Feb 16 '21 20:02 anGie44

I facing the same issue. The problem isn't with dynamic block here. Instead, when you will set waf_whitelist_ips to null it won't be able to delete the IP set as it is being used within the rule. hence, until the rule is removed from the rule IP set cannot be deleted

paliwalvimal avatar Mar 25 '21 07:03 paliwalvimal

We are facing this issue when trying to remove a rule that is referencing an ip set. It first tries to destroy the IP set but that does not work because it is still being referenced in the web acl rule. The actual behaviour should be to first adjust the web acl and delete the necessary rule and then destroying the ip set. Also settings an explicit depends_on in the web acl to the ip set does not solve the problem.

ZF-fredericvanlinthoudt avatar May 05 '21 14:05 ZF-fredericvanlinthoudt

To confirm, I have the same issue when I try and delete an ip ruleset it fails because it tries to delete it first without removing the ruleset first.

boxrick avatar Jun 08 '21 13:06 boxrick

Hello! I am facing with the same issue (Terraform v0.15.1 + provider registry.terraform.io/hashicorp/aws v3.37.0). In order to reproduce:

  1. Create e.g., 2 aws_wafv2_ip_set or aws_wafv2_regex_pattern_set and link in aws_wafv2_web_acl via rule. 1 acl with 2 rules.
  2. Remove one aws_wafv2_ip_set or aws_wafv2_regex_pattern_set and the related rule.
  3. Create plan: it should show that 1 rule and e.g., 1 ip set to be removed with the acl updated in place.

Result: Terraform starts to delete aws_wafv2_ip_set first not the rule which is not possible. Expected: Terraform should start to remove rule first.

The issue is the same if the resource name changes and acl rule to be updated. The lifecycle does not have an impact.

gergelykovacs avatar Jun 14 '21 15:06 gergelykovacs

Hello, I had similar issue when aws_wafv2_regex_pattern_set couldn't be destroyed as it was used by aws_wafv2_web_acl. I added depends_on = [aws_wafv2_regex_pattern_set.custom_allow_regex] to aws_wafv2_web_acl resource and it still did not help exactly like in cases described above.

What DID help was to add

lifecycle {
    create_before_destroy = true
  }

to both aws_wafv2_regex_pattern_set and aws_wafv2_web_acl resources so now terraform is firstly create new aws_wafv2_regex_pattern_set, update it in aws_wafv2_web_acl and then it is free to destroy previous aws_wafv2_regex_pattern_set resource. Hope it will help you :)

Pola93 avatar Jun 28 '21 12:06 Pola93

We're running into this problem too with 0.15.x. Does anyone know if it has been fixed in 1.x?

relausen-tlg avatar Sep 06 '21 15:09 relausen-tlg

Hello, I had similar issue when aws_wafv2_regex_pattern_set couldn't be destroyed as it was used by aws_wafv2_web_acl. I added depends_on = [aws_wafv2_regex_pattern_set.custom_allow_regex] to aws_wafv2_web_acl resource and it still did not help exactly like in cases described above.

What DID help was to add

lifecycle {
    create_before_destroy = true
  }

to both aws_wafv2_regex_pattern_set and aws_wafv2_web_acl resources so now terraform is firstly create new aws_wafv2_regex_pattern_set, update it in aws_wafv2_web_acl and then it is free to destroy previous aws_wafv2_regex_pattern_set resource. Hope it will help you :)

It worked for me. Thanks

phuocntsts avatar Oct 22 '21 11:10 phuocntsts

@phuocntsts what version of the provider are you using? Original issue was filed with v3.27.0. Latest is v3.63.0. v3.47.0 was latest release when @Pola93 claimed the fix you're using. So has this been fixed since v3.47.0? Possibly fixed by #17876 that was included in release v3.33.0

jmeridth avatar Oct 22 '21 14:10 jmeridth

@phuocntsts what version of the provider are you using? Original issue was filed with v3.27.0. Latest is v3.63.0. v3.47.0 was latest release when @Pola93 claimed the fix you're using. So has this been fixed since v3.47.0? Possibly fixed by #17876 that was included in release v3.33.0

Hi @jmeridth , my current version is v3.62.0. today I get the same error and it worked for me when I try with "lifecycle".

phuocntsts avatar Oct 22 '21 15:10 phuocntsts

Hi, I also solved exactly this problem using "lifecycle" block. I was trying to modify ip set, regex pattern set and rule groups. Thank you.

lifecycle {
    create_before_destroy = true
  }

Shuvo-Hoque avatar Feb 24 '22 06:02 Shuvo-Hoque

I tried to use the lifecycle block but Terraform expectedly failed to create a WAF rule group (in my case) because of the already existing one. We use Terraform v1.0.0 and terraform-provider-aws v4.15.1.

RomanDanyk avatar Jul 18 '22 12:07 RomanDanyk

Disregard - I can't delete this comment

nickeeromo avatar Aug 10 '22 15:08 nickeeromo

We are hitting this too, in our case the create_before_destroy does not work because the existing waf is just being updated not replaced

To workaround this we had to do a two step decomm First update the waf to remove the rules that no longer use the other resources. Then apply that Then we can decome the regex/ipset resources in a second apply

lorelei-rupp-imprivata avatar Sep 27 '22 16:09 lorelei-rupp-imprivata

Still a problem when updating an existing WAF with Terraform 1.3.2 and AWS provider 4.56.0.

Lifecycle block did not help.

azt3k avatar Mar 09 '23 19:03 azt3k

Still having this problem :/

olivatooo avatar Apr 06 '23 20:04 olivatooo

It is still a problem when updating WAF: Terraform v1.4.6 and AWS provider 4.66.1

popsicleslayer avatar May 08 '23 09:05 popsicleslayer

For anyone hitting this, and neither being able to fix it with the create_before_destroy configuration nor being able to temporarily remove resources to make TF happy: Another option that now worked for me is to manually remove the resources that TF wants to delete from the state (using terraform state rm), let TF do the other updates, and then manually remove the resources using the AWS console/CLI.

ankon avatar Aug 30 '23 09:08 ankon

TF still can't handle this simple dependency correctly, failing horribly as an IaC tool (manual workarounds, lol). I can't wait for this issue to turn 3 year-old (I collect TF old issues that never get fixed because they are deeply rooted into conceptions flaws. That's why I'm in such a good mood).

fdutheil avatar Sep 06 '23 15:09 fdutheil

where should we add in the waf resource or rule resource ?

lifecycle {
    create_before_destroy = true
  }

as I create dynamic rules like this

resource "aws_wafv2_ip_set" "waf_ip_sets" {
 for_each           = local.clientIpSets
 name               = "${var.infra_env}-${lower(each.key)}-ips"
 ip_address_version = each.value.version
 addresses          = each.value.addresses
 description        = each.value.description
 scope              = "REGIONAL"
 tags = {
   CreatedBy = "Manash"
   ManagedBy = "terraform"
   infra_env = var.infra_env
 }

}```

msonowal avatar Dec 05 '23 14:12 msonowal

where should we add in the waf resource or rule resource ?

lifecycle {
    create_before_destroy = true
  }

as I create dynamic rules like this

resource "aws_wafv2_ip_set" "waf_ip_sets" {
 for_each           = local.clientIpSets
 name               = "${var.infra_env}-${lower(each.key)}-ips"
 ip_address_version = each.value.version
 addresses          = each.value.addresses
 description        = each.value.description
 scope              = "REGIONAL"
 tags = {
   CreatedBy = "Manash"
   ManagedBy = "terraform"
   infra_env = var.infra_env
 }

}```

As it is mentioned in the comment

lifecycle {
    create_before_destroy = true
}

should be added to both resources

  • aws_wafv2_web_acl
  • aws_wafv2_ip_set

You can try this step by step. First add to aws_wafv2_web_acl and if not fixed, add it to aws_wafv2_ip_set and check.

air3ijai avatar Dec 06 '23 14:12 air3ijai

Adding a lifecycle does not fix the issue.

lifecycle {
    create_before_destroy = true
}

zamirTo1 avatar Feb 01 '24 19:02 zamirTo1

What is your case and components versions?

air3ijai avatar Feb 01 '24 19:02 air3ijai

We are also hitting this scenario, but in our case it is an IPSet referenced in a RuleGroup. Sadly using lifecycle/depends_on blocks doesn't work because the RuleGroup is just updated, not recreated. Not to mention that RuleGroups themselves are referenced in web ACLs, so forcing recreation wouldn't work either.

It would be greatly appreciated if this was addressed officially, even if the fix is simply a well-defined workaround instead of code changes in this provider. Web ACLs are critical pieces of security infrastructure, thus it's very important to have the ability to remove IPSets (and thus their references) from infrastructure swiftly and confidently

edit: we are on hashicorp/aws v5.22.0, Terraform ~>1.6

ckreiling avatar Feb 02 '24 05:02 ckreiling

Hello, I had similar issue when aws_wafv2_regex_pattern_set couldn't be destroyed as it was used by aws_wafv2_web_acl. I added depends_on = [aws_wafv2_regex_pattern_set.custom_allow_regex] to aws_wafv2_web_acl resource and it still did not help exactly like in cases described above.

What DID help was to add

lifecycle {
    create_before_destroy = true
  }

to both aws_wafv2_regex_pattern_set and aws_wafv2_web_acl resources so now terraform is firstly create new aws_wafv2_regex_pattern_set, update it in aws_wafv2_web_acl and then it is free to destroy previous aws_wafv2_regex_pattern_set resource. Hope it will help you :)

Thank you @Pola93. This worked for me. To provide more context for my case: terraform version: 1.4.6 aws provider version: 5.15.0

I was renaming the aws_wafv2_ip_set and aws_wafv2_rule_group resources previously created. So terraform apply was destroying them before updating the associated aws_wafv2_web_acl rules. To fix this dependency, I only added the lifecycle { create_before_destroy = true } block to the aws_wafv2_ip_set and aws_wafv2_rule_group resource blocks and it worked on terraform apply.

Note: I did not have to add the lifecycle { create_before_destroy = true } block to aws_wafv2_web_acl.

ashwinSALGAOCAR avatar Mar 20 '24 06:03 ashwinSALGAOCAR