

# 将敏感数据传递给 Amazon ECS 容器
<a name="specifying-sensitive-data"></a>

您可以将敏感数据（例如数据库凭证）安全地传递到容器中。

应用程序经常使用诸如 API 密钥和数据库凭证之类的密钥来访问其他系统。它们通常由用户名和密码、证书或 API 密钥组成。对这些密钥的访问应仅限于使用 IAM 并在运行时注入到容器中的特定 IAM 主体。

密钥可以从 AWS Secrets Manager 和 Amazon EC2 Systems Manager Parameter Store 无缝注入容器中。这些密钥可以在您的任务中作为以下任何内容引用。

1. 它们被引用为使用 `secrets` 容器定义参数的环境变量。

1. 如果您的日志记录平台需要身份验证，它们被引用为 `secretOptions`。有关更多信息，请参阅[日志记录配置选项](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html#API_LogConfiguration_Contents)。

1. 如果从中提取容器的注册表需要身份验证，则使用 `repositoryCredentials` 容器定义参数的映像将它们作为密钥引用。从 Amazon ECR 公开映像浏览馆中提取映像时使用此方法。有关更多信息，请参阅[任务的私有注册表身份验证](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html)。

在设置密钥管理时，建议您执行以下操作。

## 使用 AWS Secrets Manager 或 AWS Systems Manager Parameter Store 来存储密钥材料
<a name="security-secrets-management-recommendations-storing-secret-materials"></a>

您应该将 API 密钥、数据库凭证和其他密钥材料安全地存储在 Secrets Manager 中，或者将其作为加密参数存储在 Systems Manager Parameter Store 中。这些服务之所以相似，是因为它们都是使用 AWS KMS 加密敏感数据的托管键值存储。但是 Secrets Manager 还包括自动轮换密钥、生成随机密钥和在账户之间共享密钥的功能。要利用这些功能，请使用 Secrets Manager。否则，请使用 Systems Manager Parameter Store 中的加密参数。

**重要**  
如果您的密钥发生更改，则必须强制进行新的部署或启动新任务以检索最新的密钥值。有关更多信息，请参阅以下主题：  
任务 – 停止任务，然后启动它。有关更多信息，请参阅[停止 Amazon ECS 任务](standalone-task-stop.md)和[将应用程序作为 Amazon ECS 任务运行](standalone-task-create.md)。
服务 – 更新服务并使用强制新部署选项。有关更多信息，请参阅 [更新 Amazon ECS 服务](update-service-console-v2.md)。

## 从加密的 Amazon S3 存储桶中检索数据
<a name="security-secrets-management-recommendations-encrypted-s3-buckets"></a>

您应将密钥存储在加密的 Amazon S3 存储桶中，并使用任务角色来限制对这些密钥的访问权限。这样可以防止环境变量的值无意中泄漏到日志中，以及在运行 `docker inspect` 时被泄露。执行此操作时，必须编写应用程序以从 Amazon S3 存储桶中读取密钥。有关说明，请参阅[为 Amazon S3 存储桶设置默认服务器端加密行为](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-encryption.html)。

## 使用 sidecar 容器将密钥挂载到卷上
<a name="security-secrets-management-recommendations-mount-secret-volumes"></a>

由于环境变量会增加数据泄露的风险，因此您应该运行一个 sidecar 容器，以从 AWS Secrets Manager 中读取密钥并将其写入共享卷中。通过使用 [Amazon ECS 容器排序](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDependency.html)，此容器可以在应用程序容器之前运行和退出。当您执行此操作时，应用程序容器随后会挂载写入密钥的卷。与 Amazon S3 存储桶方法类似，必须编写您的应用程序以从共享卷中读取密钥。由于该卷的作用域仅限于任务，因此该卷将在任务停止后自动删除。有关示例，请参阅 [task-def.json](https://github.com/aws-samples/aws-secret-sidecar-injector/blob/master/ecs-task-def/task-def.json) 项目。

在 Amazon EC2 上，可使用 AWS KMS 客户托管密钥对写入密钥的卷进行加密。在 AWS Fargate 上，使用服务托管密钥自动加密卷存储。

# 将单个环境变量传递给 Amazon ECS 容器
<a name="taskdef-envfiles"></a>

**重要**  
我们建议将您的敏感数据存储在 AWS Secrets Manager 密钥或 AWS Systems Manager Parameter Store 参数中。有关更多信息，请参阅 [将敏感数据传递给 Amazon ECS 容器](specifying-sensitive-data.md)。  
任务定义中指定的环境变量可由允许执行任务定义 `DescribeTaskDefinition` 操作的所有用户和角色读取。

您可以通过以下方式将环境变量传递到容器：
+ 单独，使用 `environment` 容器定义参数。这会将 `--env` 选项映射到 [https://docs.docker.com/reference/cli/docker/container/run/](https://docs.docker.com/reference/cli/docker/container/run/)。
+ 批量，使用 `environmentFiles` 容器定义参数列出包含环境变量的一个或多个文件。该文件必须托管在 Amazon S3 中。这会将 `--env-file` 选项映射到 [https://docs.docker.com/reference/cli/docker/container/run/](https://docs.docker.com/reference/cli/docker/container/run/)。

以下是演示如何指定单个环境变量的任务定义的代码段。

```
{
    "family": "",
    "containerDefinitions": [
        {
            "name": "",
            "image": "",
            ...
            "environment": [
                {
                    "name": "variable",
                    "value": "value"
                }
            ],
            ...
        }
    ],
    ...
}
```

# 将环境变量传递给 Amazon ECS 容器
<a name="use-environment-file"></a>

**重要**  
我们建议将您的敏感数据存储在 AWS Secrets Manager 密钥或 AWS Systems Manager Parameter Store 参数中。有关更多信息，请参阅 [将敏感数据传递给 Amazon ECS 容器](specifying-sensitive-data.md)。  
环境变量文件是 Amazon S3 中的对象，所有 Amazon S3 安全注意事项都适用。  
您不能在 Windows 容器和 Fargate 上的 Windows 容器上使用 `environmentFiles` 参数。

您可以创建环境变量文件，并将其存储在 Amazon S3 中，以便将环境变量传递给您的容器。

通过在文件中指定环境变量，您可以批量注入环境变量。在容器定义中，使用包含环境变量文件的 Amazon S3 存储桶列表指定 `environmentFiles` 对象。

Amazon ECS 不对环境变量强制实施大小限制，但大型环境变量文件可能会填满磁盘空间。使用环境变量文件的每个任务都会导致文件的副本下载到磁盘。作为任务清理的一部分，Amazon ECS 会删除文件。

有关支持的环境变量的信息，请参阅[高级容器定义参数：环境](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_environment)。

在容器定义中指定环境变量文件时，请考虑以下因素。
+ 对于 Amazon EC2 上的 Amazon ECS 任务，您的容器实例需要版本 `1.39.0` 或更高版本的容器代理才能使用此功能。有关如何检查您的代理版本并更新到最新版本的信息，请参阅[更新 Amazon ECS 容器代理](ecs-agent-update.md)。
+ 对于 AWS Fargate 上的 Amazon ECS 任务，您的任务必须使用平台版本 `1.4.0` 或更高版本（Linux）来使用此功能。有关更多信息，请参阅 [适用于 Amazon ECS 的 Fargate 平台版本](platform-fargate.md)。

  验证操作系统平台是否支持该变量。有关更多信息，请参阅 [容器定义](task_definition_parameters.md#container_definitions) 和 [其他任务定义参数](task_definition_parameters.md#other_task_definition_params)。
+ 该文件必须使用 `.env` 文件扩展名和 UTF-8 编码。
+ 该任务执行角色需要使用此功能和 Amazon S3 的额外权限。这允许容器代理从 Amazon S3 中提取环境变量文件。有关更多信息，请参阅 [Amazon ECS 任务执行 IAM 角色](task_execution_IAM_role.md)。
+ 每个任务定义最多只能有 10 个文件。
+ 环境文件中的每一行都必须包含 `VARIABLE=VALUE` 格式的环境变量。空格或引号作为 Amazon ECS 文件的值的一部分**包含**。以开头的行 `#` 被视为注释并会被忽略。有关环境变量文件语法的更多信息，请参阅 Docker 文档中的 [Set environment variables (-e, --env, --env-file)](https://docs.docker.com/reference/cli/docker/container/run/#env)。

  以下是合适的语法。

  ```
  #This is a comment and will be ignored
  VARIABLE=VALUE
  ENVIRONMENT=PRODUCTION
  ```
+ 如果在容器定义中存在使用 `environment` 参数指定的环境变量，则这些变量的优先级高于环境文件中包含的变量。
+ 如果指定了多个环境文件并且其中包含相同变量，则会按输入顺序处理这些文件。这意味着将使用变量的第一个值，并忽略重复变量的后续值。建议您使用唯一的变量名。
+ 如果将环境文件指定为容器覆盖，则将使用它。此外，容器定义中指定的任何其他环境文件都将被忽略。
+ 以下规则适用于 Fargate：
  + 该文件的处理方式与原生 Docker env-file 类似。
  + 容器中不会出现引用了空白且存储在 Amazon S3 中的环境变量的容器定义。
  + 不支持 shell 转义处理。
  + 容器入口点解释 `VARIABLE` 值。

## 示例
<a name="environment-file-example"></a>

以下是演示如何指定环境变量文件的任务定义的代码段。

```
{
    "family": "",
    "containerDefinitions": [
        {
            "name": "",
            "image": "",
            ...
            "environmentFiles": [
                {
                    "value": "arn:aws:s3:::amzn-s3-demo-bucket/envfile_object_name.env",
                    "type": "s3"
                }
            ],
            ...
        }
    ],
    ...
}
```

# 在 Amazon ECS 中以编程方式传递 Secrets Manager 密钥
<a name="secrets-app-secrets-manager"></a>

您可以使用 Secrets Manager 来存储敏感数据，而不是在应用程序中以纯文本形式对敏感信息进行硬编码。

我们建议使用这种方法来检索敏感数据，因为如果随后更新 Secrets Manager 密钥，应用程序会自动检索该密钥的最新版本。

可以在 Secrets Manager 中创建秘密。创建 Secrets Manager 密钥后，更新应用程序代码以检索该密钥。

在 Secrets Manager 中保护敏感数据之前，请查看以下注意事项。
+ 仅存储文本数据的机密，这些机密是使用 `SecretString` 参数 [CreateSecret](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_CreateSecret.html) 支持 API。不支持存储二进制数据的密钥，这些密钥是使用 [CreateSecret](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_CreateSecret.html) API 的 `SecretBinary` 参数创建的。
+ 使用接口 VPC 端点增强安全控制。您必须为 Secrets Manager 创建接口 VPC 端点。有关 VPC 端点的信息，请参阅《AWS Secrets Manager 用户指南》**中的[创建 VPC 端点](https://docs.aws.amazon.com/secretsmanager/latest/userguide/setup-create-vpc.html)。
+ 您的任务使用的 VPC 必须使用 DNS 解析。
+ 任务定义必须使用具有额外 Secrets Manager 权限的任务角色。有关更多信息，请参阅 [Amazon ECS 任务 IAM 角色](task-iam-roles.md)。

## 创建 Secrets Manager 密钥
<a name="secrets-app-secrets-manager-create-secret"></a>

您可以使用 Secrets Manager 控制台为您的敏感数据创建密钥。有关如何创建密钥的信息，请参阅**《AWS Secrets Manager 用户指南》中的[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)。

## 更新应用程序以通过编程方式检索 Secrets Manager 密钥
<a name="secrets-app-secrets-manager-update-app"></a>

您可以直接从应用程序调用 Secrets Manager API 来检索密钥。有关信息，请参阅《AWS Secrets Manager 用户指南》**中的[从 AWS Secrets Manager 中检索密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets.html)。

要检索存储在 AWS Secrets Manager 中的敏感数据，请参阅 *AWS SDK 代码示例代码库*中的[使用 AWS SDK 的 AWS Secrets Manager 的代码示例](https://docs.aws.amazon.com/code-library/latest/ug/secrets-manager_code_examples.html)。

# 在 Amazon ECS 中以编程方式传递 Systems Manager Parameter Store 密钥
<a name="secrets-app-ssm-paramstore"></a>

Systems Manager Parameter Store 提供了密钥的安全存储和管理。您可以将密码、数据库字符串、EC2 实例 ID 和 AMI ID 以及许可证代码等数据存储为参数值，而不是在应用程序中将这些信息硬编码。可以将值存储为纯文本或加密数据。

建议使用这种方法来检索敏感数据，因为如果随后更新 Systems Manager Parameter Store 参数，应用程序会自动检索最新版本。

在 Systems Manager Parameter Store 中保护敏感数据之前，请查看以下注意事项。
+ 仅支持存储文本数据的密钥。不支持存储二进制数据的密钥。
+ 使用接口 VPC 端点增强安全控制。
+ 您的任务使用的 VPC 必须使用 DNS 解析。
+ 对于使用 EC2 的任务，必须使用 Amazon ECS 代理配置变量 `ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE=true` 才能使用此功能。您可以在创建容器实例的过程中将其添加到 `/etc/ecs/ecs.config` 文件中，也可以将其添加到现有实例中，然后重新启动 ECS 代理。有关更多信息，请参阅 [Amazon ECS 容器代理配置](ecs-agent-config.md)。
+ 任务定义必须使用具有额外 Systems Manager Parameter Store 权限的任务角色。有关更多信息，请参阅 [Amazon ECS 任务 IAM 角色](task-iam-roles.md)。

## 创建 参数
<a name="secrets-app-ssm-paramstore-create-secret"></a>

您可以使用 Systems Manager 控制台为您的敏感数据创建 Systems Manager Parameter Store 参数。有关更多信息，请参阅**《AWS Systems Manager 用户指南》中的[创建 Systems Manager 参数（控制台）](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-create-console.html)或[创建 Systems Manager 参数（AWS CLI）](https://docs.aws.amazon.com/systems-manager/latest/userguide/param-create-cli.html)。

## 更新应用程序以通过编程方式检索 Systems Manager Parameter Store 密钥
<a name="secrets-app-ssm-paramstore-update-app"></a>

要检索存储在 Systems Manager Parameter Store 参数中存储的敏感数据，请参阅 *AWS SDK 代码示例代码库*中的[使用 AWS SDK 的 Systems Manager 的代码示例](https://docs.aws.amazon.com/code-library/latest/ug/ssm_code_examples.html)。

# 通过 Amazon ECS 环境变量传递 Secrets Manager 密钥
<a name="secrets-envvar-secrets-manager"></a>

当您将密钥作为环境变量注入时，可以指定密钥的完整内容、密钥内的特定 JSON 键。这将帮助您控制提供给容器的敏感数据。有关密钥版本控制的更多信息，请参阅《AWS Secrets Manager 用户指南》**中的 [What's in a Secrets Manager secret?](https://docs.aws.amazon.com/secretsmanager/latest/userguide/whats-in-a-secret.html#term_version)。

在使用环境变量将 Secrets Manager 密钥注入容器时，应考虑以下事项。
+ 最初启动容器时，会将敏感数据注入容器中。如果随后更新或轮换密钥，则容器将不会自动接收更新后的值。您必须启动新任务，或者如果您的任务是服务的一部分，则可以更新服务并使用**强制新部署**选项来强制服务启动新任务。
+ 在容器上运行的应用程序以及容器日志和调试工具可以访问环境变量。
+ 对于 AWS Fargate 上的 Amazon ECS 任务，请考虑以下事项：
  + 要将密钥的完整内容注入为环境变量或注入到日志配置中，您必须使用平台版本 `1.3.0` 或更高版本的平台。有关信息，请参阅[适用于 Amazon ECS 的 Fargate 平台版本](platform-fargate.md)。
  + 要将特定 JSON 密钥或密钥版本注入为环境变量或注入到日志配置中，您必须使用平台版本 `1.4.0` 或更高版本（Linux）或者 `1.0.0`（Windows）。有关信息，请参阅[适用于 Amazon ECS 的 Fargate 平台版本](platform-fargate.md)。
+ 对于 EC2 上的 Amazon ECS 任务，应注意以下事项：
  + 要使用特定的 JSON 密钥或密钥版本注入密钥，容器实例必须具有版本 `1.37.0` 或更高版本的容器代理。但是，我们建议使用最新的容器代理版本。有关检查您的代理版本并更新到最新版本的信息，请参阅[更新 Amazon ECS 容器代理](ecs-agent-update.md)。

    要将密钥的完整内容注入为环境变量或将密钥注入日志配置中，您的容器实例必须具有版本 `1.22.0` 或更高版本的容器代理。
+ 使用接口 VPC 端点增强安全控制措施，并通过私有子网连接到 Secrets Manager。您必须为 Secrets Manager 创建接口 VPC 端点。有关 VPC 端点的信息，请参阅《AWS Secrets Manager 用户指南》**中的[创建 VPC 端点](https://docs.aws.amazon.com/secretsmanager/latest/userguide/setup-create-vpc.html)。有关使用 Secrets Manager 和 Amazon VPC 的更多信息，请参阅[如何在 Amazon VPC 内连接到 Secrets Manager 服务](https://aws.amazon.com/blogs//security/how-to-connect-to-aws-secrets-manager-service-within-a-virtual-private-cloud/)。
+ 对于配置为使用 `awslogs` 日志记录驱动程序的 Windows 任务，您还必须在容器实例上设置 `ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE` 环境变量。使用以下语法：

  ```
  <powershell>
  [Environment]::SetEnvironmentVariable("ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE", $TRUE, "Machine")
  Initialize-ECSAgent -Cluster <cluster name> -EnableTaskIAMRole -LoggingDrivers '["json-file","awslogs"]'
  </powershell>
  ```
+ 任务定义必须使用具有 Secrets Manager 额外权限的任务执行角色。有关更多信息，请参阅 [Amazon ECS 任务执行 IAM 角色](task_execution_IAM_role.md)。

## 创建 AWS Secrets Manager 密钥
<a name="secrets-envvar-secrets-manager-create-secret"></a>

您可以使用 Secrets Manager 控制台为您的敏感数据创建密钥。有关更多信息，请参阅**《AWS Secrets Manager 用户指南》中的[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)。

## 将环境变量添加到容器定义中
<a name="secrets-envvar-secrets-manager-update-container-definition"></a>

在容器定义中，可以指定以下内容：
+ `secrets` 对象，该对象包含要在容器中设置的环境变量名称
+ Secrets Manager 密钥的 Amazon 资源名称（ARN）。
+ 其他参数，这些参数包含要提供给容器的敏感数据

以下示例显示必须为 Secrets Manager 密钥指定的完整语法。

```
arn:aws:secretsmanager:region:aws_account_id:secret:secret-name:json-key:version-stage:version-id
```

下一部分介绍了其他参数。这些参数是可选的，但如果不使用它们，则必须包含冒号 `:` 以使用默认值。下面提供了示例，以便您了解更多上下文。

`json-key`  
使用要设置为环境变量值的值指定密钥-值对中密钥的名称。仅支持 JSON 格式的值。如果未指定 JSON 密钥，则使用密钥的完整内容。

`version-stage`  
指定要使用的密钥版本的暂存标签。如果指定了版本的暂存标签，则无法指定版本 ID。如果未指定版本阶段，则默认行为是使用 `AWSCURRENT` 暂存标签检索密钥。  
暂存标签用于在更新或轮换密钥的各个版本时对其进行跟踪。密钥的每个版本均有一个或多个暂存标签和一个 ID。

`version-id`  
指定要使用的密钥版本的唯一标识符。如果指定了版本 ID，则无法指定版本暂存标签。如果未指定版本 ID，则默认行为是使用 `AWSCURRENT` 暂存标签检索密钥。  
版本 ID 用于在更新或轮换密钥的各个版本时对其进行跟踪。密码的每个版本均有一个 ID。有关更多信息，请参阅 *AWS Secrets Manager 用户指南*中的 [AWS Secrets Manager 主要术语和概念。](https://docs.aws.amazon.com/secretsmanager/latest/userguide/terms-concepts.html#term_secret)

### 示例容器定义
<a name="secrets-examples"></a>

以下示例说明了可用于在容器定义中引用 Secrets Manager 密钥的方法。

**Example 引用完整密钥**  
以下是任务定义的片段，其中显示引用 Secrets Manager 密钥的完全文本时的格式。  

```
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name-AbCdEf"
    }]
  }]
}
```
要从容器中访问此密钥的值，需要调用 `$environment_variable_name`。

**Example 引用完整密钥**  
以下是任务定义的片段，其中显示引用多个 Secrets Manager 密钥的完全文本时的格式。  

```
{
  "containerDefinitions": [{
     "secrets": [
      {
        "name": "environment_variable_name1",
         "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name-AbCdEf"
      },
      {
        "name": "environment_variable_name2",
         "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name-abcdef"
      },
      {
        "name": "environment_variable_name3",
        "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name-ABCDEF"
      }
    ]
  }]
}
```
要从容器中访问此密钥的值，需要调用 `$environment_variable_name1`、`$environment_variable_name2` 和 `$environment_variable_name3`。

**Example 引用密钥中的特定密钥**  
下面显示了 [get-secret-value](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/get-secret-value.html) 命令中的示例输出，其中显示了密钥的内容以及与之关联的版本暂存标签和版本 ID。  

```
{
    "ARN": "arn:aws:secretsmanager:region:aws_account_id:secret:appauthexample-AbCdEf",
    "Name": "appauthexample",
    "VersionId": "871d9eca-18aa-46a9-8785-981ddEXAMPLE",
    "SecretString": "{\"username1\":\"password1\",\"username2\":\"password2\",\"username3\":\"password3\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1581968848.921
}
```
通过在 ARN 的末尾指定密钥名称，引用容器定义中的上一个输出中的特定密钥。  

```
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:appauthexample-AbCdEf:username1::"
    }]
  }]
}
```

**Example 引用特定的密钥版本**  
下面显示了 [describe-secret](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/describe-secret.html) 命令中的示例输出，其中显示了密钥的未加密内容以及密钥的所有版本的元数据。  

```
{
    "ARN": "arn:aws:secretsmanager:region:aws_account_id:secret:appauthexample-AbCdEf",
    "Name": "appauthexample",
    "Description": "Example of a secret containing application authorization data.",
    "RotationEnabled": false,
    "LastChangedDate": 1581968848.926,
    "LastAccessedDate": 1581897600.0,
    "Tags": [],
    "VersionIdsToStages": {
        "871d9eca-18aa-46a9-8785-981ddEXAMPLE": [
            "AWSCURRENT"
        ],
        "9d4cb84b-ad69-40c0-a0ab-cead3EXAMPLE": [
            "AWSPREVIOUS"
        ]
    }
}
```
通过在 ARN 的末尾指定密钥名称，引用容器定义中的上一个输出中的特定版本暂存标签。  

```
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:appauthexample-AbCdEf::AWSPREVIOUS:"
    }]
  }]
}
```
通过在 ARN 的末尾指定密钥名称，引用容器定义中的上一个输出中的特定版本 ID。  

```
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:appauthexample-AbCdEf:::9d4cb84b-ad69-40c0-a0ab-cead3EXAMPLE"
    }]
  }]
}
```

**Example 引用密钥的特定密钥和版本暂存标签**  
以下内容说明如何同时引用密钥中的特定密钥和特定版本暂存标签。  

```
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:appauthexample-AbCdEf:username1:AWSPREVIOUS:"
    }]
  }]
}
```
要指定特定密钥和版本 ID，请使用以下语法。  

```
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:appauthexample-AbCdEf:username1::9d4cb84b-ad69-40c0-a0ab-cead3EXAMPLE"
    }]
  }]
}
```

有关如何使用环境变量中指定的密钥创建任务定义的信息，请参阅 [使用控制台创建 Amazon ECS 任务定义](create-task-definition.md)。

# 通过 Amazon ECS 环境变量传递 Systems Manager 参数
<a name="secrets-envvar-ssm-paramstore"></a>

您可以使用 Amazon ECS 向容器中注入敏感数据，方法是将您的敏感数据存储在 AWS Systems Manager Parameter Store 参数中，然后在容器定义中引用它们。

在使用环境变量将 Systems Manager 密钥注入容器时，应注意以下事项。
+ 最初启动容器时，会将敏感数据注入容器中。如果随后更新或轮换密钥，则容器将不会自动接收更新后的值。您必须启动新任务，或者如果您的任务是服务的一部分，则可以更新服务并使用**强制新部署**选项来强制服务启动新任务。
+ 对于 AWS Fargate 上的 Amazon ECS 任务，应注意以下事项：
  + 要将密钥的完整内容注入为环境变量或注入到日志配置中，您必须使用平台版本 `1.3.0` 或更高版本的平台。有关信息，请参阅[适用于 Amazon ECS 的 Fargate 平台版本](platform-fargate.md)。
  + 要将特定 JSON 密钥或密钥版本注入为环境变量或注入到日志配置中，您必须使用平台版本 `1.4.0` 或更高版本（Linux）或者 `1.0.0`（Windows）。有关信息，请参阅[适用于 Amazon ECS 的 Fargate 平台版本](platform-fargate.md)。
+ 对于 EC2 上的 Amazon ECS 任务，应注意以下事项：
  + 要使用特定的 JSON 密钥或密钥版本注入密钥，容器实例必须具有版本 `1.37.0` 或更高版本的容器代理。但是，我们建议使用最新的容器代理版本。有关检查您的代理版本并更新到最新版本的信息，请参阅[更新 Amazon ECS 容器代理](ecs-agent-update.md)。

    要将密钥的完整内容注入为环境变量或将密钥注入日志配置中，您的容器实例必须具有版本 `1.22.0` 或更高版本的容器代理。
+ 使用接口 VPC 端点增强安全控制。您必须为 Systems Manager 创建接口 VPC 端点。有关 VPC 端点的信息，请参阅《AWS Systems Manager 用户指南》**中的[使用适用于 Systems Manager 的 VPC 端点提高 EC2 实例的安全性](https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-create-vpc.html)。
+ 任务定义必须使用具有额外 Systems Manager Parameter Store 权限的任务执行角色。有关更多信息，请参阅 [Amazon ECS 任务执行 IAM 角色](task_execution_IAM_role.md)。
+ 对于配置为使用 `awslogs` 日志记录驱动程序的 Windows 任务，您还必须在容器实例上设置 `ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE` 环境变量。使用以下语法：

  ```
  <powershell>
  [Environment]::SetEnvironmentVariable("ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE", $TRUE, "Machine")
  Initialize-ECSAgent -Cluster <cluster name> -EnableTaskIAMRole -LoggingDrivers '["json-file","awslogs"]'
  </powershell>
  ```

## 创建 Systems Manager 参数
<a name="secrets-envvar-ssm-paramstore-create-parameter"></a>

您可以使用 Systems Manager 控制台为您的敏感数据创建 Systems Manager Parameter Store 参数。有关更多信息，请参阅**《AWS Systems Manager 用户指南》中的[创建 Systems Manager 参数（控制台）](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-create-console.html)或[创建 Systems Manager 参数（AWS CLI）](https://docs.aws.amazon.com/systems-manager/latest/userguide/param-create-cli.html)。

## 将环境变量添加到容器定义中
<a name="secrets-ssm-paramstore-update-container-definition"></a>

在任务定义中的容器定义中，使用要在容器中设置的环境变量的名称以及包含要提供给容器的敏感数据的 Systems Manager Parameter Store 参数完整 ARN 指定 `secrets`。有关更多信息，请参阅 [secrets](task_definition_parameters.md#ContainerDefinition-secrets)。

以下是任务定义的片段，其中显示引用 Systems Manager Parameter Store 参数时的格式。如果 Systems Manager Parameter Store 参数存在于要启动的任务所在的区域，则可以使用参数的完整 ARN 或名称。如果参数存在于不同的区域，则指定完整的 ARN。

```
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:ssm:region:aws_account_id:parameter/parameter_name"
    }]
  }]
}
```

有关如何使用环境变量中指定的密钥创建任务定义的信息，请参阅 [使用控制台创建 Amazon ECS 任务定义](create-task-definition.md)。

## 更新应用程序以通过编程方式检索 Systems Manager Parameter Store 密钥
<a name="secrets-ssm-paramstore-update-app"></a>

要检索存储在 Systems Manager Parameter Store 参数中存储的敏感数据，请参阅 *AWS SDK 代码示例代码库*中的[使用 AWS SDK 的 Systems Manager 的代码示例](https://docs.aws.amazon.com/code-library/latest/ug/ssm_code_examples.html)。

# 传递用于 Amazon ECS 日志记录配置的密钥
<a name="secrets-logconfig"></a>

您可以使用 `logConfiguration` 中的 `secretOptions` 参数来传递用于日志记录的敏感数据。

您可以将密钥存储在 Secrets Manager 或 Systems Manager 中。

## 使用 Secrets Manager
<a name="secrets-logconfig-secrets-manager"></a>

在容器定义中，当指定 `logConfiguration` 时，您可以同时指定 `secretOptions`，方法是使用要在容器中设置的日志驱动程序选项的名称，以及包含要提供给容器的敏感数据的 Secrets Manager 密钥的完整 ARN。有关创建密钥的更多信息，请参阅[创建 AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)。

以下是任务定义的片段，其中显示引用 Secrets Manager 密钥时的格式。

```
{
  "containerDefinitions": [{
    "logConfiguration": [{
      "logDriver": "splunk",
      "options": {
        "splunk-url": "https://your_splunk_instance:8088"
      },
      "secretOptions": [{
        "name": "splunk-token",
        "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name-AbCdEf"
      }]
    }]
  }]
}
```

## 将环境变量添加到容器定义中
<a name="secrets-envvar-ssm-paramstore-update-container-definition"></a>

在容器定义中，使用要在容器中设置的环境变量的名称和包含要提供给容器的敏感数据的 Systems Manager Parameter Store 参数的完整 ARN 指定 `secrets`。有关更多信息，请参阅 [secrets](task_definition_parameters.md#ContainerDefinition-secrets)。

以下是任务定义的片段，其中显示引用 Systems Manager Parameter Store 参数时的格式。如果 Systems Manager Parameter Store 参数存在于要启动的任务所在的区域，则可以使用参数的完整 ARN 或名称。如果参数存在于不同的区域，则指定完整的 ARN。

```
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:ssm:region:aws_account_id:parameter/parameter_name"
    }]
  }]
}
```

有关如何使用环境变量中指定的密钥创建任务定义的信息，请参阅 [使用控制台创建 Amazon ECS 任务定义](create-task-definition.md)。

## 使用 Systems Manager
<a name="secrets-logconfig-ssm-paramstore"></a>

您可以在日志配置中注入敏感数据。在容器定义中，当指定 `logConfiguration` 时，您可以使用要在容器中设置的日志驱动程序选项的名称以及包含要提供给容器的敏感数据的 Systems Manager Parameter Store 参数的完整 ARN 指定 `secretOptions`。

**重要**  
如果 Systems Manager Parameter Store 参数存在于要启动的任务所在的区域，则可以使用参数的完整 ARN 或名称。如果参数存在于不同的区域，则指定完整的 ARN。

以下是任务定义的片段，其中显示引用 Systems Manager Parameter Store 参数时的格式。

```
{
  "containerDefinitions": [{
    "logConfiguration": [{
      "logDriver": "fluentd",
      "options": {
        "tag": "fluentd demo"
      },
      "secretOptions": [{
        "name": "fluentd-address",
        "valueFrom": "arn:aws:ssm:region:aws_account_id:parameter:/parameter_name"
      }]
    }]
  }]
}
```

# 在 Amazon ECS 中指定使用 Secrets Manager 密钥的敏感数据
<a name="specifying-sensitive-data-tutorial"></a>

使用 Amazon ECS 时，您可以将敏感数据存储在 AWS Secrets Manager 密钥中，然后在容器定义中引用这些密钥，从而将敏感数据注入容器。有关更多信息，请参阅 [将敏感数据传递给 Amazon ECS 容器](specifying-sensitive-data.md)。

了解如何创建 Secrets Manager 密钥，在 Amazon ECS 任务定义中引用该密钥，然后通过查询显示密钥内容的容器内的环境变量来验证它是否有效。

## 先决条件
<a name="specifying-sensitive-data-tutorial-prereqs"></a>

本教程假设以下先决条件已完成：
+ [设置以使用 Amazon ECS](get-set-up-for-amazon-ecs.md) 中的步骤已完成。
+ 您的用户具有创建 Secrets Manager 和 Amazon ECS 资源所需的 IAM 权限。

## 步骤 1：创建 Secrets Manager 密钥
<a name="specifying-sensitive-data-tutorial-create-secret"></a>

您可以使用 Secrets Manager 控制台为您的敏感数据创建密钥。在本教程中，我们将创建一个基本密钥来存储用户名和密码以便稍后在容器中引用。有关更多信息，请参阅《AWS Secrets Manager 用户指南》**中的[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)。

**key/value pairs to be stored in this secret**（要存储在此密钥中的键/值对）是教程末尾处容器中的环境变量值。

保存**密钥 ARN** 以便在后续步骤中在任务执行 IAM 策略和任务定义中引用。

## 步骤 2：向任务执行角色添加密钥权限
<a name="specifying-sensitive-data-tutorial-update-iam"></a>

为了让 Amazon ECS 检索 Secrets Manager 密钥中的敏感数据，您必须具有任务执行角色的密钥权限。有关更多信息，请参阅 [Secrets Manager 或 Systems Manager 权限](task_execution_IAM_role.md#task-execution-secrets)。

## 步骤 3：创建任务定义
<a name="specifying-sensitive-data-tutorial-create-taskdef"></a>

可以使用 Amazon ECS 控制台创建引用了 Secrets Manager 密钥的任务定义。

**创建指定密钥的任务定义**

使用 IAM 控制台更新具有所需权限的任务执行角色。

1. 在 [https://console.aws.amazon.com/ecs/v2](https://console.aws.amazon.com/ecs/v2) 打开控制台。

1. 在导航窗格中，选择 **Task definitions**（任务定义）。

1. 选择 **Create new task definition**（创建新的任务定义）、**Create new task definition with JSON**（使用 JSON 创建新的任务定义）。

1. 在 JSON 编辑器框中，输入以下任务定义 JSON 文本，确保已指定在步骤 1 中创建的 Secrets Manager 密钥的完整 ARN，以及在步骤 2 中更新的任务执行角色。选择**保存**。

1. 

   ```
   {
       "executionRoleArn": "arn:aws:iam::aws_account_id:role/ecsTaskExecutionRole",
       "containerDefinitions": [
           {
               "entryPoint": [
                   "sh",
                   "-c"
               ],
               "portMappings": [
                   {
                       "hostPort": 80,
                       "protocol": "tcp",
                       "containerPort": 80
                   }
               ],
               "command": [
                   "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' >  /usr/local/apache2/htdocs/index.html && httpd-foreground\""
               ],
               "cpu": 10,
               "secrets": [
                   {
                       "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:username_value",
                       "name": "username_value"
                   }
               ],
               "memory": 300,
               "image": "public.ecr.aws/docker/library/httpd:2.4",
               "essential": true,
               "name": "ecs-secrets-container"
           }
       ],
       "family": "ecs-secrets-tutorial"
   }
   ```

1. 选择**创建**。

## 步骤 4：创建集群
<a name="specifying-sensitive-data-tutorial-create-cluster"></a>

您可以使用 Amazon ECS 控制台创建一个包含要运行任务的容器实例的集群。如果现有集群中至少注册了一个容器实例，并且具有可用资源来运行为本教程创建的任务定义的一个实例，则可跳到下一步。

在本教程中，我们将使用经 Amazon ECS 优化的 Amazon Linux 2 AMI 创建具有一个 `t2.micro` 容器实例的集群。

有关如何为 EC2 创建集群的信息，请参阅 [为 Amazon EC2 工作负载创建 Amazon ECS 集群](create-ec2-cluster-console-v2.md)。

## 步骤 5：运行任务
<a name="specifying-sensitive-data-tutorial-run-task"></a>

您可以使用 Amazon ECS 控制台通过创建的任务定义运行任务。在本教程中，我们将使用上一步中创建的集群来运行使用 EC2 的任务。

有关如何运行任务的信息，请参阅 [将应用程序作为 Amazon ECS 任务运行](standalone-task-create.md)。

## 步骤 6：验证
<a name="specifying-sensitive-data-tutorial-verify"></a>

您可以使用以下步骤验证是否已成功完成所有步骤并在容器中正确创建了环境变量。

**验证是否已创建环境变量**

1. 查找您的容器实例的公共 IP 或 DNS 地址。

   1. 在 [https://console.aws.amazon.com/ecs/v2](https://console.aws.amazon.com/ecs/v2) 打开控制台。

   1. 在导航窗格中，选择**集群**，然后选择您创建的集群。

   1. 选择**基础设施**，然后选择容器实例。

   1. 记录您的实例的**公有 IP** 或**公有 DNS**。

1. 如果您使用的是 macOS 或 Linux 计算机，请使用以下命令连接到您的实例，并替换您的私有密钥的路径和实例的公共地址：

   ```
   $ ssh -i /path/to/my-key-pair.pem ec2-user@ec2-198-51-100-1.compute-1.amazonaws.com
   ```

   有关使用 Windows 计算机的更多信息，请参阅《Amazon EC2 用户指南》**中的[使用 PuTTY 连接到 Linux 实例](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-linux-inst-from-windows.html)。
**重要**  
要详细了解您在连接到实例时遇到的任何问题，请参阅《Amazon EC2 用户指南》中的[排查实例的连接问题](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesConnecting.html)**。

1. 列出正在实例上运行的容器。记下 `ecs-secrets-tutorial` 容器的容器 ID。

   ```
   docker ps
   ```

1. 使用上一步的输出中的容器 ID 连接到 `ecs-secrets-tutorial` 容器。

   ```
   docker exec -it container_ID /bin/bash
   ```

1. 使用 `echo` 命令打印环境变量的值。

   ```
   echo $username_value
   ```

   如果教程成功完成，您应看到以下输出：

   ```
   password_value
   ```
**注意**  
或者，您可以使用 `env`（或 `printenv`）命令列出容器中的所有环境变量。

## 步骤 7：清除
<a name="specifying-sensitive-data-tutorial-cleanup"></a>

完成本教程后，您应清除相关资源，以避免产生与未使用的资源相关的费用。

**清除资源**

1. 在 [https://console.aws.amazon.com/ecs/v2](https://console.aws.amazon.com/ecs/v2) 打开控制台。

1. 在导航窗格中，选择**集群**。

1. 在 **Clusters**（集群）页面上，选择集群。

1. 选择**删除集群**。

1. 在确认框中，输入 **delete *cluster name***，然后选择**删除**。

1. 通过以下网址打开 IAM 控制台：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 在导航窗格中，选择**角色**。

1. 在角色列表中搜索 `ecsTaskExecutionRole` 并将其选定。

1. 选择**权限**，然后选择 **ECSSecretsTutorial** 旁边的 **X**。选择**移除 **。

1. 通过 [https://console.aws.amazon.com/secretsmanager/](https://console.aws.amazon.com/secretsmanager/) 打开 Secrets Manager 控制台。

1. 选择您之前创建的 **username\$1value** 密钥，然后选择**操作**、**删除密钥**。