使用IAM用户创建ECS CloudFormation栈时遇AccessDeniedException错误求助
错误信息
错误: Resource handler returned message: "Invalid request provided: CreateService error: Access denied (Service: AmazonECS; Status Code: 400; Error Code: AccessDeniedException; Request ID: c894016a-395d-4468-92fa-b63a2a4642f9; Proxy: null)" (RequestToken: 5d151803-6b53-02ea-8903-7c34934b251e, HandlerErrorCode: InvalidRequest)
问题背景
使用CloudFormation嵌套栈创建Amazon ECS服务时触发上述访问拒绝错误,导致栈创建失败。已尝试单独创建ExecutionRole等网络方案,均未解决;使用root账号可成功创建该栈,但切换为IAM用户时就会出现访问拒绝错误。
ECS子栈模板代码
--- AWSTemplateFormatVersion: '2010-09-09' Description: The template used to create an ECS Service from the ECS Console. Parameters: ECSClusterName: Type: String Default: ecs-tutorial ECSServiceName: Type: String Default: ecs-tutorial-td LoadBalancerName: Type: String Default: ecs-tutorial-lb WAFName: Type: String Default: AllowAllTrafficAcl Resources: ECSService: Type: AWS::ECS::Service Properties: Cluster: ecs-tutorial CapacityProviderStrategy: - CapacityProvider: FARGATE Base: 0 Weight: 1 TaskDefinition: !Ref TaskDefinition #arn:aws:ecs:us-east-1:818971154557:task-definition/ecs-tutorial-td:1 ServiceName: ecs-tutorial-td # SchedulingStrategy: REPLICA DesiredCount: 2 LoadBalancers: - ContainerName: tindog ContainerPort: 80 LoadBalancerName: Ref: AWS::NoValue TargetGroupArn: Ref: TargetGroup NetworkConfiguration: AwsvpcConfiguration: # AssignPublicIp: ENABLED SecurityGroups: !Split [",", !ImportValue ECSSecurityGroup] Subnets: - !ImportValue PrivateSubnet1Id - !ImportValue PrivateSubnet2Id DeploymentController: Type: ECS DependsOn: - Listener TaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: tindog-website-family # TaskRoleArn: !ImportValue ECSTaskRoleARN # Import the IAM role ARN from another stack Cpu: 512 #0.5cpu Memory: 1024 #1gb NetworkMode: awsvpc # ExecutionRoleArn: !ImportValue ECSTaskRoleARN ContainerDefinitions: - Name: tindog Image: paranjay1/tindog:latest PortMappings: - ContainerPort: 80 RequiresCompatibilities: - EC2 - FARGATE LoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Type: application Name: ecs-tutorial-lb SecurityGroups: !Split [",", !ImportValue ECSSecurityGroup] Subnets: - !ImportValue PublicSubnet1Id - !ImportValue PublicSubnet2Id TargetGroup: DependsOn: LoadBalancer Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckPath: "/" HealthCheckProtocol: HTTP Name: ecs-tutorial-target-group Port: 80 Protocol: HTTP TargetType: ip VpcId: !ImportValue VPCID TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: '300' Listener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: Ref: TargetGroup LoadBalancerArn: Ref: LoadBalancer Port: 80 Protocol: HTTP MyWAFWebACL: Type: AWS::WAFv2::WebACL DependsOn: LoadBalancer Properties: Name: !Ref WAFName Scope: REGIONAL DefaultAction: Allow: {} # An empty Allow block allows all traffic VisibilityConfig: CloudWatchMetricsEnabled: true # Enable CloudWatch metrics collection MetricName: MyWafMetric # Define a metric name for WAF logs SampledRequestsEnabled: true # Enable capturing a sample of requests for analysis MyWAFWebACLAsgn: DependsOn: MyWAFWebACL Type: AWS::WAFv2::WebACLAssociation Properties: WebACLArn: !GetAtt MyWAFWebACL.Arn ResourceArn: !Ref LoadBalancer Outputs: ClusterName: Description: The cluster used to create the service. Value: Ref: ECSClusterName ECSService: Description: The created service. Value: Ref: ECSService LoadBalancer: Description: The created load balancer. Value: Ref: LoadBalancer Listener: Description: The created listener. Value: Ref: Listener TargetGroup: Description: The created target group. Value: Ref: TargetGroup LoadBalancerDNSName: Description: The DNS name of the load balancer. Value: !GetAtt LoadBalancer.DNSName Export: Name: LoadBalancerDNSName LoadBalancerARN: Description: "ALB ARN" Value: !GetAtt LoadBalancer.LoadBalancerArn Export: Name: "LoadBalancerARN"
IAM用户权限情况
当前使用的IAM用户已附加相关权限(权限截图显示用户拥有ECS、CloudFormation、ELB等相关权限)
可能原因及解决方案
1. IAM用户缺少ECS服务创建的关键权限
虽然截图显示有部分权限,但可能缺少以下核心权限:
ecs:CreateService:直接创建ECS服务的权限ecs:RegisterTaskDefinition:创建任务定义的权限iam:PassRole:CloudFormation需要传递任务执行角色/任务角色给ECS的权限(即使模板中注释了RoleArn,Fargate模式下仍可能需要基础的执行角色权限)- 同时需要确保权限策略中包含对应的资源,避免资源范围限制过严。
2. 嵌套栈的权限传递问题
嵌套栈的执行角色(如果指定了)可能缺少权限,或者没有为IAM用户授予cloudformation:CreateStack权限以创建嵌套子栈,同时子栈创建时需要的所有资源权限都要传递给IAM用户或嵌套栈角色。
3. 任务定义的执行角色配置缺失
模板中TaskDefinition的ExecutionRoleArn被注释掉,Fargate模式下ECS任务需要执行角色来拉取镜像、访问日志等资源。即使手动创建了ExecutionRole,需要确保:
- 角色信任策略允许ECS服务(
ecs-tasks.amazonaws.com)执行sts:AssumeRole - IAM用户拥有
iam:PassRole权限传递该执行角色给ECS - 在模板中正确引用该执行角色的ARN,取消注释
ExecutionRoleArn配置
4. 资源依赖或跨栈引用权限
模板中使用了!ImportValue导入其他栈的资源(如安全组、子网),需要确保IAM用户拥有访问这些导入资源的权限,或者跨栈导出的资源权限配置正确。
具体操作步骤
- 为IAM用户补充以下权限策略(根据实际情况调整资源范围):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecs:CreateService", "ecs:RegisterTaskDefinition", "ecs:DescribeClusters", "ecs:DescribeTaskDefinitions" ], "Resource": "*" }, { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::ACCOUNT_ID:role/ECS_EXECUTION_ROLE_NAME" }, { "Effect": "Allow", "Action": [ "cloudformation:CreateStack", "cloudformation:DescribeStacks", "cloudformation:DescribeStackResources" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:CreateLoadBalancer", "elasticloadbalancing:CreateTargetGroup", "elasticloadbalancing:CreateListener", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeTargetGroups" ], "Resource": "*" }, { "Effect": "Allow", "Action": "wafv2:CreateWebACL", "Resource": "*" } ] }
- 修复ECS任务定义的执行角色配置:
- 取消
TaskDefinition中ExecutionRoleArn的注释,确保引用正确的执行角色ARN - 验证执行角色的信任策略包含:
- 取消
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ecs-tasks.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
- 检查嵌套栈的执行配置:如果使用了CloudFormation服务角色,确保该角色拥有所有子栈资源创建的权限;如果没有使用服务角色,确保IAM用户拥有所有嵌套栈涉及的资源权限。
内容的提问来源于stack exchange,提问作者PARANJAY

