跨账户CDK部署:如何自动获取ACM证书验证域名?
跨账户部署CloudFront站点时自动完成ACM证书DNS验证
我正尝试通过CDK将CloudFront站点部署到HostedZone所在的另一个AWS账户。目前已经能创建ACM证书,但CloudFormation部署时必须手动在主账户(DNS账户)添加验证CNAME记录才能继续。我想用cdk-cross-account-route53构造移除这个手动步骤,它支持委托账户创建CNAME记录,但我不知道怎么获取ACM证书自动生成的验证记录和对应值,请问该怎么实现?
现有代码片段
DNS Stack
export class DnsStack extends cdk.Stack { constructor(scope: Construct, id: string, props: DnsStackProps) { super(scope, id, props); const zone = route53.PublicHostedZone.fromHostedZoneId( this, "delegatedDnsZone", "zoneId", ); new CrossAccountRoute53Role(this, "WebRoute53Role", { roleName: props.configurationValues.dnsAssumeRole, assumedBy: new iam.AccountPrincipal(props.configurationValues.webAccount), zone: zone, records: [ { domainNames: [ props.configurationValues.uiCustomDomain, "*." + props.configurationValues.uiCustomDomain, ], }, ], }); } }
UI Stack
this.acmCertificate = new acm.Certificate(this, "Certificate", { domainName: props.configurationValues.uiCustomDomain, certificateName: "AWS Test Cert", validation: acm.CertificateValidation.fromDns(), }); this.cloudFrontDistribution = new cloudfront.Distribution( this, "CfDistribution", { webAclId: "acl", defaultBehavior: { origin: new origins.S3Origin(this.deploymentBucket), }, certificate: this.acmCertificate, errorResponses: [ { httpStatus: 403, responseHttpStatus: 200, ttl: cdk.Duration.seconds(10), responsePagePath: "/index.html", }, { httpStatus: 404, responseHttpStatus: 200, ttl: cdk.Duration.seconds(10), responsePagePath: "/index.html", }, ], domainNames: [props.configurationValues.uiCustomDomain], }, ); new CrossAccountRoute53RecordSet(this, "ARecord", { delegationRoleName: props.configurationValues.dnsAssumeRole, delegationRoleAccount: props.configurationValues.dnsAccount, // The account that contains the zone and role hostedZoneId: props.configurationValues.hostedZoneId, resourceRecordSets: [ { Name: props.configurationValues.uiCustomDomain, Type: "A", AliasTarget: { DNSName: this.cloudFrontDistribution.distributionDomainName, HostedZoneId: "Z2FDTNDATAQYW2", // This is always the Hosted Zone Id for Cloudfront EvaluateTargetHealth: false, }, }, ], });
解决方案
要自动完成跨账户的ACM证书DNS验证,核心是获取ACM证书生成的验证记录集,再通过CrossAccountRoute53RecordSet在DNS账户的HostedZone中创建这些CNAME记录。具体修改如下:
1. 调整DNS栈的权限配置
确保DNS栈中创建的角色允许UI账户创建CNAME类型的Route53记录(移除原有的域名限制,因为ACM验证记录是随机生成的子域名):
export class DnsStack extends cdk.Stack { constructor(scope: Construct, id: string, props: DnsStackProps) { super(scope, id, props); const zone = route53.PublicHostedZone.fromHostedZoneId( this, "delegatedDnsZone", props.configurationValues.hostedZoneId, // 改用配置传入的ZoneId,避免硬编码 ); new CrossAccountRoute53Role(this, "WebRoute53Role", { roleName: props.configurationValues.dnsAssumeRole, assumedBy: new iam.AccountPrincipal(props.configurationValues.webAccount), zone: zone, // 允许创建CNAME类型记录,适配ACM验证需求 records: [{ type: route53.RecordType.CNAME }], }); } }
2. 在UI栈中自动创建验证CNAME记录
通过ACM证书的certificateValidationRecords属性获取自动生成的验证记录,再用CrossAccountRoute53RecordSet同步到DNS账户:
this.acmCertificate = new acm.Certificate(this, "Certificate", { domainName: props.configurationValues.uiCustomDomain, certificateName: "AWS Test Cert", validation: acm.CertificateValidation.fromDns(), }); // 提取ACM验证记录并创建跨账户CNAME记录 const validationRecords = this.acmCertificate.certificateValidationRecords; new CrossAccountRoute53RecordSet(this, "AcmValidationRecords", { delegationRoleName: props.configurationValues.dnsAssumeRole, delegationRoleAccount: props.configurationValues.dnsAccount, hostedZoneId: props.configurationValues.hostedZoneId, resourceRecordSets: validationRecords.map(record => ({ Name: record.domainName, Type: "CNAME", TTL: 300, ResourceRecords: [{ Value: record.resourceRecordValue }], })), }); // 原CloudFront和A记录代码保持不变 this.cloudFrontDistribution = new cloudfront.Distribution( this, "CfDistribution", { webAclId: "acl", defaultBehavior: { origin: new origins.S3Origin(this.deploymentBucket), }, certificate: this.acmCertificate, errorResponses: [ { httpStatus: 403, responseHttpStatus: 200, ttl: cdk.Duration.seconds(10), responsePagePath: "/index.html", }, { httpStatus: 404, responseHttpStatus: 200, ttl: cdk.Duration.seconds(10), responsePagePath: "/index.html", }, ], domainNames: [props.configurationValues.uiCustomDomain], }, ); new CrossAccountRoute53RecordSet(this, "ARecord", { delegationRoleName: props.configurationValues.dnsAssumeRole, delegationRoleAccount: props.configurationValues.dnsAccount, hostedZoneId: props.configurationValues.hostedZoneId, resourceRecordSets: [ { Name: props.configurationValues.uiCustomDomain, Type: "A", AliasTarget: { DNSName: this.cloudFrontDistribution.distributionDomainName, HostedZoneId: "Z2FDTNDATAQYW2", EvaluateTargetHealth: false, }, }, ], });
关键说明
certificateValidationRecords是ACM证书构造暴露的属性,包含所有需要的DNS验证记录(随机子域名和对应的值)。- DNS栈中放宽了角色权限,允许创建CNAME记录,确保UI账户能写入验证记录。
- 验证记录的TTL设置为300秒(AWS推荐的默认值),符合验证时效要求。
内容的提问来源于stack exchange,提问作者David Jacobsen
相关产品推荐
相关产品推荐

