如何在Terraform中仅将已验证的ACM证书附加到ALB?
我正在使用Terraform通过Amazon Certificate Manager(ACM)创建公证书,代码如下:
resource "aws_acm_certificate" "wc_mydomain_com" { domain_name = "*.mydomain.com" validation_method = "DNS" lifecycle { create_before_destroy = true } }
该代码可正确创建对应域名的证书,但需手动配置DNS记录完成验证。
我需要将此证书附加到Application Load Balancer(ALB),使用的代码如下:
resource "aws_lb_listener_certificate" "wc_mydomain_com_attachment" { listener_arn = <HTTPS监听器引用> certificate_arn = aws_acm_certificate.wc_mydomain_com.arn }
若证书已验证,这段代码可正常工作,但因验证为手动操作,部署时常报错,错误信息如下:
Error: creating ELB (Elastic Load Balancing) Listener Certificate:
operation error Elastic Load Balancing v2: AddListenerCertificates,
https response error StatusCode: 400, RequestID: XXX, api error
UnsupportedCertificate: The certificate 'arn:aws:acm:[REGION]:[ACCOUNT
ID]:certificate/[ID]' must have a fully-qualified domain name, a
supported signature, and a supported key size.
我尝试过两种方案:
- 使用data source
aws_acm_certificate查询状态为ISSUED的证书; - 使用
aws_acm_certificate_validation,但它的阻塞行为不符合需求;
我曾想在wc_mydomain_com_attachment中使用count,但计划阶段无法确定count值导致报错。如何实现仅在证书已验证时才将其附加到监听器,未验证时不执行该操作?
方案一:结合terraform_data与count实现条件创建
利用terraform_data在执行阶段获取证书实时状态,绕过计划阶段的静态检查,再通过count控制是否创建证书附加资源:
# 保留原有的ACM证书资源 resource "aws_acm_certificate" "wc_mydomain_com" { domain_name = "*.mydomain.com" validation_method = "DNS" lifecycle { create_before_destroy = true } } # 用于获取证书实时状态的中间资源 resource "terraform_data" "cert_status_check" { input = aws_acm_certificate.wc_mydomain_com.status } # 仅当证书状态为ISSUED时创建监听器证书附加资源 resource "aws_lb_listener_certificate" "wc_mydomain_com_attachment" { count = terraform_data.cert_status_check.output == "ISSUED" ? 1 : 0 listener_arn = <HTTPS监听器引用> # 替换为实际的HTTPS监听器ARN certificate_arn = aws_acm_certificate.wc_mydomain_com.arn }
原理:
terraform_data会在执行阶段拉取证书的当前状态,避免计划阶段因状态不确定导致的报错;count根据状态值判断:状态为ISSUED时创建1个实例,否则不创建;- 手动完成DNS验证后,重新执行
terraform apply,Terraform会检测到状态变更并自动创建附加资源。
方案二:使用data资源查询已签发证书配合count
通过data "aws_acm_certificate"过滤已签发的证书,再用count控制资源创建:
data "aws_acm_certificate" "issued_wc_mydomain_com" { domain_name = "*.mydomain.com" statuses = ["ISSUED"] most_recent = true } resource "aws_lb_listener_certificate" "wc_mydomain_com_attachment" { count = length(data.aws_acm_certificate.issued_wc_mydomain_com.arn) > 0 ? 1 : 0 listener_arn = <HTTPS监听器引用> # 替换为实际的HTTPS监听器ARN certificate_arn = data.aws_acm_certificate.issued_wc_mydomain_com.arn }
注意:
- 该方案依赖已存在的
ISSUED状态证书,若证书未验证,data资源会返回空,但count会判断不创建附加资源,避免报错; - 首次创建证书后,需手动完成验证并重新执行
terraform apply,此时data资源能查询到已签发证书,才会创建附加资源。
内容的提问来源于stack exchange,提问作者BAD_SEED

