@@ -245,7 +245,8 @@ class AssetPublishing extends Construct {
245
245
private readonly myCxAsmRoot : string ;
246
246
247
247
private readonly stage : codepipeline . IStage ;
248
- private assetRole ?: iam . Role ;
248
+ private readonly pipeline : codepipeline . Pipeline ;
249
+ private assetRole ?: iam . IRole ;
249
250
private _fileAssetCtr = 1 ;
250
251
private _dockerAssetCtr = 1 ;
251
252
@@ -256,6 +257,7 @@ class AssetPublishing extends Construct {
256
257
// We MUST add the Stage immediately here, otherwise it will be in the wrong place
257
258
// in the pipeline!
258
259
this . stage = this . props . pipeline . addStage ( { stageName : 'Assets' } ) ;
260
+ this . pipeline = this . props . pipeline ;
259
261
}
260
262
261
263
/**
@@ -269,15 +271,9 @@ class AssetPublishing extends Construct {
269
271
// FIXME: this is silly, we need the relative path here but no easy way to get it
270
272
const relativePath = path . relative ( this . myCxAsmRoot , command . assetManifestPath ) ;
271
273
272
- // This role is used by both the CodePipeline build action and related CodeBuild project. Consolidating these two
273
- // roles into one, and re-using across all assets, saves significant size of the final synthesized output.
274
- // Modeled after the CodePipeline role and 'CodePipelineActionRole' roles.
275
- // Late-binding here to prevent creating the role in cases where no asset actions are created.
274
+ // Late-binding here (rather than in the constructor) to prevent creating the role in cases where no asset actions are created.
276
275
if ( ! this . assetRole ) {
277
- this . assetRole = new iam . Role ( this , 'Role' , {
278
- roleName : PhysicalName . GENERATE_IF_NEEDED ,
279
- assumedBy : new iam . CompositePrincipal ( new iam . ServicePrincipal ( 'codebuild.amazonaws.com' ) , new iam . AccountPrincipal ( Stack . of ( this ) . account ) ) ,
280
- } ) ;
276
+ this . generateAssetRole ( ) ;
281
277
}
282
278
283
279
let action = this . publishers [ command . assetId ] ;
@@ -321,9 +317,70 @@ class AssetPublishing extends Construct {
321
317
}
322
318
}
323
319
}
320
+
321
+ /**
322
+ * This role is used by both the CodePipeline build action and related CodeBuild project. Consolidating these two
323
+ * roles into one, and re-using across all assets, saves significant size of the final synthesized output.
324
+ * Modeled after the CodePipeline role and 'CodePipelineActionRole' roles.
325
+ */
326
+ private generateAssetRole ( ) {
327
+ const assetRole = new iam . Role ( this , 'Role' , {
328
+ roleName : PhysicalName . GENERATE_IF_NEEDED ,
329
+ assumedBy : new iam . CompositePrincipal ( new iam . ServicePrincipal ( 'codebuild.amazonaws.com' ) , new iam . AccountPrincipal ( Stack . of ( this ) . account ) ) ,
330
+ } ) ;
331
+
332
+ // Logging permissions
333
+ const logGroupArn = Stack . of ( this ) . formatArn ( {
334
+ service : 'logs' ,
335
+ resource : 'log-group' ,
336
+ sep : ':' ,
337
+ resourceName : '/aws/codebuild/*' ,
338
+ } ) ;
339
+ assetRole . addToPolicy ( new iam . PolicyStatement ( {
340
+ resources : [ logGroupArn ] ,
341
+ actions : [ 'logs:CreateLogGroup' , 'logs:CreateLogStream' , 'logs:PutLogEvents' ] ,
342
+ } ) ) ;
343
+
344
+ // CodeBuild report groups
345
+ const codeBuildArn = Stack . of ( this ) . formatArn ( {
346
+ service : 'codebuild' ,
347
+ resource : 'report-group' ,
348
+ resourceName : '*' ,
349
+ } ) ;
350
+ assetRole . addToPolicy ( new iam . PolicyStatement ( {
351
+ actions : [
352
+ 'codebuild:CreateReportGroup' ,
353
+ 'codebuild:CreateReport' ,
354
+ 'codebuild:UpdateReport' ,
355
+ 'codebuild:BatchPutTestCases' ,
356
+ ] ,
357
+ resources : [ codeBuildArn ] ,
358
+ } ) ) ;
359
+
360
+ // CodeBuild start/stop
361
+ assetRole . addToPolicy ( new iam . PolicyStatement ( {
362
+ resources : [ '*' ] ,
363
+ actions : [
364
+ 'codebuild:BatchGetBuilds' ,
365
+ 'codebuild:StartBuild' ,
366
+ 'codebuild:StopBuild' ,
367
+ ] ,
368
+ } ) ) ;
369
+
370
+ // Publishing role access
371
+ assetRole . addToPolicy ( new iam . PolicyStatement ( {
372
+ actions : [ 'sts:AssumeRole' ] ,
373
+ resources : [ 'arn:*:iam::*:role/*-image-publishing-role-*' , 'arn:*:iam::*:role/*-file-publishing-role-*' ] ,
374
+ } ) ) ;
375
+
376
+ this . pipeline . artifactBucket . grantRead ( assetRole ) ;
377
+
378
+ this . assetRole = assetRole . withoutPolicyUpdates ( ) ;
379
+ return this . assetRole ;
380
+ }
324
381
}
325
382
326
383
function maybeSuffix ( x : string | undefined , suffix : string ) : string | undefined {
327
384
if ( x === undefined ) { return undefined ; }
328
385
return `${ x } ${ suffix } ` ;
329
- }
386
+ }
0 commit comments