6
votes

I am trying to create an ACM certificate to apply to my Amazon ALB using Terraform 0.12.0. I'm able to create my ALB without a certificate with no problem. The entire infrastructure stack is built and deployed as expected. Now, I've added the following code to create the Route 53 validation record, request the certificate, and assign it to a new ALB listener:

resource "aws_route53_zone" "main" { name = "${var.zone_name}" }

resource "aws_route53_record" "validation" {
  name    = "${aws_acm_certificate.main.domain_validation_options.0.resource_record_name}"
  type    = "${aws_acm_certificate.main.domain_validation_options.0.resource_record_type}"
  zone_id = "${aws_route53_zone.main.zone_id}"
  records = ["${aws_acm_certificate.main.domain_validation_options.0.resource_record_value}"]
  ttl     = "60"
}

resource "aws_acm_certificate_validation" "main" {
  certificate_arn = "${aws_acm_certificate.main.arn}"
  validation_record_fqdns = "${aws_route53_record.validation.*.fqdn}"
}

resource "aws_alb_listener" "front_end_tls" {
  load_balancer_arn = "${aws_alb.main.id}"
  port              = "443"
  protocol          = "HTTPS"

  ssl_policy = "ELBSecurityPolicy-2016–08"
  certificate_arn = "${var.certificate_arn}"

  default_action {
    target_group_arn = "${aws_alb_target_group.main.id}"
    type             = "forward"
  }
}

When I run terraform apply, however, it seems to get stuck on the certificate validation. I see messages like this:

module.dns.aws_acm_certificate_validation.main: Still creating... [38m21s elapsed]

I've let the code run for over 45 minutes, until I eventually see an error saying:

Error: Error creating LB Listener: SSLPolicyNotFound: SSL policy 'ELBSecurityPolicy-2016–08' not found
    status code: 400, request id: a5f052c1-86df-11e9-993c-f99526fa9bba

  on alb/main.tf line 25, in resource "aws_alb_listener" "front_end_tls":
  25: resource "aws_alb_listener" "front_end_tls" {



Error: Expected certificate to be issued but was in state PENDING_VALIDATION

  on dns/main.tf line 38, in resource "aws_acm_certificate_validation" "main":
  38: resource "aws_acm_certificate_validation" "main" {

If I login to the console, I see the certificate request still in the Pending Validation state. I also see the Route 53 validation record created as expected.

Why is it that this certificate request is never processed and applied? Am I missing something in my Terraform code?

UPDATE: When I use an existing Route 53 zone (with a different domain name from the one I'm trying above) and reference it as a data resource in my aws_route53_record, it works with no problem. The domain name I'm trying in this test was just purchased via Route 53 today, so I'm wondering if that has something to do with my issue. I'm unable to do an nslookup on any of the records, even though I see them listed in the Route 53 console. Maybe? I'll let it sit for a couple days and see if it's just a timing issue.

2
Your zone ID appears to be referring to a Route53 zone resource rather than a data source. Are you creating the zone in this same Terraform block? If so, have you properly delegated the zone from the parent zone? What happens if you try to resolve the created record from a public box (eg not using any private DNS)?ydaetskcoR
I edited my question to show how my zone is created. That block of code is right above my certificate-related code shown in the question, so it's all created in the same file. When I do an nslookup on the validation record value, I get an error saying the server cannot be found. I see it in the Route 53 console, however.Shadowman
The issue is you haven't properly delegated the zone from the parent. If you bought the domain through Route53 then you should already have an existing zone from that which the TLD nameservers will point to. If you bought it from somewhere else then you will need to point the nameservers at your R53 zone nameservers.ydaetskcoR
I did purchase my domain from Route 53. I don't see an existing zone for the domain, but it's possible that with all the troubleshooting I may have deleted it. The only related zone I see now is the one labeled "Managed by Terraform" that is being created by my Terraform code.Shadowman
Then you will need to fix the name servers for your domain. You should be able to follow docs.aws.amazon.com/Route53/latest/DeveloperGuide/… to do this.ydaetskcoR

2 Answers

1
votes

I don't have reputation to comment, so writing an answer

OP mentioned in a comment that domain was purchased from route53, in that case a hosted zone should have been created for the domain. OP also mentions he can see the records from AWS console but can't do nslookup for any of these records.

I think in this case OP might not have purchased a domain and might have created a private hosted zone and is working with that. And off course public ACM certs can't be validated with private hosted zone

AWS Forum: https://forums.aws.amazon.com/thread.jspa?threadID=238468

Excuse me if this isn't the case

0
votes

Before to apply the following code, make sure you've purchased one domain and then, fill domain_name variable, if it should be a wildcard, you can use wildcard_enable = true this way, you can create a wildcard certificate, really useful to reuse the same ACM in different subdomains.

My directory structure

.
|____main.tf
|____variables.tf

main.tf

locals {
  final_domain = "${var.wildcard_enable == true ? "*.${var.domain_name}" : var.domain_name}"
}

resource "aws_acm_certificate" "this" {
  domain_name       = local.final_domain
  validation_method = "DNS"

  tags = {
    "Name"       = "acm-cert-name"
    "costCenter" = "xxxxxxxxx"
    "owner"      = "xxxxxxxxx"
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "this" {
  depends_on = ["aws_acm_certificate.this"]
  zone_id    = "xxxxxxxxxx"
  name       = aws_acm_certificate.this.domain_validation_options.0.resource_record_name
  type       = "CNAME"
  ttl        = "300"
  records    = [aws_acm_certificate.this.domain_validation_options.0.resource_record_value]
}

variables.tf

variable "wildcard_enable" {
  description = "Variable that allow us to choose the possibility of not use wildcard certificate"
  default     = false
}

variable "domain_name" {
  description = "The name of the domain to which apply the cert"
}

First: apply this code as a module or just apply it and wait until AWS validate it.

Finally: use aws_acm_certificate.this.arn to get the ACM arn and it could be used on ALB.

If the ACM certificate wasn't validated yet, you can't use it with ALB because the AWS api doesn't retrieve the ACM ARN.

I hope will be useful to you and other users.