Skip to content

Commit

Permalink
fix(stack): check stack tags for deploy-time values (#31457)
Browse files Browse the repository at this point in the history
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*
  • Loading branch information
rix0rrr authored Sep 25, 2024
1 parent a2d42d2 commit abd1768
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
17 changes: 14 additions & 3 deletions packages/aws-cdk-lib/core/lib/stack-synthesizers/_shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Node, IConstruct } from 'constructs';
import { ISynthesisSession } from './types';
import * as cxschema from '../../../cloud-assembly-schema';
import { Stack } from '../stack';
import { Token } from '../token';

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

const stackTags = stack.tags.tagValues();

// nested stack tags are applied at the AWS::CloudFormation::Stack resource
// level and are not needed in the cloud assembly.
if (stack.tags.hasTags()) {
stack.node.addMetadata(cxschema.ArtifactMetadataEntryType.STACK_TAGS, stack.tags.renderTags());
if (Object.entries(stackTags).length > 0) {
for (const [k, v] of Object.entries(stackTags)) {
if (Token.isUnresolved(k) || Token.isUnresolved(v)) {
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.`);
}
}

stack.node.addMetadata(
cxschema.ArtifactMetadataEntryType.STACK_TAGS,
Object.entries(stackTags).map(([key, value]) => ({ Key: key, Value: value })));
}

const deps = [
Expand All @@ -46,7 +57,7 @@ export function addStackArtifactToAssembly(
const properties: cxschema.AwsCloudFormationStackProperties = {
templateFile: stack.templateFile,
terminationProtection: stack.terminationProtection,
tags: nonEmptyDict(stack.tags.tagValues()),
tags: nonEmptyDict(stackTags),
validateOnSynth: session.validateOnSynth,
notificationArns: stack._notificationArns,
...stackProps,
Expand Down
15 changes: 15 additions & 0 deletions packages/aws-cdk-lib/core/test/stack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2075,6 +2075,21 @@ describe('stack', () => {
expect(asm.getStackArtifact(stack2.artifactId).tags).toEqual(expected);
});

test('stack tags may not contain tokens', () => {
// GIVEN
const app = new App({
stackTraces: false,
});

const stack = new Stack(app, 'stack1', {
tags: {
foo: Lazy.string({ produce: () => 'lazy' }),
},
});

expect(() => app.synth()).toThrow(/Stack tags may not contain deploy-time values/);
});

test('stack notification arns are reflected in the stack artifact properties', () => {
// GIVEN
const NOTIFICATION_ARNS = ['arn:aws:sns:bermuda-triangle-1337:123456789012:MyTopic'];
Expand Down

0 comments on commit abd1768

Please # to comment.