Skip to content

Commit abd1768

Browse files
authored
fix(stack): check stack tags for deploy-time values (#31457)
Stack tags are not rendered to the template, but instead are passed via API call. Verify that stack tags do not contain unresolved values, as they won't work. Closes #28017. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent a2d42d2 commit abd1768

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

packages/aws-cdk-lib/core/lib/stack-synthesizers/_shared.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Node, IConstruct } from 'constructs';
33
import { ISynthesisSession } from './types';
44
import * as cxschema from '../../../cloud-assembly-schema';
55
import { Stack } from '../stack';
6+
import { Token } from '../token';
67

78
/**
89
* Shared logic of writing stack artifact to the Cloud Assembly
@@ -20,10 +21,20 @@ export function addStackArtifactToAssembly(
2021
stackProps: Partial<cxschema.AwsCloudFormationStackProperties>,
2122
additionalStackDependencies: string[]) {
2223

24+
const stackTags = stack.tags.tagValues();
25+
2326
// nested stack tags are applied at the AWS::CloudFormation::Stack resource
2427
// level and are not needed in the cloud assembly.
25-
if (stack.tags.hasTags()) {
26-
stack.node.addMetadata(cxschema.ArtifactMetadataEntryType.STACK_TAGS, stack.tags.renderTags());
28+
if (Object.entries(stackTags).length > 0) {
29+
for (const [k, v] of Object.entries(stackTags)) {
30+
if (Token.isUnresolved(k) || Token.isUnresolved(v)) {
31+
throw new Error(`Stack tags may not contain deploy-time values (tag: ${k}=${v}). Apply tags containing deploy-time values to resources only, avoid tagging stacks.`);
32+
}
33+
}
34+
35+
stack.node.addMetadata(
36+
cxschema.ArtifactMetadataEntryType.STACK_TAGS,
37+
Object.entries(stackTags).map(([key, value]) => ({ Key: key, Value: value })));
2738
}
2839

2940
const deps = [
@@ -46,7 +57,7 @@ export function addStackArtifactToAssembly(
4657
const properties: cxschema.AwsCloudFormationStackProperties = {
4758
templateFile: stack.templateFile,
4859
terminationProtection: stack.terminationProtection,
49-
tags: nonEmptyDict(stack.tags.tagValues()),
60+
tags: nonEmptyDict(stackTags),
5061
validateOnSynth: session.validateOnSynth,
5162
notificationArns: stack._notificationArns,
5263
...stackProps,

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

+15
Original file line numberDiff line numberDiff line change
@@ -2075,6 +2075,21 @@ describe('stack', () => {
20752075
expect(asm.getStackArtifact(stack2.artifactId).tags).toEqual(expected);
20762076
});
20772077

2078+
test('stack tags may not contain tokens', () => {
2079+
// GIVEN
2080+
const app = new App({
2081+
stackTraces: false,
2082+
});
2083+
2084+
const stack = new Stack(app, 'stack1', {
2085+
tags: {
2086+
foo: Lazy.string({ produce: () => 'lazy' }),
2087+
},
2088+
});
2089+
2090+
expect(() => app.synth()).toThrow(/Stack tags may not contain deploy-time values/);
2091+
});
2092+
20782093
test('stack notification arns are reflected in the stack artifact properties', () => {
20792094
// GIVEN
20802095
const NOTIFICATION_ARNS = ['arn:aws:sns:bermuda-triangle-1337:123456789012:MyTopic'];

0 commit comments

Comments
 (0)