Skip to content

Commit 513d9fb

Browse files
authored
feat(core): add validations for export name in CfnOutput (#28575)
Closes #28563. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent baf2bfb commit 513d9fb

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

packages/aws-cdk-lib/cloudformation-include/test/valid-templates.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ describe('CDK Include', () => {
727727
const output = cfnTemplate.getOutput('Output1');
728728
output.value = 'a mutated value';
729729
output.description = undefined;
730-
output.exportName = 'an export';
730+
output.exportName = 'an-export';
731731
output.condition = new core.CfnCondition(stack, 'MyCondition', {
732732
expression: core.Fn.conditionIf('AlwaysFalseCond', core.Aws.NO_VALUE, true),
733733
});
@@ -755,7 +755,7 @@ describe('CDK Include', () => {
755755
"Output1": {
756756
"Value": "a mutated value",
757757
"Export": {
758-
"Name": "an export",
758+
"Name": "an-export",
759759
},
760760
"Condition": "MyCondition",
761761
},

packages/aws-cdk-lib/core/lib/cfn-output.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,19 @@ export class CfnOutput extends CfnElement {
178178
}
179179

180180
private validateOutput(): string[] {
181-
if (this._exportName && !Token.isUnresolved(this._exportName) && this._exportName.length > 255) {
182-
return [`Export name cannot exceed 255 characters (got ${this._exportName.length} characters)`];
181+
const errors: string[] = [];
182+
if (this._exportName !== undefined && !Token.isUnresolved(this._exportName)) {
183+
if (this._exportName.length === 0) {
184+
errors.push('Export name cannot be empty');
185+
}
186+
if (this._exportName.length > 255) {
187+
errors.push(`Export name cannot exceed 255 characters (got ${this._exportName.length} characters)`);
188+
}
189+
if (!/^[A-Za-z0-9-:]*$/.test(this._exportName)) {
190+
errors.push(`Export name must only include alphanumeric characters, colons, or hyphens (got '${this._exportName}')`);
191+
}
183192
}
184-
return [];
193+
return errors;
185194
}
186195
}
187196

packages/aws-cdk-lib/core/test/output.test.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,44 @@ describe('output', () => {
140140
const errors = output.node.validate();
141141

142142
expect(errors).toEqual([
143-
expect.stringContaining('Export name cannot exceed 255 characters'),
143+
expect.stringContaining('Export name cannot exceed 255 characters (got 260 characters)'),
144+
]);
145+
});
146+
147+
test('Verify zero length of export name', () => {
148+
const output = new CfnOutput(stack, 'SomeOutput', { value: 'x', exportName: '' });
149+
const errors = output.node.validate();
150+
151+
expect(errors).toEqual([
152+
expect.stringContaining('Export name cannot be empty'),
153+
]);
154+
});
155+
156+
test('throw if export name has invalid strings (space)', () => {
157+
const output = new CfnOutput(stack, 'SomeOutput', { value: 'x', exportName: 'SOME INVALID EXPORT NAME' });
158+
const errors = output.node.validate();
159+
160+
expect(errors).toEqual([
161+
expect.stringContaining('Export name must only include alphanumeric characters, colons, or hyphens (got \'SOME INVALID EXPORT NAME\''),
162+
]);
163+
});
164+
165+
test('throw if export name has invalid strings (underscore)', () => {
166+
const output = new CfnOutput(stack, 'SomeOutput', { value: 'x', exportName: 'SOME_INVALID_EXPORT_NAME' });
167+
const errors = output.node.validate();
168+
169+
expect(errors).toEqual([
170+
expect.stringContaining('Export name must only include alphanumeric characters, colons, or hyphens (got \'SOME_INVALID_EXPORT_NAME\''),
171+
]);
172+
});
173+
174+
test('throw if export name exceeds maximum length and has invalid strings', () => {
175+
const output = new CfnOutput(stack, 'SomeOutput', { value: 'x', exportName: ' '.repeat(260) });
176+
const errors = output.node.validate();
177+
178+
expect(errors).toEqual([
179+
expect.stringContaining('Export name cannot exceed 255 characters (got 260 characters)'),
180+
expect.stringContaining(`Export name must only include alphanumeric characters, colons, or hyphens (got '${' '.repeat(260)}'`),
144181
]);
145182
});
146183
});

0 commit comments

Comments
 (0)