Terraform with API-Gateway、Route53 和 SSL 证书相互依赖问题
Terraform with API-Gateway, Route53, and SSL Certification interdependency problem
我似乎无法使用 terraform 从在 API-Gateway、Route53 上工作的 ACM 获得 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: Error creating API Gateway
Domain Name: BadRequestException: Unable to associate certificate
arn:aws:acm:us-east-1:yyyy:certificate/zzzz with CloudFront. This
error may prevent the domain name audit-log.taspli.com from being used
in API Gateway for up to 40 minutes. Please ensure the certificate
domain name matches the requested domain name, and that this user has
permission to call cloudfront:UpdateDistribution on '*' resources.
status code: 400, request id: xxxx
我似乎已经通过将证书验证记录添加到根域而不是子域来解决问题。因此打破了循环依赖。
问题似乎是没有证书就无法创建子域,没有子域就无法验证证书。于是局势陷入僵局,无法解决。
您可以手动创建子域,但是如果您必须手动解决问题,那么自动化又有什么意义呢。
所以我尝试将证书验证记录添加到根。突然它开始工作,因为根域是在项目外部创建的。一种可以在外部处理的全球基础设施项目。然后,您的个人项目可以根据具体情况从该基础设施中脱离出来。
这是有效的 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"
}
}
对我来说,我更改了 aws_route53_record.cert_validation
资源并且有效:
resource "aws_route53_record" "cert_validation" {
name = "${tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_name}"
type = "${tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_type}"
zone_id = "${aws_route53_record.sub_domain.zone_id}"
records = ["${tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_value}"]
ttl = 60
}
我似乎无法使用 terraform 从在 API-Gateway、Route53 上工作的 ACM 获得 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: Error creating API Gateway Domain Name: BadRequestException: Unable to associate certificate arn:aws:acm:us-east-1:yyyy:certificate/zzzz with CloudFront. This error may prevent the domain name audit-log.taspli.com from being used in API Gateway for up to 40 minutes. Please ensure the certificate domain name matches the requested domain name, and that this user has permission to call cloudfront:UpdateDistribution on '*' resources. status code: 400, request id: xxxx
我似乎已经通过将证书验证记录添加到根域而不是子域来解决问题。因此打破了循环依赖。
问题似乎是没有证书就无法创建子域,没有子域就无法验证证书。于是局势陷入僵局,无法解决。
您可以手动创建子域,但是如果您必须手动解决问题,那么自动化又有什么意义呢。
所以我尝试将证书验证记录添加到根。突然它开始工作,因为根域是在项目外部创建的。一种可以在外部处理的全球基础设施项目。然后,您的个人项目可以根据具体情况从该基础设施中脱离出来。
这是有效的 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"
}
}
对我来说,我更改了 aws_route53_record.cert_validation
资源并且有效:
resource "aws_route53_record" "cert_validation" {
name = "${tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_name}"
type = "${tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_type}"
zone_id = "${aws_route53_record.sub_domain.zone_id}"
records = ["${tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_value}"]
ttl = 60
}