Skip to content

Commit 2d7e3c0

Browse files
authored
fix(acm): domainName length constraint failure due to Tokens (#23567)
When creating Certificate where the domainName property contains tokens, the length check can fail. This is because the string encoded token can cause the length to exceed the maximum even if token will resolve to something shorter. To solve this the property is checked for token as provided in the design guidelines: https://github.com/aws/aws-cdk/blob/b14a3d1dc4c4508ad354d954b9480e9c2c64401c/docs/DESIGN_GUIDELINES.md#throwing-exceptions fixes #23565 ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Construct Runtime Dependencies: * [ ] This PR adds new construct runtime dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-construct-runtime-dependencies) ### New Features * [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? // No fix involves only synth time code. * [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? // No changes to integration tests where made. *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 0f4f985 commit 2d7e3c0

File tree

4 files changed

+77
-4
lines changed

4 files changed

+77
-4
lines changed

packages/@aws-cdk/aws-certificatemanager/lib/certificate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ export class Certificate extends CertificateBase implements ICertificate {
242242
}
243243

244244
// check if domain name is 64 characters or less
245-
if (props.domainName.length > 64) {
245+
if (!Token.isUnresolved(props.domainName) && props.domainName.length > 64) {
246246
throw new Error('Domain name must be 64 characters or less');
247247
}
248248

packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as iam from '@aws-cdk/aws-iam';
33
import * as lambda from '@aws-cdk/aws-lambda';
44
import * as route53 from '@aws-cdk/aws-route53';
55
import * as cdk from '@aws-cdk/core';
6+
import { Token } from '@aws-cdk/core';
67
import { Construct } from 'constructs';
78
import { CertificateProps, ICertificate } from './certificate';
89
import { CertificateBase } from './certificate-base';
@@ -87,7 +88,7 @@ export class DnsValidatedCertificate extends CertificateBase implements ICertifi
8788
this.region = props.region;
8889
this.domainName = props.domainName;
8990
// check if domain name is 64 characters or less
90-
if (this.domainName.length > 64) {
91+
if (!Token.isUnresolved(props.domainName) && props.domainName.length > 64) {
9192
throw new Error('Domain name must be 64 characters or less');
9293
}
9394
this.normalizedZoneName = props.hostedZone.zoneName;

packages/@aws-cdk/aws-certificatemanager/test/certificate.test.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Template, Match } from '@aws-cdk/assertions';
22
import * as route53 from '@aws-cdk/aws-route53';
3-
import { Duration, Lazy, Stack } from '@aws-cdk/core';
3+
import { Aws, Duration, Lazy, Stack } from '@aws-cdk/core';
44
import { Certificate, CertificateValidation } from '../lib';
55

66
test('apex domain selection by default', () => {
@@ -91,6 +91,37 @@ test('throws when domain name is longer than 64 characters', () => {
9191
}).toThrow(/Domain name must be 64 characters or less/);
9292
});
9393

94+
test('does not throw when domain name is longer than 64 characters with tokens', () => {
95+
const stack = new Stack();
96+
const embededToken = Aws.REGION;
97+
const baseDomain = 'a'.repeat(65-embededToken.length);
98+
const domainName = `${embededToken}${baseDomain}`;
99+
new Certificate(stack, 'Certificate', {
100+
domainName,
101+
validation: CertificateValidation.fromEmail({
102+
[domainName]: 'example.com',
103+
}),
104+
});
105+
106+
const domainNameJoin = {
107+
'Fn::Join': [
108+
'',
109+
[
110+
{
111+
Ref: 'AWS::Region',
112+
},
113+
baseDomain,
114+
],
115+
],
116+
};
117+
Template.fromStack(stack).hasResourceProperties('AWS::CertificateManager::Certificate', {
118+
DomainName: domainNameJoin,
119+
DomainValidationOptions: [{
120+
DomainName: domainNameJoin,
121+
ValidationDomain: 'example.com',
122+
}],
123+
});
124+
});
94125

95126
test('needs validation domain supplied if domain contains a token', () => {
96127
const stack = new Stack();

packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.test.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Template } from '@aws-cdk/assertions';
22
import * as iam from '@aws-cdk/aws-iam';
33
import { HostedZone, PublicHostedZone } from '@aws-cdk/aws-route53';
4-
import { App, Stack, Token, Tags, RemovalPolicy } from '@aws-cdk/core';
4+
import { App, Stack, Token, Tags, RemovalPolicy, Aws } from '@aws-cdk/core';
55
import { DnsValidatedCertificate } from '../lib/dns-validated-certificate';
66

77
test('creates CloudFormation Custom Resource', () => {
@@ -252,6 +252,47 @@ test('throws when domain name is longer than 64 characters', () => {
252252
}).toThrow(/Domain name must be 64 characters or less/);
253253
}),
254254

255+
test('does not throw when domain name is longer than 64 characters with tokens', () => {
256+
const stack = new Stack();
257+
const zoneName = 'example.com';
258+
const exampleDotComZone = new PublicHostedZone(stack, 'ExampleDotCom', {
259+
zoneName,
260+
});
261+
const embededToken = Aws.REGION;
262+
const baseSubDomain = 'a'.repeat(65 - embededToken.length -1 -zoneName.length);
263+
const domainName = `${embededToken}${baseSubDomain}.${zoneName}`;
264+
265+
new DnsValidatedCertificate(stack, 'Cert', {
266+
domainName,
267+
hostedZone: exampleDotComZone,
268+
transparencyLoggingEnabled: false,
269+
});
270+
271+
Template.fromStack(stack).hasResourceProperties('AWS::CloudFormation::CustomResource', {
272+
ServiceToken: {
273+
'Fn::GetAtt': [
274+
'CertCertificateRequestorFunction98FDF273',
275+
'Arn',
276+
],
277+
},
278+
DomainName: {
279+
'Fn::Join': [
280+
'',
281+
[
282+
{
283+
Ref: 'AWS::Region',
284+
},
285+
`${baseSubDomain}.${zoneName}`,
286+
],
287+
],
288+
},
289+
HostedZoneId: {
290+
Ref: 'ExampleDotCom4D1B83AA',
291+
},
292+
CertificateTransparencyLoggingPreference: 'DISABLED',
293+
});
294+
});
295+
255296
test('test transparency logging settings is passed to the custom resource', () => {
256297
const stack = new Stack();
257298

0 commit comments

Comments
 (0)