如何在 CloudFormation YAML 中为 AWS ECS Fargate 容器指定 `logs:CreateLogGroup` 权限

问题描述 投票:0回答:3

我正在尝试使用 CloudFormation 复制单个容器的极其基本的手动配置的 AWS ECS Fargate 部署。看来我快到了;生成的堆栈会旋转一个我可以访问的容器。但没有日志。

我比较了我的手动任务(通过 UI 创建)和 CloudFormation 任务,并向容器定义添加了相同的日志配置,但只是将日志组从

/ecs/foo
更改为
/ecs/bar
:

LogConfiguration:
  LogDriver: awslogs
  Options:
    awslogs-create-group: true
    awslogs-group: '/ecs/bar'
    awslogs-region: !Ref AWS::Region
    awslogs-stream-prefix: 'ecs'

但是现在任务无法启动容器。它给出这样的错误:

Resourceinitializationerror: failed to validate logger args: create stream has been retried 1 times: failed to create Cloudwatch log group: AccessDeniedException: User: arn:aws:sts::…:assumed-role/ecsTaskExecutionRole/… is not authorized to perform: logs:CreateLogGroup on resource: arn:aws:logs:us-east-1:…:log-group:/ecs/bar:log-stream: because no identity-based policy allows the logs:CreateLogGroup action status code: 400, request id: … : exit status 1

一个文档页面提到了这个

logs:CreateLogGroup
许可,并说:

要使用

awslogs-create-group
选项,请将
logs:CreateLogGroup
添加为内联 IAM 策略。

但我不明白的是我的 CloudFormation 模板与通过 UI 手动创建的堆栈有何不同。通过查看为手动创建的堆栈生成的模板,两个任务定义似乎都指示

ecsTaskExecutionRole
。我的 CloudFormation 模板任务定义如下:

ExecutionRoleArn: 'arn:aws:iam::…:role/ecsTaskExecutionRole'

手动创建的堆栈如何能够创建日志组,但我的独立的从头开始的 CloudFormation 模板却不能?我应该在哪里注明

logs:CreateLogGroup
权限?手动创建的堆栈似乎没有指示任何内联策略。 (诚然,由于某种原因,手动创建的任务定义似乎没有使用 CloudFormation 堆栈,所以它可能有一些我在 UI 中没有看到的隐藏设置。)

amazon-web-services aws-cloudformation amazon-iam amazon-ecs aws-fargate
3个回答
3
投票

如果我希望任务使用

awslogs-create-group
自动动态创建日志组,则正确的方法似乎是拥有包含
logs:CreateLogGroup
权限的 IAM 策略,如使用 awslogs 日志驱动程序中所述。 (我仍然不明白如何在 UI 中手动创建任务定义导致创建日志组。)与 ECS 资源初始化错误 相关的另一个页面表示我需要“添加
logs:CreateLogGroup
作为内联 IAM 策略” ,但没有人能够提供如何在 CloudFormation 中执行此操作的示例。我确信我能弄清楚……

但是,在我看来,最好的做法是在 CloudFormation 模板本身中声明和配置

AWS::Logs::LogGroup
资源,而不是让服务动态创建日志组。 (感谢 AWS CloudFormation - 初学者到高级(实践指南) Udemy 课程启发了这种方法。)因此,我会在 CloudFormation 中声明这样的日志组:

BarLogGroup:
  Type: AWS::Logs::LogGroup
  DeletionPolicy: Retain
  Properties: 
    LogGroupName: '/ecs/bar'

然后为了避免重复,在日志配置中引用日志组:

LogConfiguration:
  LogDriver: awslogs
  Options:
    awslogs-group: !Ref BarLogGroup
    awslogs-region: !Ref AWS::Region
    awslogs-stream-prefix: 'ecs'

这完全解决了运行时权限和动态创建的问题。日志组也是一种资源,由于任务依赖于它,我们不妨与其他资源一起以声明方式描述它。这种方式日志组的创建取决于创建堆栈的角色的权限,而不是任务本身,这似乎更合适。

(我添加了删除策略,假设您希望保留日志,即使您删除/重新创建堆栈也是如此。)

进行上述更改后,我的 CloudFormation EC Fargate 堆栈现在可以像手动创建的堆栈一样运行并生成日志,因此这种方法是成功的。


1
投票

ecsTaskExecutionRole
应分配给 TaskRoleArn,而不是
ExecutionRoleArn


0
投票

正如您所注意到的,如果您想使用 awslogs-create-group,则 messages:CreateLogGroup 需要位于 AWS::Batch::JobDefinition 的 ExecutionRoleArn 属性中引用的角色上。如果您添加以下内容,这应该会起作用:

  ManagedPolicyArns:
    - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess

那个角色。

但不建议这样做。这就是我的模板中的内容:

logGroup:
  Type: 'AWS::Logs::LogGroup'
  Properties:
    RetentionInDays: 14
    LogGroupName: my-project
job:
  Type: AWS::Batch::JobDefinition
  Properties:
    JobDefinitionName: myjob
    ContainerProperties:
      Image: !Sub '${ECRRepo}/${Image}'
      ExecutionRoleArn: !GetAtt execRole.Arn
      JobRoleArn: !GetAtt jobRole.Arn
      ResourceRequirements:
        - Value: 8192
          Type: MEMORY
        - Value: 1
          Type: VCPU
      Command:
        - echo
        - hello
        - world 
      LogConfiguration:
        LogDriver: awslogs
        Options:
          awslogs-datetime-format: '%Y-%m-%dT%H:%M:%S.%f%z'
          awslogs-region: !Sub '${AWS::Region}'
          awslogs-group: !Ref logGroup
      EphemeralStorage:
        SizeInGiB: 100
    PlatformCapabilities: 
      - FARGATE
    Type: container
execRole:
  Type: AWS::IAM::Role
  Properties:
    RoleName: myexecrole
    AssumeRolePolicyDocument:
      Statement:
        - Effect: Allow
          Principal:
            Service: ecs-tasks.amazonaws.com
          Action: sts:AssumeRole
    ManagedPolicyArns:
      - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
      - arn:aws:iam::aws:policy/.AmazonEC2ContainerRegistryReadOnly     

但是我遇到了下一个类似的错误。该作业无法创建日志流。这让我困惑了好几个小时。因此 exec 角色用于创建作业,并且需要能够访问镜像存储库,或许还可以创建日志组。作业在 JobRoleArn 中指定的角色下运行。这终于对我有用了:

jobRole:
  Type: AWS::IAM::Role
  Properties:
    RoleName: myjobrole
    AssumeRolePolicyDocument:
      Statement:
        - Effect: Allow
          Principal:
            Service: ecs-tasks.amazonaws.com
          Action: sts:AssumeRole
    Policies:
      - PolicyName: MyS3AndLoggingPolicy
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action:
                - s3:GetObject
                - s3:ListBucket
                - s3:DeleteObject
              Resource:
                - !Sub 'arn:${AWS::Partition}:s3:::${bucketName}'
                - !Sub 'arn:${AWS::Partition}:s3:::${bucketName}/*'
            - Effect: Allow
              Action:
                - logs:PutLogEvents
                - logs:CreateLogStream
              Resource: !Sub 'arn:${AWS::Partition}:logs:*:*:log-group:${logGroup}:log-stream:*'                

我希望这对某人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.