diff --git a/packages/aws-cdk-lib/aws-cloudfront/README.md b/packages/aws-cdk-lib/aws-cloudfront/README.md index 965e3cbac7f69..69dd28e093cc1 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/README.md +++ b/packages/aws-cdk-lib/aws-cloudfront/README.md @@ -115,6 +115,16 @@ new cloudfront.Distribution(this, 'myDist', { }); ``` +#### Moving an alternate domain name to a different distribution + +When you try to add an alternate domain name to a distribution but the alternate domain name is already in use on a different distribution, you get a `CNAMEAlreadyExists` error (One or more of the CNAMEs you provided are already associated with a different resource). + +In that case, you might want to move the existing alternate domain name from one distribution (the source distribution) to another (the target distribution). The following steps are an overview of the process. For more information, see [Moving an alternate domain name to a different distribution](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/alternate-domain-names-move.html). + +1. Deploy the stack with the target distribution. The `certificate` property must be specified but the `domainNames` should be absent. +2. Move the alternate domain name by running CloudFront `associate-alias` command. For the example and preconditions, see the AWS documentation above. +3. Specify the `domainNames` property with the alternative domain name, then deploy the stack again to resolve the drift at the alternative domain name. + #### Cross Region Certificates > **This feature is currently experimental** diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts index 336affec8b862..c8f23e40d210f 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts @@ -129,7 +129,10 @@ export interface DistributionProps { * * If you want to use your own domain name, such as www.example.com, instead of the cloudfront.net domain name, * you can add an alternate domain name to your distribution. If you attach a certificate to the distribution, - * you must add (at least one of) the domain names of the certificate to this list. + * you should add (at least one of) the domain names of the certificate to this list. + * + * When you want to move a domain name between distributions, you can associate a certificate without specifying any domain names. + * For more information, see the _Moving an alternate domain name to a different distribution_ section in the README. * * @default - The distribution will only support the default generated name (e.g., d111111abcdef8.cloudfront.net) */ @@ -318,10 +321,6 @@ export class Distribution extends Resource implements IDistribution { if (!Token.isUnresolved(certificateRegion) && certificateRegion !== 'us-east-1') { throw new Error(`Distribution certificates must be in the us-east-1 region and the certificate you provided is in ${certificateRegion}.`); } - - if ((props.domainNames ?? []).length === 0) { - throw new Error('Must specify at least one domain name to use a certificate with a distribution'); - } } const originId = this.addOrigin(props.defaultBehavior.origin); diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts index abd135a418632..7ad33d02a336e 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts @@ -457,23 +457,22 @@ describe('certificates', () => { }).toThrow(/Distribution certificates must be in the us-east-1 region and the certificate you provided is in eu-west-1./); }); - test('adding a certificate without a domain name throws', () => { + test('adding a certificate without a domain name', () => { const certificate = acm.Certificate.fromCertificateArn(stack, 'Cert', 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012'); - expect(() => { - new Distribution(stack, 'Dist1', { - defaultBehavior: { origin: defaultOrigin() }, - certificate, - }); - }).toThrow(/Must specify at least one domain name/); + new Distribution(stack, 'Dist1', { + defaultBehavior: { origin: defaultOrigin() }, + certificate, + }); - expect(() => { - new Distribution(stack, 'Dist2', { - defaultBehavior: { origin: defaultOrigin() }, - domainNames: [], - certificate, - }); - }).toThrow(/Must specify at least one domain name/); + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::Distribution', { + DistributionConfig: { + Aliases: Match.absent(), + ViewerCertificate: { + AcmCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012', + }, + }, + }); }); test('use the TLSv1.2_2021 security policy by default', () => {