BAD_SEED
BAD_SEED

Reputation: 5056

Terraform: Attach an ACM certificate to the load balancer only if that certificate has been validated

I'm creating a public certificate using Amazon Certificate Manager (ACM) using Terraform. The code looks like this:

resource "aws_acm_certificate" "wc_mydomain_com" {
  domain_name       = "*.mydomain.com"
  validation_method = "DNS"
    
  lifecycle {
    create_before_destroy = true
  }
}

this code correctly creates a new certificate for that domain. I only need to check the DNS key and value that I need to use to validate it. This is a manual task.

This certificate needs to be attached to an Application Load Balancer (ALB), so I would use something like this:

resource "aws_lb_listener_certificate" "wc_mydomain_com_attachment" {
  listener_arn    = <REFERENCE TO HTTPS LISTENER>
  certificate_arn = aws_acm_certificate.wc_mydomain_com.arn
}

This code works correctly if the certificate above has been validated. Alas, since validation is a manual task, a lot of time this code fails with an error because, I think, I can't attach an invalid certificate to the listener. This is the error:

Error: creating ELB (Elastic Load Balancing) Listener Certificate: operation error Elastic Load Balancing v2: AddListenerCertificates, https response error StatusCode: 400, RequestID: XXX, api error UnsupportedCertificate: The certificate 'arn:aws:acm:[REGION]:[ACCOUNT ID]:certificate/[ID]' must have a fully-qualified domain name, a supported signature, and a supported key size.

I tried many solutions:

  1. using the data source aws_acm_certificate to query a certificate that has the status ISSUED;
  2. using the aws_acm_certificate_validation but it implements a blocking behaviour that I don't like;

The idea was to put a count in wc_mydomain_com_attachment but it turned into an error since the count value can't be established during the plan. What can I do?

I want only to deactivate the assignment of the certificate to the listener if the certificate is not validated.

Upvotes: 0

Views: 537

Answers (1)

The DevOps Dude
The DevOps Dude

Reputation: 1937

The way I currently handle this situation of conditionally attaching a certificate to an Application Load Balancer (ALB) based on whether the certificate has been validated in AWS Certificate Manager (ACM), is by using the aws_acm_certificate_validation resource in Terraform. This resource allows you to wait until the ACM certificate is validated before proceeding with the attachment.

To do this, keep the creation of your certificate as is, but add the validation step explicitly.

resource "aws_acm_certificate" "wc_mydomain_com" {
  domain_name       = "*.mydomain.com"
  validation_method = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "cert_validation" {
  zone_id = "<ZONE_ID>"
  name    = aws_acm_certificate.wc_mydomain_com.domain_validation_options.0.resource_record_name
  type    = aws_acm_certificate.wc_mydomain_com.domain_validation_options.0.resource_record_type
  records = [aws_acm_certificate.wc_mydomain_com.domain_validation_options.0.resource_record_value]
  ttl     = 60
}

resource "aws_acm_certificate_validation" "wc_mydomain_com_validated" {
  certificate_arn         = aws_acm_certificate.wc_mydomain_com.arn
  validation_record_fqdns = [aws_route53_record.cert_validation.fqdn]
}

Make sure you replace <ZONE_ID> with the actual ID of the Route53 zone where you want to create the DNS record for validation.

Next thing you want to do is to utilize the depends_on argument in your aws_lb_listener_certificate resource to ensure that it only tries to attach the certificate after validation is complete.

resource "aws_lb_listener_certificate" "wc_mydomain_com_attachment" {
  listener_arn    = <REFERENCE TO HTTPS LISTER>
  certificate_arn = aws_acm_certificate.wc_mydomain_com.arn

  depends_on = [aws_acm_setup.wc_mydomain_com_validated]
}

Replace <REFERENCE TO HTTPS LISTENER> with the actual ARN of the HTTPS listener where you want to attach the certificate.

Here’s a summary of the modifications I made to your setup :

  • DNS Validation Record: This resource creates the necessary DNS validation record in Route53. Terraform automatically extracts the required values from the aws_acm_certificate resource.
  • Certificate Validation: The aws_acm_certificate_validation resource ensures that Terraform waits for the DNS validation to complete before marking the certificate as validated.
  • Conditional Certificate Attachment: By using the depends_on attribute in the aws_lb_listener_certificate resource, Terraform ensures that it only attempts to attach the certificate to the ALB after it has been validated.

This setup should eliminate the issue of trying to attach an unvalidated certificate to the ALB, and I confirm that it works for me.

Hope it helps or gives you an idea you can work with.

Upvotes: 0

Related Questions