

# Amazon ECS 中 IAM 角色的最佳实践
<a name="security-iam-roles"></a>

Amazon ECS 需要的角色取决于任务定义启动类型和您使用的功能。我们建议您在表中创建单独的角色，而不是共享角色。


| 角色 | 定义 | 何时需要 | 更多信息 | 
| --- | --- | --- | --- | 
| 任务执行 角色 | 此角色允许 Amazon ECS 代表您使用其他 AWS 服务。 |  您的任务托管在 AWS Fargate 或外部实例上且： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonECS/latest/developerguide/security-iam-roles.html) 您的任务托管在 AWS Fargate 或 Amazon EC2 实例上且： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonECS/latest/developerguide/security-iam-roles.html)  | [Amazon ECS 任务执行 IAM 角色](task_execution_IAM_role.md) | 
| 任务 角色 | 此角色允许您的应用程序代码（在容器上）使用其他 AWS 服务。 | 您的应用程序访问其他 AWS 服务，例如 Amazon S3。 | [Amazon ECS 任务 IAM 角色](task-iam-roles.md) | 
| 容器实例角色 | 此角色允许您的 EC2 实例或外部实例向集群注册。 | 您的任务托管在 Amazon EC2 实例或外部实例上。 | [Amazon ECS 容器实例 IAM 角色](instance_IAM_role.md) | 
| Amazon ECS Anywhere 角色 | 此角色允许您的外部实例访问 AWS API。 | 您的任务托管在外部实例上。 | [Amazon ECS Anywhere IAM 角色](iam-role-ecsanywhere.md) | 
| Amazon ECS CodeDeploy 角色 | 此角色允许 CodeDeploy 对您的服务进行更新。 | 您可使用 CodeDeploy 蓝/绿部署类型来部署服务。 | [Amazon ECS CodeDeploy IAM 角色](codedeploy_IAM_role.md) | 
| Amazon ECS EventBridge 角色 | 此角色允许 EventBridge 对您的服务进行更新。 | 您可使用 EventBridge 规则和目标来计划任务。 | [Amazon ECS EventBridge IAM 角色](CWE_IAM_role.md) | 
| Amazon ECS 基础设施角色 | 此角色允许 Amazon ECS 管理集群中的基础设施资源。 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonECS/latest/developerguide/security-iam-roles.html) | [Amazon ECS 基础设施 IAM 角色](infrastructure_IAM_role.md) | 

## 任务 角色
<a name="security-iam-task-role"></a>

建议您为任务分配角色。它的角色可以与其运行的 Amazon EC2 实例的角色不同。为每项任务分配角色符合最低权限访问的原则，并有利于对操作和资源进行更精细的控制。

当您在任务定义中添加任务角色时，Amazon ECS 容器代理会自动为该任务创建具有唯一凭证 ID（例如 `12345678-90ab-cdef-1234-567890abcdef`）的令牌。然后，该令牌和角色凭证将添加到代理的内部缓存中。代理使用凭证 ID 的 URI 填充容器 `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` 中的环境变量（例如，`/v2/credentials/12345678-90ab-cdef-1234-567890abcdef`）。

您可以通过将环境变量附加到 Amazon ECS 容器代理的 IP 地址并对生成的字符串运行 `curl` 命令来手动检索容器内部的临时角色凭证。

```
curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
```

预期的输出如下所示：

```
{
	"RoleArn": "arn:aws:iam::123456789012:role/SSMTaskRole-SSMFargateTaskIAMRole-DASWWSF2WGD6",
	"AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
	"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
	"Token": "IQoJb3JpZ2luX2VjEEM/Example==",
	"Expiration": "2021-01-16T00:51:53Z"
}
```

调用 AWS API 时，较新版本的 AWS 开发工具包会自动从 `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` 环境变量中获取这些凭证。有关如何续订凭证的信息，请参阅在 re:Post 上的 [Renewing AWS credentials](https://repost.aws/questions/QUgcf1EIOPS7GZNboeAiyO9Q/renewing-aws-credentials)。

输出包括一个访问密钥对，该密钥对由您的应用程序用于访问 AWS 资源的秘密访问密钥 ID 和秘密密钥组成。它还包括 AWS 用于验证凭证是否有效的令牌。默认情况下，使用任务角色分配给任务的凭证有效期为六小时。之后，Amazon ECS 容器代理会自动轮换它们。

## 任务执行 角色
<a name="security-iam-roles-task-execution"></a>

任务执行角色用于授予 Amazon ECS 容器代理代表您调用特定 AWS API 操作的权限。例如，当您使用 AWS Fargate 时，Fargate 需要一个 IAM 角色来允许它从 Amazon ECR 提取映像并将日志写入 CloudWatch Logs。当任务引用存储在 AWS Secrets Manager 中的密钥（例如映像提取密钥）时，还需要一个 IAM 角色。

**注意**  
如果您以经过身份验证的用户身份提取映像，则不太可能受到 [Docker Hub 拉取速率限制](https://www.docker.com/pricing/resource-consumption-updates)变化的影响。有关更多信息，请参阅[容器实例的私有注册表身份验证](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth-container-instances.html)。  
通过使用 Amazon ECR 和 Amazon ECR Public，您可以避开 Docker 施加的限制。如果您从 Amazon ECR 提取映像，这还有助于缩短网络提取时间，并减少流量离开您的 VPC 时的数据传输变化。

**重要**  
使用 Fargate 时，您必须使用 `repositoryCredentials` 向私有映像注册表进行身份验证。无法为 Fargate 上托管的任务设置 Amazon ECS 容器代理环境变量 `ECS_ENGINE_AUTH_TYPE` 或 `ECS_ENGINE_AUTH_DATA` 或修改 `ecs.config` 文件。有关更多信息，请参阅[任务的私有注册表身份验证](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html)。

## 容器实例角色
<a name="security-iam-roles-ec2-container-instance"></a>

`AmazonEC2ContainerServiceforEC2Role` 托管 IAM 策略必须包含以下权限。遵循授予最低权限的标准安全建议，`AmazonEC2ContainerServiceforEC2Role` 托管策略可用作指南。如果不需要在托管策略中为您的使用案例授予的任何权限，请创建自定义策略并仅添加所需的权限。
+ `ec2:DescribeTags`：（可选）允许主体描述与 Amazon EC2 实例关联的标签。Amazon ECS 容器代理使用此权限来支持资源标签传播。有关更多信息，请参阅 [如何为资源添加标签](ecs-using-tags.md#tag-resources)。
+ `ecs:CreateCluster` –（可选）允许主体创建 Amazon ECS 集群。Amazon ECS 容器代理将使用此权限创建 `default` 集群（如果还没有集群）。
+ `ecs:DeregisterContainerInstance` –（可选）允许主体从集群注销 Amazon ECS 容器实例。Amazon ECS 容器代理不会调用此 API 操作，但仍保留此权限以帮助确保后续的兼容性。
+ `ecs:DiscoverPollEndpoint` –（必要）此操作返回 Amazon ECS 容器代理用于轮询更新的端点。
+ `ecs:Poll` –（必要）允许 Amazon ECS 容器代理与 Amazon ECS 控制面板通信，报告任务状态更改。
+ `ecs:RegisterContainerInstance` –（必要）允许主体向集群注册容器实例。Amazon ECS 容器代理使用此权限向集群注册 Amazon EC2 实例并支持资源标签传播。
+ `ecs:StartTelemetrySession` –（可选）允许 Amazon ECS 容器代理与 Amazon ECS 控制面板通信，报告每个容器和任务的运行状况信息和指标。

  尽管此权限并非必需，但我们建议您添加此权限，以便容器实例指标启动扩展操作，并接收与运行状况检查命令相关的报告。
+ `ecs:TagResource` –（可选）允许 Amazon ECS 容器代理在创建集群时标记集群，并在容器实例注册到集群时对其进行标记。
+ `ecs:UpdateContainerInstancesState`— 允许委托人修改 Amazon ECS 容器实例的状态。Amazon ECS 容器代理将此权限用于竞价型实例耗尽。
+ `ecs:Submit*` –（必要）这包括 `SubmitAttachmentStateChanges`、`SubmitContainerStateChange` 和 `SubmitTaskStateChange` API 操作。Amazon ECS 容器代理使用它们向 Amazon ECS 控制面板报告每个资源的状态变化。`SubmitContainerStateChange` 权限不再被 Amazon ECS 容器代理使用，但仍可帮助确保后续的兼容性。
+ `ecr:GetAuthorizationToken` –（可选）允许主体检索授权令牌。授权令牌表示您的 IAM 身份验证凭证，可用于访问您的 IAM 委托人有权访问的任何 Amazon ECR 注册表。收到的授权令牌有效期为 12 小时。
+ `ecr:BatchCheckLayerAvailability` –（可选）将容器映像推送到 Amazon ECR 私有存储库时，系统会检查每个映像层，验证其是否已推送。如果是，则会跳过映像层。
+ `ecr:GetDownloadUrlForLayer` –（可选）从 Amazon ECR 私有存储库中提取容器映像时，对于尚未缓存的每个映像层，此 API 都会被调用一次。
+ `ecr:BatchGetImage` –（可选）从 Amazon ECR 私有存储库中提取容器映像时，系统会调用一次此 API 来检索映像清单。
+ `logs:CreateLogStream` –（可选）允许主体为指定的日志组创建 CloudWatch Logs 日志流。
+ `logs:PutLogEvents` –（可选）允许主体将一批日志事件上传到指定的日志流。

## 服务关联角色
<a name="security-iam-roles-service-linked"></a>

您可以将服务相关角色用于 Amazon ECS，以授予 Amazon ECS 服务代表您调用其他服务 API 的权限。Amazon ECS 需要拥有创建和删除网络接口、向目标组注册和注销目标的权限。它还需要必要的权限才能创建和删除扩展策略。这些权限通过服务相关角色授予。此角色是在您首次使用该服务时代表您创建的。

**注意**  
如果您无意中删除了服务相关角色，则可以重新创建它。有关说明，请参阅[创建服务相关角色](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using-service-linked-roles.html#create-service-linked-role)。

## 角色建议
<a name="security-iam-roles-recommendations"></a>

在设置任务 IAM 角色和策略时，建议执行以下操作。

### 阻止对 Amazon EC2 元数据的访问
<a name="security-iam-roles-recommendations-ec2-metadata"></a>

当您在 Amazon EC2 实例上运行任务时，强烈建议您阻止访问 Amazon EC2 元数据，以防止您的容器继承分配给这些实例的角色。如果您的应用程序必须调用 AWS API 操作，请改用 IAM 角色执行任务。

要防止在**桥接**模式下运行的任务访问 Amazon EC2 元数据，请运行以下命令或更新实例的用户数据。有关更新实例用户数据的更多说明，请参阅此 [AWS 支持文章](https://aws.amazon.com/premiumsupport/knowledge-center/ecs-container-ec2-metadata/)。有关任务定义桥接模式的更多信息，请参阅[任务定义网络模式](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#network_mode)。

```
sudo yum install -y iptables-services; sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP
```

要使此更改在重启后保持不变，请运行以下特定于您的亚马逊机器映像（AMI）的命令：
+ Amazon Linux 2

  ```
  sudo iptables-save | sudo tee /etc/sysconfig/iptables && sudo systemctl enable --now iptables
  ```
+ Amazon Linux

  ```
  sudo service iptables save
  ```

对于使用 `awsvpc` 网络模式的任务，请在 `/etc/ecs/ecs.config` 文件中将环境变量 `ECS_AWSVPC_BLOCK_IMDS` 设置为 `true`。

您应在 `ecs-agent config` 文件中将 `ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST` 变量设置为 `false`，以防止在 `host` 网络中运行的容器访问 Amazon EC2 元数据。

### 使用 `awsvpc` 网络模式
<a name="security-iam-roles-recommendations-awsvpc-networking-mode"></a>

使用网络 `awsvpc` 网络模式限制不同任务之间或您的任务与在 Amazon VPC 内运行的其他服务之间的流量。这将额外增加一层安全性。`awsvpc` 网络模式为在 Amazon EC2 上运行的任务提供任务级别的网络隔离。它是 AWS Fargate 上的默认模式，是唯一可以用来为任务分配安全组的网络模式。

### 使用上次访问的信息优化角色
<a name="security-iam-roles-recommendations-iam-access-advisor-refine-roles"></a>

建议您删除任何从未使用或一段时间未使用的操作。这样可以防止发生不必要的访问。为此，请查看 IAM 提供的上次访问的信息，然后移除从未使用过或最近未使用过的操作。您可以按照以下步骤执行此操作。

运行以下命令以生成报告，其中显示所引用策略的最后访问信息：

```
aws iam generate-service-last-accessed-details --arn arn:aws:iam::123456789012:policy/ExamplePolicy1
```

使用输出中的 `JobId` 来运行以下命令。执行此操作后，您可以查看报告的结果。

```
aws iam get-service-last-accessed-details --job-id 98a765b4-3cde-2101-2345-example678f9
```

有关更多信息，请参阅[使用上次访问的信息优化 AWS 中的权限](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_last-accessed.html)。

### 监控 AWS CloudTrail 是否有可疑活动
<a name="security-iam-roles-recommendations-cloudtrail-monitoring"></a>

您可以监控 AWS CloudTrail 是否有任何可疑活动。大多数 AWS API 调用都以事件形式记录到 AWS CloudTrail 中。AWS CloudTrail Insights 会对它们进行分析，并提醒您注意任何与 `write` API 调用相关的可疑行为。这可能包括通话量激增。这些警报包括异常活动发生的时间和促成 API 的高级身份 ARN 等信息。

您可以通过查看事件的 `userIdentity` 属性来识别具有 IAM 角色的任务在 AWS CloudTrail 中执行的操作。在以下示例中，`arn` 包括代入的角色的名称 `s3-write-go-bucket-role`，随后是任务的名称 `7e9894e088ad416eb5cab92afExample`。

```
"userIdentity": {
    "type": "AssumedRole",
    "principalId": "AROA36C6WWEJ2YEXAMPLE:7e9894e088ad416eb5cab92afExample",
    "arn": "arn:aws:sts::123456789012:assumed-role/s3-write-go-bucket-role/7e9894e088ad416eb5cab92afExample",
    ...
}
```

**注意**  
在 Amazon EC2 容器实例上运行代入角色的任务时，Amazon ECS 容器代理会将请求记录到该代理的审核日志中，该代理位于 `/var/log/ecs/audit.log.YYYY-MM-DD-HH` 格式的地址上。有关更多信息，请参阅[任务 IAM 角色日志](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/logs.html#task_iam_roles-logs)和[记录跟踪记录的见解事件](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-insights-events-with-cloudtrail.html)。