Search code examples
google-cloud-platformterraformterraform-provider-gcp

Terraform dynamic block and list(object) error in gcp


I have a root module, variable module and child module. I am receiving: The given value is not suitable for child module variable "rule" defined at .. .. element 0: attribute "match" • attribute "expr": element 0: attribute "expression " : element 0: object required . element 0:

Root module:

resource "google_compute_security_policy" "policy" {
  project = var.gcp_project_id
  name = var.waf_name
  #creating a dynamic rule
  dynamic "rule" {
    for_each = var.rule
    content {
      action = rule.value.action
      priority = rule.value.priority
      dynamic "match" {
        for_each = rule.value.match
        content {
          dynamic "expr" {
            for_each = match.value.expr
            content{
              dynamic "expression" {
                for_each = expr.value.expression
                content{
                  evaluatePreconfiguredExpr = expression.value.evaluatePreconfiguredExpr
                }
              }
            }
           }
        }  
      }
    }
  }

Variable Module(variable.tf):

 variable "rule" {
  description = "WAF rule 1"
  type        = list(object(
    {
      action = list(string)
      priority = list(string)
      match = list(object(
        {
          expr = list(object(
            {
              expression = list(object(
                {
                evaluatePreconfiguredExpr= list(string)
                }
              ))
            }
          ))
        }
      ))
    }
  )) 
}

Child module(main.tf or input module)

rule =[{
action   = ["deny(403)"]
priority = ["1000"]
match = [{
  expr = [{
    expression = [<<EOF
    evaluatePreconfiguredExpr('xss-stable', ['owasp-crs-v030001-id941340-xss',
      'owasp-crs-v030001-id941130-xss',
      'owasp-crs-v030001-id941170-xss',
      'owasp-crs-v030001-id941330-xss',
    ]
    )
    EOF
    ]
}]

}] The reference site for this one is: https://github.com/DeimosCloud/terraform-google-waf/blob/master/main.tf


Solution

  • The expanded rule parameter doesn't match the provider spec here so it's being rejected.
    For example, you're passing a list of objects for the match parameter but the spec requires a single object.
    Tweaking the files as so works for me:

    root.tf:

    resource "google_compute_security_policy" "policy" {
      project = var.gcp_project_id
      name    = var.waf_name
      #creating a dynamic rule
      dynamic "rule" {
        for_each = var.rule
        content {
          action   = rule.value.action
          priority = rule.value.priority
          dynamic "match" {
            for_each = rule.value.match
            content {
              dynamic "expr" {
                for_each = rule.value.match
                content {
                  expression = expr.value.expression
                }
              }
            }
          }
        }
      }
    }
    

    variable.tf:

    variable "rule" {
      description = "WAF rule 1"
      type = list(object(
        {
          action   = string
          priority = string
          match = object(
            {
              expr = object(
                {
                  expression = string
                }
              )
            }
          )
        }
        )
      )
    }
    

    child.tf:

    rule = [{
        action   = "deny(403)"
        priority = "1000"
        match = {
          expr = {
            expression = <<EOF
        evaluatePreconfiguredExpr('xss-stable', ['owasp-crs-v030001-id941340-xss',
          'owasp-crs-v030001-id941130-xss',
          'owasp-crs-v030001-id941170-xss',
          'owasp-crs-v030001-id941330-xss',
        ]
        )
        EOF
          }
        }
      }]
    

    This produces the following plan:

      + resource "google_compute_security_policy" "policy" {
          + fingerprint = (known after apply)
          + id          = (known after apply)
          + name        = "test"
          + project     = "something"
          + self_link   = (known after apply)
    
          + rule {
              + action   = "deny(403)"
              + preview  = (known after apply)
              + priority = 1000
    
              + match {
    
                  + expr {
                      + expression = <<-EOT
                                evaluatePreconfiguredExpr('xss-stable', ['owasp-crs-v030001-id941340-xss',
                                  'owasp-crs-v030001-id941130-xss',
                                  'owasp-crs-v030001-id941170-xss',
                                  'owasp-crs-v030001-id941330-xss',
                                ]
                                )
                        EOT
                    }
                }
            }
        }