Отсутствует запись проверки DNS при использовании terraform aws_acm_certificate_validation

Я весь день застревал на ошибке Terraform, пытаясь создать ресурс AWS Route53 и ресурс AWS Certificate Manager. Эти 2 бита являются частью более широкого проекта (веб-сайт, размещенный в s3 с помощью функции статического обслуживания).

В частности, ошибка появляется во время проверки сертификата DNS, когда запись CNAME вставляется как запись DNS в Route53.

Выложу ошибку и потом опишу настройку.

Ошибка

terraform plan -var-file=production.vars

Creating...
module.infrastructure.aws_route53_record.idarth-validation-record: Still creating... [10s elapsed]
module.infrastructure.aws_route53_record.idarth-validation-record: Still creating... [20s elapsed]
module.infrastructure.aws_route53_record.idarth-validation-record: Still creating... [30s elapsed]
module.infrastructure.aws_route53_record.idarth-validation-record: Still creating... [40s elapsed]
module.infrastructure.aws_route53_record.idarth-validation-record: Still creating... [50s elapsed]
module.infrastructure.aws_route53_record.idarth-validation-record: Still creating... [1m0s elapsed]
module.infrastructure.aws_route53_record.idarth-validation-record: Still creating... [1m10s elapsed]
module.infrastructure.aws_route53_record.idarth-validation-record: Creation complete after 1m12s [id=ZB4TSGZTTZ3CQ__7bc5230529c8192e8e697aeab0ec0eb9.idarth.com._CNAME]
module.infrastructure.aws_acm_certificate_validation.idarth-ssl-certificate: Creating...
2019/08/24 18:32:40 [ERROR] module.infrastructure: eval: *terraform.EvalSequence, err: 1 error occurred:
    * missing www.idarth.com DNS validation record: _18ff46dac48c6d852b696306dfa57093.www.idarth.com

2019/08/24 18:32:40 [TRACE] [walkApply] Exiting eval tree: module.infrastructure.aws_acm_certificate_validation.idarth-ssl-certificate

Error: 1 error occurred:
    * missing www.idarth.com DNS validation record: _18ff46dac48c6d852b696306dfa57093.www.idarth.com



  on ../modules/route53.tf line 14, in resource "aws_acm_certificate_validation" "idarth-ssl-certificate":
  14: resource "aws_acm_certificate_validation" "idarth-ssl-certificate" {

ПРИМЕЧАНИЕ: я не включил план выполнения, который создавал другие части инфраструктуры, но я только сообщил о проблемном элементе.

Вот мои файлы tf:

route53.tf

resource "aws_route53_zone" "idarth-hosted-zone" {
  name = "${var.domain_name}"
}


resource "aws_route53_record" "idarth-validation-record" {
  name    = "${aws_acm_certificate.idarth-ssl-certificate.domain_validation_options.0.resource_record_name}"
  type    = "${aws_acm_certificate.idarth-ssl-certificate.domain_validation_options.0.resource_record_type}"
  zone_id = "${aws_route53_zone.idarth-hosted-zone.zone_id}"
  records = ["${aws_acm_certificate.idarth-ssl-certificate.domain_validation_options.0.resource_record_value}"]
  ttl     = "60"
}

resource "aws_acm_certificate_validation" "idarth-ssl-certificate" {
  provider        = "aws.us_east_1"
  certificate_arn = "${aws_acm_certificate.idarth-ssl-certificate.arn}"
  validation_record_fqdns = [
    "${aws_route53_record.idarth-validation-record.fqdn}"
  ]
}

resource "aws_route53_record" "idarth-record-domain" {
  zone_id = "${aws_route53_zone.idarth-hosted-zone.zone_id}"
  name = "${var.domain_name}"
  type = "A"

  alias {
    name = "${aws_cloudfront_distribution.idarth-cloudfront-distr.domain_name}"
    zone_id = "${aws_cloudfront_distribution.idarth-cloudfront-distr.hosted_zone_id}"
    evaluate_target_health = false
  }
}

resource "aws_route53_record" "idarth-record-domain-www" {
  zone_id = "${aws_route53_zone.idarth-hosted-zone.zone_id}"
  name = "${var.domain_name_www}"
  type = "A"

  alias {
    name = "${aws_cloudfront_distribution.idarth-cloudfront-distr.domain_name}"
    zone_id = "${aws_cloudfront_distribution.idarth-cloudfront-distr.hosted_zone_id}"
    evaluate_target_health = false
  }
}

ssl_certificate.tf

provider "aws" {
  alias           = "us_east_1"
  region          = "us-east-1"
}

resource "aws_acm_certificate" "idarth-ssl-certificate" {
  provider        = "aws.us_east_1"

  domain_name       = "${var.domain_name}"
  subject_alternative_names = ["${var.domain_name_www}"]
  validation_method = "DNS"

  lifecycle {
    create_before_destroy = true
  }

  tags = {
        Project = "${var.name}-${var.env}"
        Scope    = "personal-blog"
    }
}

distribution.tf

resource "aws_cloudfront_distribution" "idarth-cloudfront-distr" {
  depends_on = ["aws_acm_certificate_validation.idarth-ssl-certificate"]

  origin {
    domain_name = "${aws_s3_bucket.idarth-static-site-host.bucket_regional_domain_name}"
    origin_id   = "${var.domain_name}"

    /*s3_origin_config {
      origin_access_identity = "origin-access-identity/cloudfront/ABCDEFG1234567"
    }*/
  }

  enabled             = true
  is_ipv6_enabled     = true
  default_root_object = "index.html"

  /*logging_config {
    include_cookies = false
    bucket          = "mylogs.s3.amazonaws.com"
    prefix          = "myprefix"
  }*/

  aliases = ["${var.domain_name}", "${var.domain_name_www}"]

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "${var.domain_name}"

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    compress = true
    viewer_protocol_policy = "redirect-to-https"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }


  #price_class = "PriceClass_200"

  restrictions {
    geo_restriction {
      restriction_type = "none"
      locations        = []
    }
  }

  viewer_certificate {
    acm_certificate_arn  = "${aws_acm_certificate_validation.idarth-ssl-certificate.certificate_arn}"
    ssl_support_method  = "sni-only"
  }


    tags = {
        Project = "${var.name}-${var.env}"
        Scope    = "personal-blog"
    }
}

Версия Terraform: 0.12.7, версия поставщика aws: v2.25.0_x4

Анализ журнала ошибок

Я потратил один день, пытаясь отладить указанную выше ошибку, вот мои мысли:

  • Сертификат создает 2 CNAME для 2 доменов (переменные: var.domain_name, var.domain_name_www): _7bc5230529c8192e8e697aeab0ec0eb9.idarth.com._CNAME, _18ff46dac48c6d852b696306dfa57093.www.idarth.com
  • Создание первого, как вы видите в журналах плана выполнения, выполнено успешно, в то время как второй вызывает проблемы.
  • Посмотрев в консоль AWS, я увидел первый CNAME, вставленный в зону размещения DNS, но не вторую. Даже если вставлена ​​зона размещения DNS, сертификат для этой записи по-прежнему ожидает проверки.

Это то, что я смог найти до сих пор, но я не знаю, как двигаться дальше. Кто-нибудь был здесь раньше и мог помочь со следующим?

Спасибо!


person AlessioG    schedule 25.08.2019    source источник


Ответы (4)


Не уверен, что это все еще актуально, но сегодня у меня была такая же проблема, и я нашел этот вопрос здесь, поэтому, возможно, я оставлю ответ для потомков.

Оказывается, ресурс проверки должен включать все сгенерированные CNAME, например:

resource "aws_acm_certificate" "some-cert" {
  provider = "aws.us-east-1"

  domain_name               = "some.domain"
  validation_method         = "DNS"
  subject_alternative_names = ["www.some.domain"]
}

resource "aws_route53_record" "cert-validations" {
  count = length(aws_acm_certificate.some-cert.domain_validation_options)

  zone_id = var.zone_id
  name    = element(aws_acm_certificate.some-cert.domain_validation_options.*.resource_record_name, count.index)
  type    = element(aws_acm_certificate.some-cert.domain_validation_options.*.resource_record_type, count.index)
  records = [element(aws_acm_certificate.some-cert.domain_validation_options.*.resource_record_value, count.index)]
  ttl     = 60
}

resource "aws_acm_certificate_validation" "cert-validation" {
  provider = "aws.us-east-1"

  certificate_arn         = aws_acm_certificate.some-cert.arn
  validation_record_fqdns = aws_route53_record.cert-validations.*.fqdn
}

В частности, обратите внимание, что у нас есть один aws_acm_certificate_validation ресурс, но он содержит список из нескольких validation_record_fqdns из всех сгенерированных проверочных записей DNS CNAME.

Надеюсь, это поможет!

person Marcin Wyszynski    schedule 29.10.2019
comment
Terraform выдает сообщение об ошибке: значение счетчика зависит от атрибутов ресурса, которые не могут быть определены до применения, поэтому Terraform не может предсказать, сколько экземпляров будет создано. Какую работу вы для этого сделали? Вы использовали -target? - person nsantiago2719; 30.10.2019
comment
Догадаться. Сделал список переменных с альтернативными именами, затем использовал его для подсчета. Бывший. count = length(var.alternative-names) + 1. - person nsantiago2719; 30.10.2019
comment
Да, это один из вариантов. Другой вариант - разделить его на два прогона: сначала создать записи, а затем проверка. - person Marcin Wyszynski; 30.10.2019

Вот как я решил это в своей конфигурации, немного изменив ответ Марцина Вышинского. Поскольку проверка может привести к дублированию записей DNS, используйте allow_overwrite = true в aws_route53_record, чтобы обойти already exists ошибки и убедиться, что все они созданы.

config.tf

# locals must be used so ${var.env} can be interpolated in the definition
locals {
  tags = {
    Name        = "${var.domain_name}"
    Environment = "${var.env}"
  }
  cert_sans = ["www.${var.domain_name}", "cdn.${var.domain_name}", "*.${var.domain_name}"]
}

variable "env" {
  default = "production"
}

variable "domain_name" {
  default = "your-domain.com"
}

acm.tf

resource "aws_acm_certificate" "site" {
  domain_name               = var.domain_name
  validation_method         = "DNS"
  tags                      = local.tags
  subject_alternative_names = local.cert_sans

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "cert_validations" {
  count = length(local.cert_sans) + 1

  zone_id         = aws_route53_zone.public.zone_id
  allow_overwrite = true # This is what allowed for conflict resolution in DNS
  name            = element(aws_acm_certificate.site.domain_validation_options.*.resource_record_name, count.index)
  type            = element(aws_acm_certificate.site.domain_validation_options.*.resource_record_type, count.index)
  records         = [element(aws_acm_certificate.site.domain_validation_options.*.resource_record_value, count.index)]
  ttl             = 60
}

resource "aws_acm_certificate_validation" "cert_validation" {
  certificate_arn         = aws_acm_certificate.site.arn
  validation_record_fqdns = aws_route53_record.cert_validations.*.fqdn

  timeouts {
    create = "120m"
  }
}
person Gio Palacino    schedule 15.01.2020

В зоне не должно быть заключительного .?

resource "aws_route53_zone" "idarth-hosted-zone" {
  name = "${var.dns_zone}."
}

Также в аналогичном сценарии я использовал CNAME для записи DNS, указывающей на раздачу CloudFront.

resource aws_route53_record www {
    zone_id = data.aws_route53_zone.selected.zone_id
    name    = "openbanking.${var.dns_zone}"
    type    = "CNAME"
    records = [aws_cloudfront_distribution.open_banking_public_website.domain_name]
    ttl     = 60
}

HTH

person Giulio Vian    schedule 26.08.2019
comment
Привет, Джулио, я все еще сталкиваюсь с той же проблемой с CNAME. В сети много путаницы с этим aws_acm_certificate_validation. Я читал о многих людях, которые сталкиваются с проблемами, похожими на мою, и на данный момент нет четкого ответа. Я ценю, что вы пытаетесь помочь здесь, спасибо! - person AlessioG; 26.08.2019
comment
У меня есть рабочий код, датированный 4-6 недель назад в Terraform 0.12, так что это можно сделать. Я не могу поделиться им полностью, но частично он должен быть виден в сообщении в блоге. Отправлю ссылку, когда она станет общедоступной. - person Giulio Vian; 27.08.2019
comment
Это поможет Джулио, вы можете пропинговать его здесь, когда будете готовы, если сможете. - person AlessioG; 27.08.2019

Теперь вы можете использовать validate_certificate = false в качестве обходного пути, но это было решено в последней версии этого модуля, попробуйте обновить свой терраформ.

person lORD    schedule 25.08.2019
comment
обе версии моего terraform и моего поставщика aws являются последними в соответствии с github.com/hashicorp/terraform/releases и github.com/terraform-providers/terraform-provider-aws/ выпуски. Я не понимаю, куда мне вставить valdiate_certificate = false. Не могли бы Вы уточнить? - person AlessioG; 25.08.2019
comment
Я тоже не мог найти этого. Столкнувшись с той же проблемой, которая началась из ничего. - person Rafael Sales; 29.08.2019