From 0a5e3a0b294bb60e3bd375f18025aab239787ae5 Mon Sep 17 00:00:00 2001 From: Anton Ustyuzhanin Date: Fri, 1 Aug 2025 20:24:16 +0200 Subject: [PATCH] feat(cli): add sts:TagSession permission to trusted accounts --- .../test/api/bootstrap/bootstrap2.test.ts | 91 +++++++++++++++++++ .../lib/api/bootstrap/bootstrap-template.yaml | 20 +++- 2 files changed, 106 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/toolkit-lib/test/api/bootstrap/bootstrap2.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/bootstrap/bootstrap2.test.ts index 972a12ca8..832d92bb4 100644 --- a/packages/@aws-cdk/toolkit-lib/test/api/bootstrap/bootstrap2.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/api/bootstrap/bootstrap2.test.ts @@ -3,6 +3,8 @@ import * as deployStack from '../../../lib/api/deployments/deploy-stack'; import type { Stack } from '@aws-sdk/client-cloudformation'; import { CreatePolicyCommand, GetPolicyCommand } from '@aws-sdk/client-iam'; +import { Match, Template } from 'aws-cdk-lib/assertions'; + import { mockBootstrapStack, mockIAMClient, @@ -642,4 +644,93 @@ describe('Bootstrapping v2', () => { }, ); }); + + describe('contains sts:TagSession on trusted accounts', () => { + let template: Template; + + const iamRoleName = (name: string) => { + return { + 'Fn::Sub': `cdk-\${Qualifier}-${name}-\${AWS::AccountId}-\${AWS::Region}`, + }; + }; + + const statementWithCondition = (conditionName: string) => { + return Match.objectLike({ + 'Fn::If': Match.arrayWith([ + conditionName, + Match.objectLike({ + Action: Match.arrayWith(['sts:AssumeRole', 'sts:TagSession']), + }), + ]), + }); + }; + + beforeEach(async () => { + let rawTemplate: any; + mockDeployStack.mockImplementation((args: deployStack.DeployStackOptions) => { + rawTemplate = args.stack.template; + return Promise.resolve({ + type: 'did-deploy-stack', + noOp: false, + outputs: {}, + stackArn: 'arn:stack', + }); + }); + await bootstrapper.bootstrapEnvironment(env, sdk, {}); + template = Template.fromJSON(rawTemplate); + }); + + test('in the FilePublishingRole', async () => { + template.hasResource('AWS::IAM::Role', { + Properties: { + RoleName: iamRoleName('file-publishing-role'), + AssumeRolePolicyDocument: { + Statement: Match.arrayWith([ + statementWithCondition('HasTrustedAccounts'), + ]), + }, + }, + }); + }); + + test('in the ImagePublishingRole', async () => { + template.hasResource('AWS::IAM::Role', { + Properties: { + RoleName: iamRoleName('image-publishing-role'), + AssumeRolePolicyDocument: { + Statement: Match.arrayWith([ + statementWithCondition('HasTrustedAccounts'), + ]), + }, + }, + }); + }); + + test('in the LookupRole', async () => { + template.hasResource('AWS::IAM::Role', { + Properties: { + RoleName: iamRoleName('lookup-role'), + AssumeRolePolicyDocument: { + Statement: Match.arrayWith([ + statementWithCondition('HasTrustedAccountsForLookup'), + statementWithCondition('HasTrustedAccounts'), + ]), + }, + }, + }); + }); + + test('in the DeploymentActionRole', async () => { + template.hasResource('AWS::IAM::Role', { + Properties: { + RoleName: iamRoleName('deploy-role'), + AssumeRolePolicyDocument: { + Statement: Match.arrayWith([ + statementWithCondition('HasTrustedAccounts'), + ]), + }, + }, + }); + }); + }); }); diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml index 9871a73fa..995a0f746 100644 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml @@ -310,7 +310,9 @@ Resources: Ref: AWS::AccountId - Fn::If: - HasTrustedAccounts - - Action: sts:AssumeRole + - Action: + - sts:AssumeRole + - sts:TagSession Effect: Allow Principal: AWS: @@ -340,7 +342,9 @@ Resources: Ref: AWS::AccountId - Fn::If: - HasTrustedAccounts - - Action: sts:AssumeRole + - Action: + - sts:AssumeRole + - sts:TagSession Effect: Allow Principal: AWS: @@ -370,7 +374,9 @@ Resources: Ref: AWS::AccountId - Fn::If: - HasTrustedAccountsForLookup - - Action: sts:AssumeRole + - Action: + - sts:AssumeRole + - sts:TagSession Effect: Allow Principal: AWS: @@ -378,7 +384,9 @@ Resources: - Ref: AWS::NoValue - Fn::If: - HasTrustedAccounts - - Action: sts:AssumeRole + - Action: + - sts:AssumeRole + - sts:TagSession Effect: Allow Principal: AWS: @@ -485,7 +493,9 @@ Resources: Ref: AWS::AccountId - Fn::If: - HasTrustedAccounts - - Action: sts:AssumeRole + - Action: + - sts:AssumeRole + - sts:TagSession Effect: Allow Principal: AWS: