简体   繁体   English

AWS CDK 路由 53 + 证书配置不适用于 www 子域

[英]AWS CDK route 53 + certificate configuration not working for www subdomain

I am confused to how to create a certificate for the apex domain, which will also work with subdomain.我对如何为顶级域创建证书感到困惑,该证书也适用于子域。

I have created a basic website deployment CDK Construct and have been trying to fix it so it works for both www.example.com subdomain and example.com but I haven't been able to do that.我已经创建了一个基本的网站部署 CDK Construct 并一直在尝试修复它,以便它适用于www.example.com子域和 example.com 但我无法做到这一点。 With the current setup, www.example.com works but when I visit example.com it issues the following error:使用当前设置, www.example.com可以工作,但是当我访问 example.com 时,它会发出以下错误:

This site can't provide a secure connection example.com sent an invalid response.此站点无法提供安全连接示例。com 发送了无效响应。 ERR_SSL_PROTOCOL_ERROR ERR_SSL_PROTOCOL_ERROR

My guess is an issue with certificate creation but I am not sure.我的猜测是证书创建的问题,但我不确定。 Here is the partial CDK code, showing the zone, cloudFormation, certificate and route53 setup.这是部分 CDK 代码,显示了区域、cloudFormation、证书和 route53 设置。

    const siteDomain = "example.com"

    const zone = route53.HostedZone.fromLookup(this, "Zone", {
      domainName: siteDomain,
    });


    // TLS certificate
    const certificateArn = new acm.DnsValidatedCertificate(
      this,
      "SiteCertificate",
      {
        domainName: "*." + siteDomain,
        hostedZone: zone,
        region: "us-east-1", // Cloudfront only checks this region for certificates.
      }
    ).certificateArn;

    // Specifies you want viewers to use HTTPS & TLS v1.1 to request your objects
    const viewerCertificate = cloudfront.ViewerCertificate.fromAcmCertificate(
      {
        certificateArn: certificateArn,
        env: {
          region: Aws.REGION,
          account: Aws.ACCOUNT_ID,
        },
        node: this.node,
        stack: parent,
        metricDaysToExpiry: () => ...
      },
      {
        sslMethod: cloudfront.SSLMethod.SNI,
        securityPolicy: cloudfront.SecurityPolicyProtocol.TLS_V1_1_2016,
        aliases: ["*." + siteDomain],
      }
    );


    // CloudFront distribution
    const distribution = new cloudfront.CloudFrontWebDistribution(
      this,
      "SiteDistribution",
      {
        viewerCertificate,
        originConfigs: [
          {
            s3OriginSource: {
              ...
            },
            behaviors: [
              {
                ...
              },
            ],
          },
        ],
      }
    );

    // Route53 alias record for the CloudFront distribution
    const siteRecord = new route53.ARecord(this, "SiteAliasRecord", {
      recordName: siteDomain,
      target: route53.RecordTarget.fromAlias(
        new targets.CloudFrontTarget(distribution)
      ),
      zone,
    });

    new route53.CnameRecord(this, "SiteWWWAliasRecord", {
       recordName: "www." + siteDomain,
       domainName: siteDomain,
       zone,
    });


    // deploy/copy the website built website to s3 bucket
    this.deploy = new s3Deployment.BucketDeployment(
      this,
      CONSTRUCT_NAMES.bucket.deployment,
      {
        sources: [...],
        destinationBucket: this.websiteBucket,
        distribution,
        distributionPaths: ["/*"],
      }
    );
  }
}

After a successful deployment, when I visit the full domain www.example.com it shows the page but without the www subdomain the certificate issues an error.部署成功后,当我访问完整域www.example.com时,它会显示该页面,但没有 www 子域,证书会发出错误。 An ideas on how to fix this?关于如何解决这个问题的想法? I have to somehow set a correct certificate root domain value instead of a wildcard.我必须以某种方式设置正确的证书根域值而不是通配符。 Here is the route53 output after running the command:这是运行命令后的 route53 output:

在此处输入图像描述

Mhh try more like my working bits: Mhh 尝试更像我的工作位:

    const cloudFrontOAI = new cloudfront.OriginAccessIdentity(this, 'OAI');
siteBucket.grantRead(cloudFrontOAI.grantPrincipal);

const hostedZone = route53.HostedZone.fromLookup(this, 'Zone', {
  domainName: props.domainName,
});

const certificate = new certificatemanager.DnsValidatedCertificate(
  this,
  'certificate',
  {
    domainName: `${props.recordName === '' ? '' : props.recordName + '.'}${
      props.domainName
    }`,
    subjectAlternativeNames: props.alternativeRecordName
      ? [`${props.alternativeRecordName}.${props.domainName}`]
      : undefined,
    hostedZone,
    region: 'us-east-1',
  },
);

const distribution = new cloudfront.CloudFrontWebDistribution(
  this,
  'Distribution',
  {
    enableIpV6: false,
    originConfigs: [
      {
        s3OriginSource: {
          s3BucketSource: siteBucket,
          originAccessIdentity: cloudFrontOAI,
        },
        behaviors: [{ isDefaultBehavior: true }],
      },
    ],
    errorConfigurations: [
      {
        errorCode: 404,
        responseCode: 404,
        responsePagePath: '/index.html',
      },
    ],
    viewerCertificate: cloudfront.ViewerCertificate.fromAcmCertificate(
      certificate,
      {
        aliases: props.alternativeRecordName
          ? [
              `${props.recordName === '' ? '' : props.recordName + '.'}${
                props.domainName
              }`,
              `${props.alternativeRecordName}.${props.domainName}`,
            ]
          : [
              `${props.recordName === '' ? '' : props.recordName + '.'}${
                props.domainName
              }`,
            ],
      },
    ),
  },
);

Try using the newer Distribution construct rather than the older CloudFrontWebDistribution construct.尝试使用较新的Distribution构造而不是旧的CloudFrontWebDistribution构造。 From the docs :文档

The CloudFrontWebDistribution construct is the original construct written for working with CloudFront distributions. CloudFrontWebDistribution 构造是为使用 CloudFront 分配而编写的原始构造。 Users are encouraged to use the newer Distribution instead, as it has a simpler interface and receives new features faster.鼓励用户改用较新的分发版,因为它具有更简单的界面并且可以更快地接收新功能。

You also need to make sure you add both domain names to your distribution if you want to be able to access it via both URLs.如果您希望能够通过两个 URL 访问它,您还需要确保将两个域名都添加到您的分配中。 See below example, disregard the OAI portion if you don't need it:请参见下面的示例,如果不需要,请忽略 OAI 部分:

const siteDomain = "example.com";

const zone = route53.HostedZone.fromLookup(this, "Zone", {
  domainName: siteDomain,
});

const certificate = new acm.DnsValidatedCertificate(
  this,
  "SiteCertificate",
  {
    domainName: siteDomain,
    subjectAlternativeNames: ["*." + siteDomain],
    hostedZone: zone,
    region: "us-east-1", // Cloudfront only checks this region for certificates.
  }
);

const oai = new cloudfront.OriginAccessIdentity(this, "SiteOai");
this.websiteBucket.grantRead(oai);

const distribution = new cloudfront.Distribution(
  this, 
  "SiteDistribution", 
  {
    certificate,
    defaultBehavior: {
      origin: new origins.S3Origin(this.websiteBucket, {
        originAccessIdentity: oai
      }),
      ...
    },
    domainNames: [siteDomain, "www." + siteDomain],
    ...
  }
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM