diff --git a/source/infrastructure/lib/components/config/nuke-config.yaml b/source/infrastructure/lib/components/config/nuke-config.yaml index 19b9c9d..4f3e6e7 100644 --- a/source/infrastructure/lib/components/config/nuke-config.yaml +++ b/source/infrastructure/lib/components/config/nuke-config.yaml @@ -113,6 +113,9 @@ accounts: - property: RoleName type: glob value: aws-controltower-* + IAMServiceLinkedRole: + - type: exact + value: AWSServiceRoleForECS # ECS Service Linked Role IAMSAMLProvider: - type: contains value: AWSSSO diff --git a/source/infrastructure/lib/isb-sandbox-account-resources.ts b/source/infrastructure/lib/isb-sandbox-account-resources.ts index 30f9555..0cf8663 100644 --- a/source/infrastructure/lib/isb-sandbox-account-resources.ts +++ b/source/infrastructure/lib/isb-sandbox-account-resources.ts @@ -3,6 +3,7 @@ import { Stack } from "aws-cdk-lib"; import { AccountPrincipal, + CfnServiceLinkedRole, Effect, PolicyDocument, PolicyStatement, @@ -59,5 +60,18 @@ export class IsbSandboxAccountResources { "IAM_NO_INLINE_POLICY_CHECK", "IAM_POLICYDOCUMENT_NO_WILDCARD_RESOURCE", ]); + + // ECS Service Linked Role + // This ensures ECS clusters can be created without permission issues + const ecsServiceLinkedRole = new CfnServiceLinkedRole(scope, "ECSServiceLinkedRole", { + awsServiceName: "ecs.amazonaws.com", + description: "Role to enable Amazon ECS to manage your cluster.", + }); + + // Add cfn-guard suppressions using direct metadata approach + // (CfnServiceLinkedRole doesn't support cfnOptions, so we use addMetadata directly) + ecsServiceLinkedRole.addMetadata("guard", { + SuppressedRules: ["CFN_NO_EXPLICIT_RESOURCE_NAMES"], + }); } } diff --git a/source/infrastructure/test/__snapshots__/snapshots.test.ts.snap b/source/infrastructure/test/__snapshots__/snapshots.test.ts.snap index d054eec..0d4e882 100644 --- a/source/infrastructure/test/__snapshots__/snapshots.test.ts.snap +++ b/source/infrastructure/test/__snapshots__/snapshots.test.ts.snap @@ -19956,6 +19956,9 @@ accounts: - property: RoleName type: glob value: aws-controltower-* + IAMServiceLinkedRole: + - type: exact + value: AWSServiceRoleForECS # ECS Service Linked Role IAMSAMLProvider: - type: contains value: AWSSSO @@ -20494,6 +20497,13 @@ exports[`SandboxAccountStack Snapshot > matches the snapshot 1`] = ` }, }, "Resources": { + "ECSServiceLinkedRole": { + "Properties": { + "AWSServiceName": "ecs.amazonaws.com", + "Description": "Role to enable Amazon ECS to manage your cluster.", + }, + "Type": "AWS::IAM::ServiceLinkedRole", + }, "SandboxAccountRole39551795": { "Metadata": { "guard": {