@@ -6,7 +6,7 @@ import nodeunit = require('nodeunit');
66import cloudformation = require( '../lib' ) ;
77
88export = nodeunit . testCase ( {
9- CreateReplaceChangeSet : {
9+ ' CreateReplaceChangeSet' : {
1010 works ( test : nodeunit . Test ) {
1111 const stack = new cdk . Stack ( ) ;
1212 const pipelineRole = new RoleDouble ( stack , 'PipelineRole' ) ;
@@ -21,11 +21,7 @@ export = nodeunit.testCase({
2121
2222 _assertPermissionGranted ( test , pipelineRole . statements , 'iam:PassRole' , action . role . roleArn ) ;
2323
24- const stackArn = cdk . ArnUtils . fromComponents ( {
25- service : 'cloudformation' ,
26- resource : 'stack' ,
27- resourceName : 'MyStack/*'
28- } ) ;
24+ const stackArn = _stackArn ( 'MyStack' ) ;
2925 const changeSetCondition = { StringEquals : { 'cloudformation:ChangeSetName' : 'MyChangeSet' } } ;
3026 _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:DescribeStacks' , stackArn ) ;
3127 _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:DescribeChangeSet' , stackArn , changeSetCondition ) ;
@@ -44,7 +40,7 @@ export = nodeunit.testCase({
4440 test . done ( ) ;
4541 }
4642 } ,
47- ExecuteChangeSet : {
43+ ' ExecuteChangeSet' : {
4844 works ( test : nodeunit . Test ) {
4945 const stack = new cdk . Stack ( ) ;
5046 const pipelineRole = new RoleDouble ( stack , 'PipelineRole' ) ;
@@ -55,11 +51,7 @@ export = nodeunit.testCase({
5551 stackName : 'MyStack' ,
5652 } ) ;
5753
58- const stackArn = cdk . ArnUtils . fromComponents ( {
59- service : 'cloudformation' ,
60- resource : 'stack' ,
61- resourceName : 'MyStack/*'
62- } ) ;
54+ const stackArn = _stackArn ( 'MyStack' ) ;
6355 _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:ExecuteChangeSet' , stackArn ,
6456 { StringEquals : { 'cloudformation:ChangeSetName' : 'MyChangeSet' } } ) ;
6557
@@ -71,7 +63,44 @@ export = nodeunit.testCase({
7163
7264 test . done ( ) ;
7365 }
74- }
66+ } ,
67+
68+ 'the CreateUpdateStack Action sets the DescribeStack*, Create/Update/DeleteStack & PassRole permissions' ( test : nodeunit . Test ) {
69+ const stack = new cdk . Stack ( ) ;
70+ const pipelineRole = new RoleDouble ( stack , 'PipelineRole' ) ;
71+ const action = new cloudformation . PipelineCreateUpdateStackAction ( stack , 'Action' , {
72+ stage : new StageDouble ( { pipelineRole } ) ,
73+ templatePath : new cpapi . Artifact ( stack as any , 'TestArtifact' ) . atPath ( 'some/file' ) ,
74+ stackName : 'MyStack' ,
75+ } ) ;
76+ const stackArn = _stackArn ( 'MyStack' ) ;
77+
78+ _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:DescribeStack*' , stackArn ) ;
79+ _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:CreateStack' , stackArn ) ;
80+ _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:UpdateStack' , stackArn ) ;
81+ _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:DeleteStack' , stackArn ) ;
82+
83+ _assertPermissionGranted ( test , pipelineRole . statements , 'iam:PassRole' , action . role . roleArn ) ;
84+
85+ test . done ( ) ;
86+ } ,
87+
88+ 'the DeleteStack Action sets the DescribeStack*, DeleteStack & PassRole permissions' ( test : nodeunit . Test ) {
89+ const stack = new cdk . Stack ( ) ;
90+ const pipelineRole = new RoleDouble ( stack , 'PipelineRole' ) ;
91+ const action = new cloudformation . PipelineDeleteStackAction ( stack , 'Action' , {
92+ stage : new StageDouble ( { pipelineRole } ) ,
93+ stackName : 'MyStack' ,
94+ } ) ;
95+ const stackArn = _stackArn ( 'MyStack' ) ;
96+
97+ _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:DescribeStack*' , stackArn ) ;
98+ _assertPermissionGranted ( test , pipelineRole . statements , 'cloudformation:DeleteStack' , stackArn ) ;
99+
100+ _assertPermissionGranted ( test , pipelineRole . statements , 'iam:PassRole' , action . role . roleArn ) ;
101+
102+ test . done ( ) ;
103+ } ,
75104} ) ;
76105
77106interface PolicyStatementJson {
@@ -121,7 +150,7 @@ function _assertPermissionGranted(test: nodeunit.Test, statements: PolicyStateme
121150 : '' ;
122151 const statementsStr = JSON . stringify ( cdk . resolve ( statements ) , null , 2 ) ;
123152 test . ok ( _grantsPermission ( statements , action , resource , conditions ) ,
124- `Expected to find a statement granting ${ action } on ${ cdk . resolve ( resource ) } ${ conditionStr } , found:\n${ statementsStr } ` ) ;
153+ `Expected to find a statement granting ${ action } on ${ JSON . stringify ( cdk . resolve ( resource ) ) } ${ conditionStr } , found:\n${ statementsStr } ` ) ;
125154}
126155
127156function _grantsPermission ( statements : PolicyStatementJson [ ] , action : string , resource : string , conditions ?: any ) {
@@ -145,6 +174,14 @@ function _isOrContains(entity: string | string[], value: string): boolean {
145174 return false ;
146175}
147176
177+ function _stackArn ( stackName : string ) : string {
178+ return cdk . ArnUtils . fromComponents ( {
179+ service : 'cloudformation' ,
180+ resource : 'stack' ,
181+ resourceName : `${ stackName } /*` ,
182+ } ) ;
183+ }
184+
148185class StageDouble implements cpapi . IStage , cpapi . IInternalStage {
149186 public readonly name : string ;
150187 public readonly pipelineArn : string ;
0 commit comments