Aws_acm_certificate.app_cert.domain_validation_options是一组对象,



我一直在参加Terraform(+CI/CD(研讨会,该研讨会是在早期版本的Terraform中教授的,但我在1.0.11中决定与AWS提供商3.65.0合作……只是想看看会有什么不同。我在与ACM打交道以获得证书时遇到了障碍,我需要一些关于如何继续的建议。

我得到的错误是在计划阶段:

[ckerr@ck-vm-rhel8-localdomain recipe-app-api-devops]$ docker-compose -f deploy/docker-compose.yml run --rm terraform plan
Creating deploy_terraform_run ... done
╷
│ Error: Invalid for_each argument
│ 
│   on dns.tf line 44, in resource "aws_route53_record" "app_cert_validation_records":
│   44:   for_each = {
│   45:     for dvo in aws_acm_certificate.app_cert.domain_validation_options : dvo.domain_name => {
│   46:       name   = dvo.resource_record_name
│   47:       type   = dvo.resource_record_type
│   48:       record = dvo.resource_record_value
│   49:     }
│   50:   }
│     ├────────────────
│     │ aws_acm_certificate.app_cert.domain_validation_options is a set of object, known only after apply
│ 
│ The "for_each" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how
│ many instances will be created. To work around this, use the -target argument to first apply only the resources that the
│ for_each depends on.
╵
Releasing state lock. This may take a few moments...
ERROR: 1

我有一个名为dns.tf的文件,负责管理dns和SSL证书,目的是让亚马逊的证书管理器(ACM(获得证书。那个文件看起来是这样的,我加入了评论,希望有人能够确定我的想法哪里出了问题。

// BELIEF: this is the DNS zone we will be operating in. No issues there.
//
data "aws_route53_zone" "zone" {
name = "${var.dns_zone_name}."
}
// BELIEF: this creates a CNAME record that points to our AWS ELB instance for our application.
// This is where it departs a little from the documentation, but I'm not sure if the documentation
// is just being a bit sparse, or if the validation records are meant to also be part of this object.
//
resource "aws_route53_record" "app" {
zone_id = data.aws_route53_zone.zone.zone_id
name    = "${lookup(var.subdomain, terraform.workspace)}.${data.aws_route53_zone.zone.name}"
type    = "CNAME"
ttl     = "300"
records = [aws_lb.api.dns_name]
}
// BELIEF: this models the certificate for our application.
//
resource "aws_acm_certificate" "app_cert" {
domain_name       = aws_route53_record.app.fqdn
validation_method = "DNS"
tags = local.common_tags
lifecycle {
create_before_destroy = true
}
}
// BELIEF: to prove ownership of the domain we need to be able to prove that we can
// place certain records into the domain as part of a DNS challenge method.
// I believe this is meant to refer to just those challenge records.
// As this is the dynamic part, its unlikely that the domain validation options would
// be known ahead of time, and so this is where I'm coming unstuck.
//
resource "aws_route53_record" "app_cert_validation_records" {
allow_overwrite = true
zone_id         = data.aws_route53_zone.zone.zone_id
ttl             = "60"
for_each = {
for dvo in aws_acm_certificate.app_cert.domain_validation_options : dvo.domain_name => {
name   = dvo.resource_record_name
type   = dvo.resource_record_type
record = dvo.resource_record_value
}
}
name    = each.value.name
type    = each.value.type
records = [each.value.record]
}
// BELIEF: This doesn't create anything; its just a placeholder for the validation
// process... presumably for dependency reasons.
// It basically just associates the FQDN (in the certificate) with its validation records.
//
resource "aws_acm_certificate_validation" "app_cert_validation_process" {
certificate_arn         = aws_acm_certificate.app_cert.arn
validation_record_fqdns = [for record in aws_route53_record.app_cert_validation_records : record.fqdn]
}
// Reading https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate
// I don't see where the problem is.

如果重要的话,还有另一个资源依赖于此,那就是使用证书的ELB实例:

resource "aws_lb_listener" "api_https" {
load_balancer_arn = aws_lb.api.arn
port              = 443
protocol          = "HTTPS"
certificate_arn   = aws_acm_certificate_validation.app_cert_validation_process.certificate_arn
default_action {
type             = "forward"
target_group_arn = aws_lb_target_group.api.arn
}
}

我一直想追随https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate,这表明计划应该有效,我应该看到文本";(申请后已知(";在输出中。

根据我迄今为止的研究,我认为根本原因是AWS提供商无法/不会提前预测域验证选项。。。。然而,升级文档表明,虽然这只是应用后才知道的事情,但它不应该导致计划失败,我不应该需要任何丑陋的目标解决方案。

我试着使用dependens_on,但这对计划阶段没有帮助。

完整代码在https://gitlab.com/cameron.kerr.nz/recipe-app-api-devops/如果有帮助的话。

感谢阅读,Cameron

PS。我以前在中问过这个问题https://discuss.hashicorp.com/t/aws-acm-certificate-app-cert-domain-validation-options-is-a-set-of-object-known-only-after-apply/31952,但到目前为止没有回复。

TL;DR:这修复了我测试中的示例:

resource "aws_acm_certificate" "app_cert" {
-  domain_name       = aws_route53_record.app.fqdn
+  domain_name       = aws_route53_record.app.name
validation_method = "DNS"

但速度不那么快,这只是因为您在aws_route53_record.app中创建的记录与最终的fqdn同名。

根据aws_route53_record资源的文档,fqdn是使用区域域和name参数构建的。

为了进一步解释,在工作示例中,我们可以看到fqdn是未知的,但name是。这是aws_route53_record.app_cert_validation_records中的For_each不喜欢的。

# aws_route53_record.app will be created
+ resource "aws_route53_record" "app" {
+ allow_overwrite = (known after apply)
+ fqdn            = (known after apply)
+ id              = (known after apply)
+ name            = "foo.example.com"
+ records         = [
+ "xxxx.alb.amazon.com",
]
+ ttl             = 300
+ type            = "CNAME"
+ zone_id         = "XXXXXXXXXXX"
}

相关内容

  • 没有找到相关文章

最新更新