@@ -59,11 +59,20 @@ function createStack() {
5959 traceArtifactsBucket,
6060 attachmentsBucket,
6161 } ) ;
62- sessionRole . grantAssumeToComputeRole ( computeRole ) ;
6362
6463 return { stack, template : Template . fromStack ( stack ) , computeRole, sessionRole } ;
6564}
6665
66+ function findComputeRolePolicy ( template : Template ) {
67+ const policies = template . findResources ( 'AWS::IAM::Policy' ) ;
68+ return Object . entries ( policies ) . find ( ( [ id ] ) => id . includes ( 'ComputeRole' ) ) ! [ 1 ] ;
69+ }
70+
71+ function findSessionRoleTrust ( template : Template ) {
72+ const roles = template . findResources ( 'AWS::IAM::Role' ) ;
73+ return Object . entries ( roles ) . find ( ( [ id ] ) => id . includes ( 'AgentSessionRole' ) ) ! [ 1 ] ;
74+ }
75+
6776describe ( 'AgentSessionRole construct' , ( ) => {
6877 let template : Template ;
6978
@@ -75,8 +84,9 @@ describe('AgentSessionRole construct', () => {
7584 template . hasResourceProperties ( 'AWS::IAM::Role' , {
7685 AssumeRolePolicyDocument : {
7786 Statement : Match . arrayWith ( [
78- Match . objectLike ( { Action : 'sts:AssumeRole' } ) ,
79- Match . objectLike ( { Action : 'sts:TagSession' } ) ,
87+ Match . objectLike ( {
88+ Action : Match . arrayWith ( [ 'sts:AssumeRole' , 'sts:TagSession' ] ) ,
89+ } ) ,
8090 ] ) ,
8191 } ,
8292 // Role chaining caps at 1h regardless; documented explicitly.
@@ -163,20 +173,27 @@ describe('AgentSessionRole construct', () => {
163173 ) ;
164174 } ) ;
165175
166- test ( 'compute role is granted sts:AssumeRole + sts:TagSession on the SessionRole' , ( ) => {
167- const policies = template . findResources ( 'AWS::IAM::Policy' ) ;
168- const computePolicy = Object . entries ( policies ) . find ( ( [ id ] ) =>
169- id . includes ( 'ComputeRole' ) ,
170- ) ! [ 1 ] ;
176+ test ( 'constructor admits assumingRoles with both trust and grant wired' , ( ) => {
177+ const computePolicy = findComputeRolePolicy ( template ) ;
171178 const statements = computePolicy . Properties . PolicyDocument . Statement ;
172179 const stsStatement = statements . find ( ( s : { Action : string | string [ ] } ) => {
173180 const actions = Array . isArray ( s . Action ) ? s . Action : [ s . Action ] ;
174181 return actions . includes ( 'sts:AssumeRole' ) && actions . includes ( 'sts:TagSession' ) ;
175182 } ) ;
176183 expect ( stsStatement ) . toBeDefined ( ) ;
184+
185+ const trustDoc = findSessionRoleTrust ( template ) . Properties . AssumeRolePolicyDocument ;
186+ const bundledTrust = trustDoc . Statement . find (
187+ ( s : { Action : string | string [ ] } ) => {
188+ const actions = Array . isArray ( s . Action ) ? s . Action : [ s . Action ] ;
189+ return actions . includes ( 'sts:AssumeRole' ) && actions . includes ( 'sts:TagSession' ) ;
190+ } ,
191+ ) ;
192+ expect ( bundledTrust ) . toBeDefined ( ) ;
193+ expect ( JSON . stringify ( trustDoc ) ) . toContain ( 'ComputeRole' ) ;
177194 } ) ;
178195
179- test ( 'addAssumingRole admits a second compute role (ECS task role) to the trust ' , ( ) => {
196+ test ( 'admitComputeRole wires both trust and grant for an additional compute role ' , ( ) => {
180197 const app = new App ( ) ;
181198 const stack = new Stack ( app , 'MultiPrincipalStack' ) ;
182199 const agentcoreRole = new iam . Role ( stack , 'AgentCoreRole' , {
@@ -194,17 +211,25 @@ describe('AgentSessionRole construct', () => {
194211 traceArtifactsBucket : new s3 . Bucket ( stack , 'TB' ) ,
195212 attachmentsBucket : new s3 . Bucket ( stack , 'AB' ) ,
196213 } ) ;
197- sessionRole . addAssumingRole ( ecsTaskRole ) ;
198-
199- const trustStatements = Template . fromStack ( stack ) . findResources (
200- 'AWS::IAM::Role' ,
201- ) ;
202- const sr = Object . entries ( trustStatements ) . find ( ( [ id ] ) => id . includes ( 'SR' ) ) ! [ 1 ] ;
203- // Trust policy now has statements for both AssumeRole and TagSession; the
204- // ECS task role ARN appears as an additional principal.
205- const serialized = JSON . stringify ( sr . Properties . AssumeRolePolicyDocument ) ;
206- expect ( serialized ) . toContain ( 'sts:TagSession' ) ;
207- expect ( serialized ) . toContain ( 'EcsTaskRole' ) ;
208- expect ( serialized ) . toContain ( 'AgentCoreRole' ) ;
214+ sessionRole . admitComputeRole ( ecsTaskRole ) ;
215+
216+ const stackTemplate = Template . fromStack ( stack ) ;
217+ const trustDoc = Object . entries ( stackTemplate . findResources ( 'AWS::IAM::Role' ) ) . find (
218+ ( [ id ] ) => id . includes ( 'SR' ) ,
219+ ) ! [ 1 ] . Properties . AssumeRolePolicyDocument ;
220+ const serializedTrust = JSON . stringify ( trustDoc ) ;
221+ expect ( serializedTrust ) . toContain ( 'sts:TagSession' ) ;
222+ expect ( serializedTrust ) . toContain ( 'EcsTaskRole' ) ;
223+ expect ( serializedTrust ) . toContain ( 'AgentCoreRole' ) ;
224+
225+ const ecsPolicy = Object . entries ( stackTemplate . findResources ( 'AWS::IAM::Policy' ) ) . find (
226+ ( [ id ] ) => id . includes ( 'EcsTaskRole' ) ,
227+ ) ! [ 1 ] ;
228+ const ecsStatements = ecsPolicy . Properties . PolicyDocument . Statement ;
229+ const stsGrant = ecsStatements . find ( ( s : { Action : string | string [ ] } ) => {
230+ const actions = Array . isArray ( s . Action ) ? s . Action : [ s . Action ] ;
231+ return actions . includes ( 'sts:AssumeRole' ) && actions . includes ( 'sts:TagSession' ) ;
232+ } ) ;
233+ expect ( stsGrant ) . toBeDefined ( ) ;
209234 } ) ;
210235} ) ;
0 commit comments