terraformamazon-cloudfrontamazon-waf

error updating CloudFront Distribution (E32RNPFGEUHQ6J): InvalidWebACLId: Web ACL is not accessible by the requester


I am using terraform to create a web-acl in aws and want to associate that web-acl with CloudFront distribution.

So, here's how my code looks like:

provider "aws" {
  alias  = "east1"
  region = "us-east-1"
}

# -------------------------------------------
# -------------------------------------------
# Cloud Front
module "front_end_cloudfront" {
  source = "./modules/front-end/CF"

  # CF_ALIASES = ["terraformer-frontend.dev.effi.com.au"]  
  CF_LAMBDA_ARN = module.frontend_lambda.cf_lambda_qualified_arn
  CF_BUCKET_DOMAIN_NAME = module.front_end_bucket.website_endpoint
  CF_BUCKET_ORIGIN_ID = module.front_end_bucket.website_domain
  CF_TAGS_LIST = { "Name" : "terraformer-front-end-cloudfrontv2" }
  CF_CERTFICATE_ARN = var.CLOUDFRONT_US_EAST_1_ACM_ARN
  # WEB_ACL = module.waf.web_acl_id
  WEB_ACL = module.waf_cf.web_acl_id

  depends_on = [module.waf_cf]
}



# -------------------------------------------
# -------------------------------------------
# WAF for CF
module "waf_cf" {
  source = "./modules/waf"

  providers = {
    aws = aws.east1
  }  

  WAF_NAME  = "terraform-web-acl-cf"
  WAF_DESCRIPTION = "terraform web acl-cf"
  WAF_SCOPE = "CLOUDFRONT"
  WAF_RULE_NAME_1 = "AWSManagedRulesCommonRuleSet"
  WAF_RULE_NAME_2 = "AWSManagedRulesAmazonIpReputationList"
  WAF_RULE_NAME_3 = "AWSManagedRulesLinuxRuleSet"
  WAF_RULE_NAME_4 = "AWSManagedRulesKnownBadInputsRuleSet"
  WAF_VENDOR = "AWS"
  WAF_METRIC_1 = "aws-waf-logs-terraformer-metric"
  WAF_METRIC_2 = "aws-waf-logs-terraformer-metric"
  WAF_METRIC_3 = "aws-waf-logs-terraformer-metric"
  WAF_METRIC_4 = "aws-waf-logs-terraformer-metric"
  WAF_TAG_LIST = {
    "Tag1" : "Name"
    "Tag2" : "terraformer-rule-cf"
  }
  WAF_METRIC = "aws-waf-logs-friendly-metric-name"
  CLOUDWATCH_METRICS_ENABLED = false
  SAMPLE_REQUESTS_ENABLED = false
}

These are terraform modules I have wrote, the specific resource files for above modules are below respectively.

# CF
resource "aws_cloudfront_distribution" "aws_cloudfront_distribution" {
  # aliases = var.CF_ALIASES

  default_cache_behavior {
    allowed_methods = ["GET", "HEAD"]
    cached_methods  = ["GET", "HEAD"]
    compress        = "true"
    default_ttl     = "0"

    forwarded_values {
      cookies {
        forward = "none"
      }

      query_string = "false"
    }

    lambda_function_association {
      event_type   = "origin-response"
      include_body = "false"
      lambda_arn   = var.CF_LAMBDA_ARN
    }

    max_ttl                = "0"
    min_ttl                = "0"
    smooth_streaming       = "false"
    target_origin_id       = var.CF_BUCKET_ORIGIN_ID
    viewer_protocol_policy = "redirect-to-https"
  }

  enabled         = "true"
  http_version    = "http2"
  is_ipv6_enabled = "true"

  origin {
    custom_origin_config {
      http_port                = "80"
      https_port               = "443"
      origin_keepalive_timeout = "5"
      origin_protocol_policy   = "http-only"
      origin_read_timeout      = "30"
      origin_ssl_protocols     = ["TLSv1", "TLSv1.1", "TLSv1.2"]
    }

    domain_name = var.CF_BUCKET_DOMAIN_NAME
    origin_id   = var.CF_BUCKET_ORIGIN_ID
  }

  price_class = "PriceClass_All"

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  retain_on_delete = "false"

  tags = var.CF_TAGS_LIST

  viewer_certificate {
    acm_certificate_arn            = var.CF_CERTFICATE_ARN
    cloudfront_default_certificate = "false"
    minimum_protocol_version       = "TLSv1.2_2018"
    ssl_support_method             = "sni-only"
  }

  web_acl_id = var.WEB_ACL
}

# WAF
resource "aws_wafv2_web_acl" "aws_wafv2_web_acl" {
  name        = var.WAF_NAME
  description = var.WAF_DESCRIPTION
  scope       = var.WAF_SCOPE

  default_action {
    allow {}
  }

  rule {
    name     = var.WAF_RULE_NAME_1
    priority = 1

    override_action {
      count {}
    }

    statement {
      managed_rule_group_statement {
        name        = var.WAF_RULE_NAME_1
        vendor_name = var.WAF_VENDOR

        # excluded_rule {
        #   name = "SizeRestrictions_QUERYSTRING"
        # }

        # excluded_rule {
        #   name = "NoUserAgent_HEADER"
        # }
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = var.CLOUDWATCH_METRICS_ENABLED
      metric_name                = var.WAF_METRIC_1
      sampled_requests_enabled   = var.SAMPLE_REQUESTS_ENABLED
    }
  }



  rule {
    name     = var.WAF_RULE_NAME_2
    priority = 2

    override_action {
      count {}
    }

    statement {
      managed_rule_group_statement {
        name        = var.WAF_RULE_NAME_2
        vendor_name = var.WAF_VENDOR
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = var.CLOUDWATCH_METRICS_ENABLED
      metric_name                = var.WAF_METRIC_2
      sampled_requests_enabled   = var.SAMPLE_REQUESTS_ENABLED
    }
  }  


  rule {
    name     = var.WAF_RULE_NAME_3
    priority = 3

    override_action {
      count {}
    }

    statement {
      managed_rule_group_statement {
        name        = var.WAF_RULE_NAME_3
        vendor_name = var.WAF_VENDOR
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = var.CLOUDWATCH_METRICS_ENABLED
      metric_name                = var.WAF_METRIC_3
      sampled_requests_enabled   = var.SAMPLE_REQUESTS_ENABLED
    }
  } 

  rule {
    name     = var.WAF_RULE_NAME_4
    priority = 4

    override_action {
      count {}
    }

    statement {
      managed_rule_group_statement {
        name        = var.WAF_RULE_NAME_4
        vendor_name = var.WAF_VENDOR
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = var.CLOUDWATCH_METRICS_ENABLED
      metric_name                = var.WAF_METRIC_4
      sampled_requests_enabled   = var.SAMPLE_REQUESTS_ENABLED
    }
  } 

  tags = var.WAF_TAG_LIST

  visibility_config {
    cloudwatch_metrics_enabled = var.CLOUDWATCH_METRICS_ENABLED
    metric_name                = var.WAF_METRIC
    sampled_requests_enabled   = var.SAMPLE_REQUESTS_ENABLED
  }
}

But I am getting the below error

error updating CloudFront Distribution (E32RNPFGEUHQ6J): InvalidWebACLId: Web ACL is not accessible by the requester.

Here the cloudfront is created in ap-southeast-2 region and the waf is created in us-east-1 region.

Can someone please help me on this?


Solution

  • When using WAFv2, you need to specify the the ARN not the ID to web_acl_id in aws_cloudfront_distribution.

    See the note here https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#web_acl_id

    or this GitHub issue https://github.com/hashicorp/terraform-provider-aws/issues/13902