From 3ac633e079fa8440ce650728a6c8467d1711bc58 Mon Sep 17 00:00:00 2001 From: Joerg Woehrle Date: Fri, 7 Jun 2024 14:56:20 +0000 Subject: [PATCH 1/2] chore: Add wildcard revision to imported taskdefinition. Fixes #30390 --- .../aws-events-targets/lib/ecs-task.ts | 10 +- .../test/ecs/event-rule-target.test.ts | 98 +++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts b/packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts index d17ef04e17e20..6498273a2007f 100644 --- a/packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts +++ b/packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts @@ -277,10 +277,18 @@ export class EcsTask implements events.IRuleTarget { } private createEventRolePolicyStatements(): iam.PolicyStatement[] { + // check if there is a taskdefinition revision (arn will end with : followed by digits) included in the arn already + let needsRevisionWildcard = false; + if ( !cdk.Token.isUnresolved(this.taskDefinition.taskDefinitionArn)) { + const revisionAtEndPattern = /:[0-9]+$/; + const hasRevision = revisionAtEndPattern.test(this.taskDefinition.taskDefinitionArn); + needsRevisionWildcard = !hasRevision; + } + const policyStatements = [ new iam.PolicyStatement({ actions: ['ecs:RunTask'], - resources: [this.taskDefinition.taskDefinitionArn], + resources: [`${this.taskDefinition.taskDefinitionArn}${needsRevisionWildcard ? ':*' : ''}`], conditions: { ArnEquals: { 'ecs:cluster': this.cluster.clusterArn }, }, diff --git a/packages/aws-cdk-lib/aws-events-targets/test/ecs/event-rule-target.test.ts b/packages/aws-cdk-lib/aws-events-targets/test/ecs/event-rule-target.test.ts index ebc88f0f91e9a..58e46eb29a219 100644 --- a/packages/aws-cdk-lib/aws-events-targets/test/ecs/event-rule-target.test.ts +++ b/packages/aws-cdk-lib/aws-events-targets/test/ecs/event-rule-target.test.ts @@ -9,6 +9,7 @@ import * as iam from '../../../aws-iam'; import * as sqs from '../../../aws-sqs'; import * as cdk from '../../../core'; import * as targets from '../../lib'; +import { EcsTask } from '../../lib'; let stack: cdk.Stack; let vpc: ec2.Vpc; @@ -1095,3 +1096,100 @@ test.each([ ], }); }); + +test('Non-imported TaskDefinition role is targeting by Ref', () => { + const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef'); + taskDefinition.addContainer('TheContainer', { + image: ecs.ContainerImage.fromRegistry('henk'), + }); + + const rule = new events.Rule(stack, 'Rule', { + schedule: events.Schedule.rate(cdk.Duration.hours(1)), + }); + + rule.addTarget( + new EcsTask({ + cluster: cluster, + taskDefinition: taskDefinition, + }), + ); + + const policyMatch = Match.objectLike({ + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'ecs:RunTask', + Resource: { + Ref: 'TaskDef54694570', + }, + }), + ]), + }, + }); + const template = Template.fromStack(stack); + template.hasResource('AWS::IAM::Policy', { Properties: policyMatch }); +}); + +test('Imported task definition without revision adds wildcard to policy resource', () => { + const taskDefinition = ecs.FargateTaskDefinition.fromFargateTaskDefinitionAttributes(stack, 'TaskDefImport', { + taskDefinitionArn: 'arn:aws:ecs:us-west-2:012345678901:task-definition/MyTask', + taskRole: iam.Role.fromRoleArn(stack, 'RoleImport', 'arn:aws:iam::012345678901:role/MyTaskRole'), + networkMode: ecs.NetworkMode.AWS_VPC, + }); + + const rule = new events.Rule(stack, 'Rule', { + schedule: events.Schedule.rate(cdk.Duration.hours(1)), + }); + + rule.addTarget( + new EcsTask({ + cluster: cluster, + taskDefinition: taskDefinition, + }), + ); + + const policyMatch = Match.objectLike({ + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'ecs:RunTask', + Resource: `${taskDefinition.taskDefinitionArn}:*`, + }), + ]), + }, + }); + const template = Template.fromStack(stack); + template.hasResource('AWS::IAM::Policy', { Properties: policyMatch }); +}); + +test('Imported task definition with revision uses original arn for policy resource', () => { + const taskDefinition = ecs.FargateTaskDefinition.fromFargateTaskDefinitionAttributes(stack, 'TaskDefImport', { + taskDefinitionArn: 'arn:aws:ecs:us-west-2:012345678901:task-definition/MyTask:1', + taskRole: iam.Role.fromRoleArn(stack, 'RoleImport', 'arn:aws:iam::012345678901:role/MyTaskRole'), + networkMode: ecs.NetworkMode.AWS_VPC, + }); + + const rule = new events.Rule(stack, 'Rule', { + schedule: events.Schedule.rate(cdk.Duration.hours(1)), + }); + + rule.addTarget( + new EcsTask({ + cluster: cluster, + taskDefinition: taskDefinition, + }), + ); + + const policyMatch = Match.objectLike({ + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'ecs:RunTask', + Resource: taskDefinition.taskDefinitionArn, + }), + ]), + }, + }); + const template = Template.fromStack(stack); + template.hasResource('AWS::IAM::Policy', { Properties: policyMatch }); +}); \ No newline at end of file From 202ffb24c94150d6f088f4991522567f5ed73058 Mon Sep 17 00:00:00 2001 From: Joerg Woehrle Date: Mon, 17 Jun 2024 14:21:58 +0000 Subject: [PATCH 2/2] fix indent for linting --- .../test/ecs/event-rule-target.test.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/aws-cdk-lib/aws-events-targets/test/ecs/event-rule-target.test.ts b/packages/aws-cdk-lib/aws-events-targets/test/ecs/event-rule-target.test.ts index 58e46eb29a219..d6a6c857e2914 100644 --- a/packages/aws-cdk-lib/aws-events-targets/test/ecs/event-rule-target.test.ts +++ b/packages/aws-cdk-lib/aws-events-targets/test/ecs/event-rule-target.test.ts @@ -1108,10 +1108,10 @@ test('Non-imported TaskDefinition role is targeting by Ref', () => { }); rule.addTarget( - new EcsTask({ - cluster: cluster, - taskDefinition: taskDefinition, - }), + new EcsTask({ + cluster: cluster, + taskDefinition: taskDefinition, + }), ); const policyMatch = Match.objectLike({ @@ -1142,10 +1142,10 @@ test('Imported task definition without revision adds wildcard to policy resource }); rule.addTarget( - new EcsTask({ - cluster: cluster, - taskDefinition: taskDefinition, - }), + new EcsTask({ + cluster: cluster, + taskDefinition: taskDefinition, + }), ); const policyMatch = Match.objectLike({ @@ -1174,10 +1174,10 @@ test('Imported task definition with revision uses original arn for policy resour }); rule.addTarget( - new EcsTask({ - cluster: cluster, - taskDefinition: taskDefinition, - }), + new EcsTask({ + cluster: cluster, + taskDefinition: taskDefinition, + }), ); const policyMatch = Match.objectLike({