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