Skip to content

Commit 4af0dfc

Browse files
authored
fix(events-targets): ecs:TagResource permission (#28898)
I enabled the following: `aws ecs put-account-setting-default --name tagResourceAuthorization --value on` And then confirmed the task completes successfully. Closes #28854. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 2ebb409 commit 4af0dfc

File tree

39 files changed

+1170
-912
lines changed

39 files changed

+1170
-912
lines changed

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.js.snapshot/aws-ecs-integ-ecs.assets.json

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.js.snapshot/aws-ecs-integ-ecs.template.json

+61-41
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818
"VpcPublicSubnet1Subnet5C2D37C4": {
1919
"Type": "AWS::EC2::Subnet",
2020
"Properties": {
21-
"VpcId": {
22-
"Ref": "Vpc8378EB38"
23-
},
2421
"AvailabilityZone": {
2522
"Fn::Select": [
2623
0,
@@ -44,21 +41,24 @@
4441
"Key": "Name",
4542
"Value": "aws-ecs-integ-ecs/Vpc/PublicSubnet1"
4643
}
47-
]
44+
],
45+
"VpcId": {
46+
"Ref": "Vpc8378EB38"
47+
}
4848
}
4949
},
5050
"VpcPublicSubnet1RouteTable6C95E38E": {
5151
"Type": "AWS::EC2::RouteTable",
5252
"Properties": {
53-
"VpcId": {
54-
"Ref": "Vpc8378EB38"
55-
},
5653
"Tags": [
5754
{
5855
"Key": "Name",
5956
"Value": "aws-ecs-integ-ecs/Vpc/PublicSubnet1"
6057
}
61-
]
58+
],
59+
"VpcId": {
60+
"Ref": "Vpc8378EB38"
61+
}
6262
}
6363
},
6464
"VpcPublicSubnet1RouteTableAssociation97140677": {
@@ -75,12 +75,12 @@
7575
"VpcPublicSubnet1DefaultRoute3DA9E72A": {
7676
"Type": "AWS::EC2::Route",
7777
"Properties": {
78-
"RouteTableId": {
79-
"Ref": "VpcPublicSubnet1RouteTable6C95E38E"
80-
},
8178
"DestinationCidrBlock": "0.0.0.0/0",
8279
"GatewayId": {
8380
"Ref": "VpcIGWD7BA715C"
81+
},
82+
"RouteTableId": {
83+
"Ref": "VpcPublicSubnet1RouteTable6C95E38E"
8484
}
8585
},
8686
"DependsOn": [
@@ -102,15 +102,15 @@
102102
"VpcPublicSubnet1NATGateway4D7517AA": {
103103
"Type": "AWS::EC2::NatGateway",
104104
"Properties": {
105-
"SubnetId": {
106-
"Ref": "VpcPublicSubnet1Subnet5C2D37C4"
107-
},
108105
"AllocationId": {
109106
"Fn::GetAtt": [
110107
"VpcPublicSubnet1EIPD7E02669",
111108
"AllocationId"
112109
]
113110
},
111+
"SubnetId": {
112+
"Ref": "VpcPublicSubnet1Subnet5C2D37C4"
113+
},
114114
"Tags": [
115115
{
116116
"Key": "Name",
@@ -126,9 +126,6 @@
126126
"VpcPrivateSubnet1Subnet536B997A": {
127127
"Type": "AWS::EC2::Subnet",
128128
"Properties": {
129-
"VpcId": {
130-
"Ref": "Vpc8378EB38"
131-
},
132129
"AvailabilityZone": {
133130
"Fn::Select": [
134131
0,
@@ -152,21 +149,24 @@
152149
"Key": "Name",
153150
"Value": "aws-ecs-integ-ecs/Vpc/PrivateSubnet1"
154151
}
155-
]
152+
],
153+
"VpcId": {
154+
"Ref": "Vpc8378EB38"
155+
}
156156
}
157157
},
158158
"VpcPrivateSubnet1RouteTableB2C5B500": {
159159
"Type": "AWS::EC2::RouteTable",
160160
"Properties": {
161-
"VpcId": {
162-
"Ref": "Vpc8378EB38"
163-
},
164161
"Tags": [
165162
{
166163
"Key": "Name",
167164
"Value": "aws-ecs-integ-ecs/Vpc/PrivateSubnet1"
168165
}
169-
]
166+
],
167+
"VpcId": {
168+
"Ref": "Vpc8378EB38"
169+
}
170170
}
171171
},
172172
"VpcPrivateSubnet1RouteTableAssociation70C59FA6": {
@@ -183,12 +183,12 @@
183183
"VpcPrivateSubnet1DefaultRouteBE02A9ED": {
184184
"Type": "AWS::EC2::Route",
185185
"Properties": {
186-
"RouteTableId": {
187-
"Ref": "VpcPrivateSubnet1RouteTableB2C5B500"
188-
},
189186
"DestinationCidrBlock": "0.0.0.0/0",
190187
"NatGatewayId": {
191188
"Ref": "VpcPublicSubnet1NATGateway4D7517AA"
189+
},
190+
"RouteTableId": {
191+
"Ref": "VpcPrivateSubnet1RouteTableB2C5B500"
192192
}
193193
}
194194
},
@@ -206,11 +206,11 @@
206206
"VpcVPCGWBF912B6E": {
207207
"Type": "AWS::EC2::VPCGatewayAttachment",
208208
"Properties": {
209-
"VpcId": {
210-
"Ref": "Vpc8378EB38"
211-
},
212209
"InternetGatewayId": {
213210
"Ref": "VpcIGWD7BA715C"
211+
},
212+
"VpcId": {
213+
"Ref": "Vpc8378EB38"
214214
}
215215
}
216216
},
@@ -412,8 +412,6 @@
412412
"EcsClusterDefaultAutoScalingGroupASGC1A785DB": {
413413
"Type": "AWS::AutoScaling::AutoScalingGroup",
414414
"Properties": {
415-
"MaxSize": "1",
416-
"MinSize": "1",
417415
"LaunchTemplate": {
418416
"LaunchTemplateId": {
419417
"Ref": "EcsClusterDefaultAutoScalingGroupLaunchTemplate3719972A"
@@ -425,6 +423,8 @@
425423
]
426424
}
427425
},
426+
"MaxSize": "1",
427+
"MinSize": "1",
428428
"Tags": [
429429
{
430430
"Key": "Name",
@@ -577,12 +577,6 @@
577577
"Code": {
578578
"ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n"
579579
},
580-
"Role": {
581-
"Fn::GetAtt": [
582-
"EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA",
583-
"Arn"
584-
]
585-
},
586580
"Environment": {
587581
"Variables": {
588582
"CLUSTER": {
@@ -591,6 +585,12 @@
591585
}
592586
},
593587
"Handler": "index.lambda_handler",
588+
"Role": {
589+
"Fn::GetAtt": [
590+
"EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA",
591+
"Arn"
592+
]
593+
},
594594
"Runtime": "python3.9",
595595
"Tags": [
596596
{
@@ -624,15 +624,15 @@
624624
"EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopic8F34E394": {
625625
"Type": "AWS::SNS::Subscription",
626626
"Properties": {
627-
"Protocol": "lambda",
628-
"TopicArn": {
629-
"Ref": "EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"
630-
},
631627
"Endpoint": {
632628
"Fn::GetAtt": [
633629
"EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E",
634630
"Arn"
635631
]
632+
},
633+
"Protocol": "lambda",
634+
"TopicArn": {
635+
"Ref": "EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"
636636
}
637637
}
638638
},
@@ -699,9 +699,9 @@
699699
"AutoScalingGroupName": {
700700
"Ref": "EcsClusterDefaultAutoScalingGroupASGC1A785DB"
701701
},
702-
"LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING",
703702
"DefaultResult": "CONTINUE",
704703
"HeartbeatTimeout": 300,
704+
"LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING",
705705
"NotificationTargetARN": {
706706
"Ref": "EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"
707707
},
@@ -911,6 +911,26 @@
911911
"Ref": "ScheduledEc2TaskScheduledTaskDef56328BA4"
912912
}
913913
},
914+
{
915+
"Action": "ecs:TagResource",
916+
"Effect": "Allow",
917+
"Resource": {
918+
"Fn::Join": [
919+
"",
920+
[
921+
"arn:aws:ecs:",
922+
{
923+
"Ref": "AWS::Region"
924+
},
925+
":*:task/",
926+
{
927+
"Ref": "EcsCluster97242B84"
928+
},
929+
"/*"
930+
]
931+
]
932+
}
933+
},
914934
{
915935
"Action": "iam:PassRole",
916936
"Effect": "Allow",

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.js.snapshot/cdk.out

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.js.snapshot/integ.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.js.snapshot/manifest.json

+4-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.js.snapshot/scheduledEc2TaskTestDefaultTestDeployAssertF02313CA.assets.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)