Closed PowerShellPat closed 1 month ago
Hey @PowerShellPat 👋 Thank you for taking the time to raise this! Am I correct in understanding that when you add the depends_on
block to introduce the dependency on aws_acm_certificate_validation
to aws_lb_listener
, this works as expected?
Hi @justinretzolk
Correct; by adding the depends_on
block, this code will run fine.
Having said this, it means we can't use the community module terraform-aws-alb without running the code twice if we have an ACM certificate being created and validated in the same deployment.
If we do add a depends_on
block to the module to depend on aws_acm_certificate_validation
, we run into cyclic errors.
Hey @PowerShellPat 👋 Thank you for confirming that. I'm not sure I'm following on where you run into cycle errors when adding the depends_on
block -- is it possible for you to supply a sample configuration illustrating that as well? I suspect that this is something that can be worked around by either a configuration change or a change to the module you linked to, and having that information may help me to provide that workaround.
Hi @justinretzolk,
Sorry for the delay in responding.
I've attached an example of when we run into cyclic errors when using the community module terraform-aws-alb:
module "alb_external" {
source = "terraform-aws-modules/alb/aws"
version = "~> 6.0"
name = "alb-testing"
load_balancer_type = "application"
vpc_id = "vpc-XXX"
subnets = ["subnet-XXX", "subnet-XXX"]
security_groups = ["sg-XXX"]
target_groups = [ # We add the target to the TG as part of another deployment.
{
name = "tg-test"
backend_protocol = "HTTPS"
backend_port = 443
target_type = "instance"
}
]
https_listeners = [
{
port = 443
protocol = "HTTPS"
certificate_arn = aws_acm_certificate.public.arn
target_group_index = 0
}
]
tags = {
name = "alb-testing"
}
depends_on = [
aws_acm_certificate_validation.public
]
}
resource "aws_route53_record" "public_entry" {
zone_id = "XXX"
name = "name.domain"
type = "A"
alias {
name = module.alb_external.lb_dns_name
zone_id = module.alb_external.lb_zone_id
evaluate_target_health = false
}
}
resource "aws_route53_record" "public_acm" {
for_each = {
for dvo in aws_acm_certificate.public.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = "XXX"
}
resource "aws_acm_certificate" "public" {
domain_name = aws_route53_record.public_entry.name
validation_method = "DNS"
}
resource "aws_acm_certificate_validation" "public" {
certificate_arn = aws_acm_certificate.public.arn
validation_record_fqdns = [for record in aws_route53_record.public_acm : record.fqdn]
}
When running the code twice without the depends_on
block in the module alb_external
it works fine.
Here is the error we get when adding the depends_on
block:
Error: Cycle: module.alb_external.output.lb_zone_id (expand), module.alb_external.var.name (expand), module.alb_external.var.load_balancer_update_timeout (expand), module.alb_external.var.drop_invalid_header_fields (expand), module.alb_external.var.name_prefix (expand), module.alb_external.var.desync_mitigation_mode (expand), module.alb_external.var.subnets (expand), module.alb_external.var.enable_http2 (expand), module.alb_external.var.access_logs (expand), module.alb_external.var.ip_address_type (expand), module.alb_external.var.load_balancer_type (expand), module.alb_external.var.idle_timeout (expand), module.alb_external.var.enable_waf_fail_open (expand), module.alb_external.var.putin_khuylo (expand), module.alb_external.local.create_lb (expand), module.alb_external.var.subnet_mapping (expand), module.alb_external.var.enable_cross_zone_load_balancing (expand), module.alb_external.var.enable_deletion_protection (expand), module.alb_external.var.internal (expand), module.alb_external.var.security_groups (expand), module.alb_external.var.load_balancer_create_timeout (expand), module.alb_external.var.load_balancer_delete_timeout (expand), module.alb_external.var.lb_tags (expand), module.alb_external.var.tags (expand), module.alb_external.aws_lb.this, module.alb_external.output.lb_dns_name (expand), aws_route53_record.public_entry, aws_acm_certificate.public, aws_route53_record.public_acm, aws_acm_certificate_validation.public, module.alb_external (expand), module.alb_external.var.create_lb (expand)
@PowerShellPat - I think you can break that dependency cycle by following the example at https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation#dns-validation-with-route-53. The trick here is to use the certifcate ARN that is held within the aws_certificate_validation
resource so that you don't depend on both the cert and the validation thereof. In addition, and probably more critical than the former is to extract the FQDN of the cert into its own variable/local (or even just hardcoding it in both places would work but is a bit icky). That will break the cert -> dns record -> alb -> cert cycle you have. i.e. I think you want something like this (I've reordered your resources to be in dependency order, hopefully for clarity):
resource "aws_acm_certificate" "public" {
domain_name = var.alb_fqdn
validation_method = "DNS"
}
resource "aws_route53_record" "public_acm" {
for_each = {
for dvo in aws_acm_certificate.public.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = "XXX"
}
resource "aws_acm_certificate_validation" "public" {
certificate_arn = aws_acm_certificate.public.arn
validation_record_fqdns = [for record in aws_route53_record.public_acm : record.fqdn]
}
module "alb_external" {
source = "terraform-aws-modules/alb/aws"
version = "~> 6.0"
name = "alb-testing"
load_balancer_type = "application"
vpc_id = "vpc-XXX"
subnets = ["subnet-XXX", "subnet-XXX"]
security_groups = ["sg-XXX"]
target_groups = [ # We add the target to the TG as part of another deployment.
{
name = "tg-test"
backend_protocol = "HTTPS"
backend_port = 443
target_type = "instance"
}
]
https_listeners = [
{
port = 443
protocol = "HTTPS"
certificate_arn = aws_acm_certificate_validation.public.certificate_arn
target_group_index = 0
}
]
tags = {
name = "alb-testing"
}
}
resource "aws_route53_record" "public_entry" {
zone_id = "XXX"
name = var.alb_fqdn
type = "A"
alias {
name = module.alb_external.lb_dns_name
zone_id = module.alb_external.lb_zone_id
evaluate_target_health = false
}
}
Marking this issue as stale due to inactivity. This helps our maintainers find and focus on the active issues. If this issue receives no comments in the next 30 days it will automatically be closed. Maintainers can also remove the stale label.
If this issue was automatically closed and you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thank you!
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Community Note
Terraform CLI and Terraform AWS Provider Version
Terraform - 1.2.7 AWS provider - 4.25.0
Affected Resource(s)
Terraform Configuration Files
Please include all Terraform configurations required to reproduce the bug. Bug reports without a functional reproduction may be closed without investigation.
Debug Output
Error: creating ELBv2 Listener (arn:aws:elasticloadbalancing:ap-southeast-2:XXX:loadbalancer/app/testing/XXX): UnsupportedCertificate: The certificate 'arn:aws:acm:ap-southeast-2:XXX:certificate/XXX' must have a fully-qualified domain name, a supported signature, and a supported key size. status code: 400, request id: XXX
Panic Output
N\A
Expected Behavior
The resource
aws_acm_certificate_validation
should be fully completed before moving onto the next resourceaws_lb_listener
.A workaround is available by adding the depends_on block to the
aws_lb_listener
resource, dependant on theaws_acm_certificate_validation
resource. This is how the console output below was produced:It shows the graph being walked correctly. However, it may be that the certificate is not ready for consumption when the LB listener is being created.
Actual Behavior
Error as specified in the Debug Output section.
Steps to Reproduce
terraform apply
Important Factoids
N\A
References
0000