You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨账户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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:49:53