Terraform 与 A​​PI-Gateway、Route53 和 SSL 认证相互依赖问题

Posted

技术标签:

【中文标题】Terraform 与 A​​PI-Gateway、Route53 和 SSL 认证相互依赖问题【英文标题】:Terraform with API-Gateway, Route53, and SSL Certification interdependency problem 【发布时间】:2019-07-28 14:16:00 【问题描述】:

我似乎无法使用 terraform 从 ACM 获得在 API-Gateway、Route53 上工作的 SSL 证书。似乎存在相互依赖问题。

data "aws_route53_zone" "root_domain" 
  name         = "$var.route53_root_domain_name"
  private_zone = false


# The domain name to use with api-gateway
resource "aws_api_gateway_domain_name" "domain_name" 
  domain_name = "$var.route53_sub_domain_name"

  certificate_arn = "$aws_acm_certificate.cert.arn"


resource "aws_route53_record" "sub_domain" 
  name    = "$var.route53_sub_domain_name"
  type    = "A"
  zone_id = "$data.aws_route53_zone.root_domain.zone_id"

  alias 
    name                   = "$aws_api_gateway_domain_name.domain_name.cloudfront_domain_name"
    zone_id                = "$aws_api_gateway_domain_name.domain_name.cloudfront_zone_id"
    evaluate_target_health = false
  


resource "aws_acm_certificate" "cert" 
  # api-gateway / cloudfront certificates need to use the us-east-1 region
  provider          = "aws.cloudfront-acm-certs"
  domain_name       = "$var.route53_sub_domain_name"
  validation_method = "DNS"

  lifecycle 
    create_before_destroy = true
  


resource "aws_route53_record" "cert_validation" 
  name    = "$aws_acm_certificate.cert.domain_validation_options.0.resource_record_name"
  type    = "$aws_acm_certificate.cert.domain_validation_options.0.resource_record_type"
  zone_id = "$aws_route53_record.sub_domain.zone_id"
  records = ["$aws_acm_certificate.cert.domain_validation_options.0.resource_record_value"]
  ttl     = 60


resource "aws_acm_certificate_validation" "cert" 
  # api-gateway / cloudfront certificates need to use the us-east-1 region
  provider          = "aws.cloudfront-acm-certs"

  certificate_arn         = "$aws_acm_certificate.cert.arn"
  validation_record_fqdns = ["$aws_route53_record.cert_validation.fqdn"]

问题似乎是:

    aws_api_gateway_domain_name 需要 aws_acm_certificate aws_acm_certificate 必须经过验证,所以第 3 步 aws_route53_record.cert_validation 需要 aws_route53_record.sub_domain aws_route53_record.subdomain 需要 aws_api_gateway_domain_name 转到 1

每次我尝试使用给定的配置时,都会收到以下错误:

aws_api_gateway_domain_name.domain_name:创建 API 网关时出错 域名:BadRequestException:无法关联证书 arn:aws:acm:us-east-1:yyyy:certificate/zzzz 与 CloudFront。这 错误可能会阻止域名 audit-log.taspli.com 被使用 在 API Gateway 中最多 40 分钟。请确保证书 域名与请求的域名匹配,并且该用户拥有 在“*”资源上调用 cloudfront:UpdateDistribution 的权限。 状态码:400,请求ID:xxxx

【问题讨论】:

3. aws_route53_record.cert_validation requires aws_route53_record.sub_domain 是假的。它只需要验证记录,而不需要作为证书主题的子域的记录。您可以通过为工作中的 Route 53 托管区域中不存在的子域手动创建经过 DNS 验证的 ACM 证书来证明这一点。错误消息仅表明证书尚未被验证,而不是验证不能/不会成功。 啊,所以我可以删除 zone_id 字段,然后它会成功吗?如果不是我创建它的域,它怎么知道在哪里添加记录作为它的父项? 好的,所以我验证了我的说法,即用于证书验证的 aws_route53_record 需要 zone_id。因此,要附加记录的区域必须先存在,然后才能附加记录。这是有道理的。那么问题是,它所附加的子域的 aws_route53_record 需要来自 api 网关域名的记录,以便将别名附加到 api 网关创建的云端分发。再说一次,这只是另一个我不确定如何解决的循环依赖。 【参考方案1】:

我似乎通过将证书验证记录添加到根域而不是子域来解决问题。从而打破循环依赖。

问题似乎是没有证书就无法创建子域,没有子域就无法验证证书。所以情况陷入僵局,无法解决。

您可以手动创建子域,但如果您必须手动解决问题,那么自动化的意义何在。

所以我尝试将证书验证记录添加到根目录。突然它开始工作,因为根域是在项目外部创建的。一种可以在外部处理的全球基础设施项目。然后,您的各个项目可以根据具体情况暂停该基础架构。

这是有效的 terraform 配置:

data "aws_route53_zone" "root_domain" 
  name         = "$var.route53_root_domain_name"
  private_zone = false


# The domain name to use with api-gateway
resource "aws_api_gateway_domain_name" "domain_name" 
  domain_name = "$var.route53_sub_domain_name"

  certificate_arn = "$aws_acm_certificate.cert.arn"


resource "aws_route53_record" "sub_domain" 
  name    = "$var.route53_sub_domain_name"
  type    = "A"
  zone_id = "$data.aws_route53_zone.root_domain.zone_id"

  alias 
    name                   = "$aws_api_gateway_domain_name.domain_name.cloudfront_domain_name"
    zone_id                = "$aws_api_gateway_domain_name.domain_name.cloudfront_zone_id"
    evaluate_target_health = false
  


resource "aws_acm_certificate" "cert" 
  # api-gateway / cloudfront certificates need to use the us-east-1 region
  provider          = "aws.cloudfront-acm-certs"
  domain_name       = "$var.route53_sub_domain_name"
  validation_method = "DNS"


resource "aws_route53_record" "cert_validation" 
  name    = "$aws_acm_certificate.cert.domain_validation_options.0.resource_record_name"
  type    = "$aws_acm_certificate.cert.domain_validation_options.0.resource_record_type"
  zone_id = "$data.aws_route53_zone.root_domain.zone_id"
  records = ["$aws_acm_certificate.cert.domain_validation_options.0.resource_record_value"]
  ttl     = 60


resource "aws_acm_certificate_validation" "cert" 
  # api-gateway / cloudfront certificates need to use the us-east-1 region
  provider          = "aws.cloudfront-acm-certs"

  certificate_arn         = "$aws_acm_certificate.cert.arn"
  validation_record_fqdns = ["$aws_route53_record.cert_validation.fqdn"]

  timeouts 
    create = "45m"
  

【讨论】:

以上是关于Terraform 与 A​​PI-Gateway、Route53 和 SSL 认证相互依赖问题的主要内容,如果未能解决你的问题,请参考以下文章

Terraform - 与环境关联的实例配置文件不存在

如何使 Azure 备份与 Terraform 一起使用?

Terraform与Kubernetes的体验

为 GCS 与 Terraform 启用“互操作”访问?

terraform 解决冲突的提供者约束:没有可用的版本与给定的约束匹配

text Terraform:ACM与DNS验证