0

I'm using the Terraform AWS ALB module to create an internal ALB in my AWS environment. I want to configure two HTTPS listener rules: one that forwards traffic to a specific IP address if the host header matches a certain value, and another that returns a fixed response if a specific query string is present.

Here's a snippet of my Terraform code:

module "alb" {
  source  = "terraform-aws-modules/alb/aws"
  version = "~> 8.6"

  load_balancer_type = "application"
  internal           = true

  name    = "my-alb-int"
  vpc_id  = module.vpc.vpc_id
  subnets = module.vpc.private_subnets

  security_groups = [module.alb_sg.this_security_group_id]

  https_listeners = [
    {
      port            = 443
      protocol        = "HTTPS"
      certificate_arn = aws_acm_certificate.my_cert.arn
      action_type     = "fixed-response"
      fixed_response = {
        content_type = "text/plain"
        status_code  = "200"
        message_body = "Nothing to see here move along"
      }
    },
  ]

  https_listener_rules = [
    {
      https_listener_index = 0
      priority             = 100

      actions = [{
        type               = "forward"
        target_group_index = 0
      }]

      conditions = [{ host_headers = ["my-host-header.example.com"] }]
    },
    {
      https_listener_index = 0
      priority                = 5000

      actions = [
        {
          type         = "fixed-response"
          content_type = "text/plain"
          status_code  = 200
          message_body = "Something here"
      }]

      conditions = [{ "query_strings" = [{ "bob" = "3" }] },]
    }
  ]

  target_groups = [
    {
      name_prefix          = "my-tg"
      backend_protocol     = "HTTPS"
      backend_port         = 443
      target_type          = "ip"
      deregistration_delay = 60
      health_check = {
        path                = "/"
        port                = "traffic-port"
        protocol            = "HTTPS"
        healthy_threshold   = 2
        unhealthy_threshold = 2
        timeout             = 5
        interval            = 30
      }
    }
  ]

}

The problem is that the module keeps modifying the same HTTPS listener rule over and over again, instead of creating two separate rules with different priorities. Here's an example of the output I'm seeing:

module.alb.aws_lb_listener_rule.https_listener_rule[1]: Modifying... [id=arn:aws:elasticloadbalancing:us-east-1:010538286820:listener-rule/app/admin-alb-int/73642b1c08283103/f94b47f3a79393ab/3a13a52129a353d1]

module.alb.aws_lb_listener_rule.https_listener_rule[0]: Modifying... [id=arn:aws:elasticloadbalancing:us-east-1:010538286820:listener-rule/app/admin-alb-int/73642b1c08283103/f94b47f3a79393ab/3a13a52129a353d1]
module.alb.aws_lb_listener_rule.https_listener_rule[0]: Modifications complete after 0s [id=arn:aws:elasticloadbalancing:us-east-1:010538286820:listener-rule/app/admin-alb-int/73642b1c08283103/f94b47f3a79393ab/3a13a52129a353d1]
module.alb.aws_lb_listener_rule.https_listener_rule[1]: Modifications complete after 0s [id=arn:aws:elasticloadbalancing:us-east-1:010538286820:listener-rule/app/admin-alb-int/73642b1c08283103/f94b47f3a79393ab/3a13a52129a353d1]

Notice that the rule is exactly the same for both rules so this results in one one rule being created.

As suggested here is the plan of the first run

# module.alb.aws_lb_listener_rule.https_listener_rule[0] will be updated in-place
  ~ resource "aws_lb_listener_rule" "https_listener_rule" {
        id           = "arn:aws:elasticloadbalancing:us-east-1:010538286820:listener-rule/app/admin-alb-int/73642b1c08283103/f94b47f3a79393ab/3a13a52129a353d1"
      ~ priority     = 102 -> 100

        # (3 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.alb.aws_lb_listener_rule.https_listener_rule[1] will be updated in-place
  ~ resource "aws_lb_listener_rule" "https_listener_rule" {
        id           = "arn:aws:elasticloadbalancing:us-east-1:010538286820:listener-rule/app/admin-alb-int/73642b1c08283103/f94b47f3a79393ab/3a13a52129a353d1"


        # (4 unchanged attributes hidden)

      ~ action {
          ~ type             = "forward" -> "fixed-response"
            # (2 unchanged attributes hidden)

          + fixed_response {
              + content_type = "text/plain"
              + message_body = "Something here"
              + status_code  = "200"
            }
        }

      - condition {
          - host_header {
              - values = [
                  - "my-host-header.example.com",
                ] -> null
            }
        }
      + condition {

          + query_string {
              + key   = "bob"
              + value = "3"
            }
        }
    }
   

After it has been applied and terraform is run second time the plan changes to:

    #module.alb.aws_lb_listener_rule.https_listener_rule[0] will be updated in-place
  ~ resource "aws_lb_listener_rule" "https_listener_rule" {
        id           = "arn:aws:elasticloadbalancing:us-east-1:010538286820:listener-rule/app/admin-alb-int/73642b1c08283103/f94b47f3a79393ab/3a13a52129a353d1"

        # (4 unchanged attributes hidden)

      ~ action {
          + target_group_arn = "arn:aws:elasticloadbalancing:us-east-1:010538286820:targetgroup/nas-bm20230409034236754900000001/60cf6accbb8dde6b"
          ~ type             = "fixed-response" -> "forward"
            # (1 unchanged attribute hidden)

            # (1 unchanged block hidden)
        }

      + condition {
          + host_header {
              + values = [
                  + "my-host-header.example.com",
                ]
            }
        }
      - condition {

          - query_string {
              - key   = "bob" -> null
              - value = "3" -> null
            }
        }
    }

  # module.alb.aws_lb_listener_rule.https_listener_rule[1] will be updated in-place
  ~ resource "aws_lb_listener_rule" "https_listener_rule" {
        id           = "arn:aws:elasticloadbalancing:us-east-1:010538286820:listener-rule/app/admin-alb-int/73642b1c08283103/f94b47f3a79393ab/3a13a52129a353d1"
      ~ priority     = 100 -> 102

        # (3 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

The third time the plan becomes like a first plan, the fourth time the plan becomes like the second plan and so on ad infinitum

Vlad
  • 9,180
  • 5
  • 48
  • 67
  • Please include the `terraform plan` output in your question. Just seeing that Terraform is modifying something isn't very helpful. We need to see the `plan` output to know exactly what is happening. – Mark B Apr 09 '23 at 13:04
  • Ok I added the plan hope this give you more context – Vlad Apr 09 '23 at 17:51
  • Honestly I think that terraform module is bugged, or not written correctly. You could post this on their GitHub page. It really isn't saving you many lines of code at all, using that module instead of simply declaring the resourced directly in your code, and given this issue the module certainly isn't speeding up your development compared to just declaring the resources yourself. I'm a big fan of using some of the official terraform modules like the AWS VPC module and the RDS module, but for creating a load balancer I just declare the resourced directly. – Mark B Apr 09 '23 at 19:56
  • I think so too, I am a big fan of writing all the TF code myself, unfortunately I am on a new project where use of these modules is widespread, just trying to follow the suit. Alas, I think I spent more time troubleshooting these modules than just writing everything myself. These modules are very buggy – Vlad Apr 09 '23 at 20:13

0 Answers0