Home > Mobile >  Create waf rule if environment is nonprod Terraform
Create waf rule if environment is nonprod Terraform

Time:10-15

I'm trying to create an IP whitelist in nonprod for load testing, the WAF is dynamically created in prod and nonprod based on the envname/envtype:

resource "aws_waf_ipset" "pwa_cloudfront_ip_restricted" {
  name = "${var.envname}-pwa-cloudfront-whitelist"
  dynamic "ip_set_descriptors" {
    for_each = var.cloudfront_ip_restricted_waf_cidr_whitelist
    content {
      type  = ip_set_descriptors.value.type
      value = ip_set_descriptors.value.value
    }
  }
}

resource "aws_waf_rule" "pwa_cloudfront_ip_restricted" {
  depends_on  = [aws_waf_ipset.pwa_cloudfront_ip_restricted]
  name        = "${var.envname}-pwa-cloudfront-whitelist"
  metric_name = "${var.envname}PWACloudfrontWhitelist"

  predicates {
    data_id = aws_waf_ipset.pwa_cloudfront_ip_restricted.id
    negated = false
    type    = "IPMatch"
  }
}

resource "aws_waf_ipset" "pwa_cloudfront_ip_restricted_load_testing" {
  name  = "${var.envname}-pwa-cloudfront-whitelist_load_testing"
  count = var.envtype == "nonprod" ? 1 : 0
  dynamic "ip_set_descriptors" {
    for_each = var.cloudfront_ip_restricted_waf_cidr_whitelist_load_testing
    content {
      type  = ip_set_descriptors.value.type
      value = ip_set_descriptors.value.value
    }
  }
}

resource "aws_waf_rule" "pwa_cloudfront_ip_restricted_load_testing" {
  depends_on  = [aws_waf_ipset.pwa_cloudfront_ip_restricted_load_testing]
  count = var.envtype == "nonprod" ? 1 : 0
  name        = "${var.envname}-pwa-cloudfront-whitelist-load_testing"
  metric_name = "${var.envname}PWACloudfrontWhitelistload_testing"

  predicates {
    data_id = aws_waf_ipset.pwa_cloudfront_ip_restricted_load_testing[count.index].id
    negated = false
    type    = "IPMatch"
  }
}

resource "aws_waf_web_acl" "pwa_cloudfront_ip_restricted" {
  name        = "${var.envname}-pwa-cloudfront-whitelist"
  metric_name = "${var.envname}PWACloudfrontWhitelist"

  default_action {
    type = "BLOCK"
  }

  rules {
    action {
      type = "ALLOW"
    }

    priority = 1
    rule_id  = aws_waf_rule.pwa_cloudfront_ip_restricted.id
    type     = "REGULAR"
  }

    rules {
    action {
      type = "ALLOW"
    }

    priority = 2
    rule_id  = aws_waf_rule.pwa_cloudfront_ip_restricted_load_testing.id
    type     = "REGULAR"
  }
}

The second rules block throws and error in the terraform plan:

Error: Missing resource instance key

  on waf.tf line 73, in resource "aws_waf_web_acl" "pwa_cloudfront_ip_restricted":
  73:     rule_id  = aws_waf_rule.pwa_cloudfront_ip_restricted_load_testing.id

Because aws_waf_rule.pwa_cloudfront_ip_restricted_load_testing has "count" set,
its attributes must be accessed on specific instances.

For example, to correlate with indices of a referring resource, use:
    aws_waf_rule.pwa_cloudfront_ip_restricted_load_testing[count.index]

However if I add [count.index] :

Error: Reference to "count" in non-counted context

  on waf.tf line 73, in resource "aws_waf_web_acl" "pwa_cloudfront_ip_restricted":
  73:     rule_id  = aws_waf_rule.pwa_cloudfront_ip_restricted_load_testing[count.index].id

The "count" object can only be used in "module", "resource", and "data"
blocks, and only when the "count" argument is set.

Is there a way to do this that doesn't use the count param? Or am I missing something in the way that I am using it?

CodePudding user response:

Since there is difference between the prod and non-prod environment, the way this should be tackled is by using dynamic [1] and for_each meta-argument [2]:

resource "aws_waf_web_acl" "pwa_cloudfront_ip_restricted" {
  name        = "${var.envname}-pwa-cloudfront-whitelist"
  metric_name = "${var.envname}PWACloudfrontWhitelist"

  default_action {
    type = "BLOCK"
  }

  dynamic "rules" {
    for_each = var.envtype == "nonprod" ? [1] : []
    content {
      action {
        type = "ALLOW"
     }
      priority = 1
      rule_id  = aws_waf_rule.pwa_cloudfront_ip_restricted[0].id
      type     = "REGULAR"
    }
  }

  dynamic "rules" {
    for_each = var.envtype == "nonprod" ? [1] : []
    content {
      action {
        type = "ALLOW"
      }
      priority = 2
      rule_id  = aws_waf_rule.pwa_cloudfront_ip_restricted_load_testing[0].id
      type     = "REGULAR"
    }
  }
}

[1] https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks

[2] https://developer.hashicorp.com/terraform/language/expressions/for

  • Related