

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 安全性 AWS AppConfig
<a name="appconfig-security"></a>

云安全 AWS 是重中之重。作为 AWS 客户，您可以从专为满足大多数安全敏感型组织的要求而构建的数据中心和网络架构中受益。

安全是双方共同承担 AWS 的责任。[责任共担模式](https://aws.amazon.com/compliance/shared-responsibility-model/)将其描述为云*的*安全性和云*中*的安全性：
+ **云安全** — AWS 负责保护在云中运行 AWS 服务的基础架构 AWS 云。 AWS 还为您提供可以安全使用的服务。作为[AWS 合规计划合规计划合规计划合](https://aws.amazon.com/compliance/programs/)的一部分，第三方审计师定期测试和验证我们安全的有效性。要了解适用的合规计划 AWS Systems Manager，请参阅按合规计划划分的[范围内的AWSAWS 服务按合规计划](https://aws.amazon.com/compliance/services-in-scope/)。
+ **云端安全**-您的责任由您使用的 AWS 服务决定。您还需要对其他因素负责，包括您的数据的敏感性、您公司的要求以及适用的法律法规。

AWS AppConfig 是一个工具 AWS Systems Manager。要了解在使用时如何应用分担责任模型 AWS AppConfig，请参阅[中的 “安全” AWS Systems Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/security.html)。本节介绍了如何配置 Systems Manager 以实现 AWS AppConfig的安全性和合规性目标。

## 实施最低权限访问
<a name="appconfig-security-least-privilege-access"></a>

作为安全最佳实践，应授予身份在特定条件下对特定资源执行特定操作所需的最低权限。 AWS AppConfig 代理提供两种功能，使代理能够访问实例或容器的文件系统：*备份*和*写入磁盘*。如果启用这些功能，请确认只有 AWS AppConfig 代理才有权写入文件系统上的指定配置文件。还要验证只有从这些配置文件中进行读取所需的进程才能读取这些配置文件。实施最低权限访问对于减小安全风险以及可能由错误或恶意意图造成的影响至关重要。

有关实现最低权限访问的更多信息，请参阅SEC03《*AWS Well-Architected Tool 用户指南》*中的 “[BP02 授予最低权限访问权限](https://docs.aws.amazon.com/wellarchitected/latest/framework/sec_permissions_least_privileges.html)”。有关本节中提及的 AWS AppConfig 代理功能的更多信息，请参阅[使用清单启用其它检索功能](appconfig-agent-how-to-use-additional-features.md)。

## 静态数据加密 AWS AppConfig
<a name="appconfig-security-data-encryption"></a>

AWS AppConfig 默认情况下提供加密，以使用保护静态客户数据 AWS 拥有的密钥。

**AWS 拥有的密钥**— 默认 AWS AppConfig 使用这些密钥自动加密由服务部署并托管在 AWS AppConfig 数据存储中的数据。您无法查看、管理 AWS 拥有的密钥、使用或审核其使用情况。但是您无需执行任何工作或更改任何计划即可保护用于加密数据的密钥。有关更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的 [AWS 拥有的密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-owned-cmk)。

虽然您无法禁用此加密层或选择其他加密类型，但您可以指定在保存数据存储中托管的配置数据和部署配置 AWS AppConfig 数据时使用的客户托管密钥。

**客户托管密钥** — AWS AppConfig 支持使用您创建、拥有和管理的对称客户托管密钥，在现有 AWS 拥有的密钥密钥的基础上添加第二层加密。由于您可以完全控制这一层加密，因此可以执行以下任务：
+ 建立和维护密钥政策和授权
+ 建立和维护 IAM 策略
+ 启用和禁用密钥政策
+ 轮换加密材料
+ 添加 标签
+ 创建密钥别名
+ 计划删除密钥

有关更多信息，请参阅 *AWS Key Management Service 开发人员指南*中的[客户托管密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk)。

**AWS AppConfig 支持客户托管密钥**

AWS AppConfig 为配置数据的客户托管密钥加密提供支持。对于保存到 AWS AppConfig 托管数据存储的配置版本，客户可以在相应的配置文件`KmsKeyIdentifier`上设置。每次使用 `CreateHostedConfigurationVersion` API 操作创建新版本的配置数据时， AWS AppConfig 都会从中生成一个 AWS KMS 数据密钥，`KmsKeyIdentifier`以便在存储数据之前对其进行加密。以后访问数据时，无论是在`GetHostedConfigurationVersion`或 `StartDeployment` API 操作期间，都会使用有关生成的数据 AWS AppConfig 密钥的信息解密配置数据。

AWS AppConfig 还支持对已部署的配置数据进行客户托管密钥加密。要加密配置数据，客户可以`KmsKeyIdentifier`为其部署提供。 AWS AppConfig 使用它生成 AWS KMS 数据密钥`KmsKeyIdentifier`以加密 `StartDeployment` API 操作中的数据。

**AWS AppConfig 加密访问**

创建客户托管密钥时，请使用以下密钥政策来确保密钥可以使用。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::{{111122223333}}:role/{{role_name}}"
            },
            "Action": [
                "kms:Decrypt",
                "kms:GenerateDataKey"
            ],
            "Resource": "*"
        }
    ]
}
```

------

要使用客户托管密钥加密托管配置数据，`CreateHostedConfigurationVersion` 的身份调用需要以下可分配给用户、群组或角色的策略声明：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "kms:GenerateDataKey",
            "Resource": "arn:aws:kms:{{us-east-1}}:{{111122223333}}:key/{{key-ID}}"
        }
    ]
}
```

------

如果您使用的是 Secrets Manager 密钥或使用客户托管密钥加密的任何其他配置数据，则您的 `retrievalRoleArn` 将需要 `kms:Decrypt` 来解密和检索数据。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "kms:Decrypt",
      "Resource": "arn:aws:kms:{{us-east-1}}:{{111122223333}}:key/{{key-ID}}"
    }
  ]
}
```

------

调用 AWS AppConfig [StartDeployment](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_appconfigdata_StartDeployment.html)API 操作时，身份调用`StartDeployment`需要以下 IAM 策略，该策略可以分配给用户、群组或角色：

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:GenerateDataKey*"
      ],
      "Resource": "arn:aws:kms:{{us-east-1}}:{{111122223333}}:key/{{key-ID}}"
    }
  ]
}
```

------

在调用 AWS AppConfig [GetLatestConfiguration](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_appconfigdata_GetLatestConfiguration.html)API 操作时，身份调用`GetLatestConfiguration`需要以下可以分配给用户、组或角色的策略：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "kms:Decrypt",
            "Resource": "arn:aws:kms:{{us-east-1}}:{{111122223333}}:key/{{key-ID}}"
        }
    ]
}
```

------

**加密上下文**

[加密上下文](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)是一组可选的键值对，包含有关数据的其他上下文信息。

AWS KMS 使用加密上下文作为其他经过身份验证的数据来支持经过身份验证的加密。当您在加密数据的请求中包含加密上下文时，会将加密上下文 AWS KMS 绑定到加密数据。要解密数据，您必须在请求中包含相同的加密上下文。

 **AWS AppConfig 加密上下文**：在所有加密操作中 AWS AppConfig 使用加密上下 AWS KMS 文来处理加密的托管配置数据和部署。上下文包含一个与数据类型对应的键和一个用于标识特定数据项的值。

**监控您的加密密钥 AWS**

当您将 AWS KMS 客户托管密钥与一起使用时 AWS AppConfig，您可以使用 AWS CloudTrail 或 Amazon CloudWatch Logs 来跟踪 AWS AppConfig 发送到的请求 AWS KMS。

以下示例是一个 CloudTrail 事件，用于监控`Decrypt`为访问由 AWS AppConfig 您的客户托管密钥加密的数据而调用的 AWS KMS 操作：

```
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AWSService",
        "invokedBy": "appconfig.amazonaws.com"
    },
    "eventTime": "2023-01-03T02:22:28z",
    "eventSource": "kms.amazonaws.com",
    "eventName": "Decrypt",
    "awsRegion": "{{Region}}",
    "sourceIPAddress": "172.12.34.56",
    "userAgent": "ExampleDesktop/1.0 (V1; OS)",
    "requestParameters": {
        "encryptionContext": {
            "aws:appconfig:deployment:arn": "arn:aws:appconfig:{{Region}}:{{account_ID}}:application/{{application_ID}}/environment/{{environment_ID}}/deployment/{{deployment_ID}}"
        },
        "keyId": "arn:aws:kms:{{Region}}:{{account_ID}}:key/{{key_ID}}",
        "encryptionAlgorithm": "SYMMETRIC_DEFAULT"
    },
    "responseElements": null,
    "requestID": "ff000af-00eb-00ce-0e00-ea000fb0fba0SAMPLE",
    "eventID": "ff000af-00eb-00ce-0e00-ea000fb0fba0SAMPLE",
    "readOnly": true,
    "resources": [
        {
            "accountId": "{{account_ID}}",
            "type": "AWS::KMS::Key",
            "ARN": "arn:aws:kms:{{Region}}:{{account_ID}}:{{key_ID}}"
        }
    ],
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "eventCategory": "Management",
    "recipientAccountId": "{{account_ID}}",
    "sharedEventID": "dc129381-1d94-49bd-b522-f56a3482d088"
}
```

## AWS AppConfig 使用接口端点进行访问 (AWS PrivateLink)
<a name="vpc-interface-endpoints"></a>

您可以使用 AWS PrivateLink 在您的 VPC 和之间创建私有连接 AWS AppConfig。您可以像在 VPC 中 AWS AppConfig 一样进行访问，无需使用互联网网关、NAT 设备、VPN 连接或 Direct Connect 连接。VPC 中的实例不需要公有 IP 地址即可访问 AWS AppConfig。

您可以通过创建由 AWS PrivateLink提供支持的*接口端点*来建立此私有连接。我们将在您为接口端点启用的每个子网中创建一个端点网络接口。这些是请求者托管的网络接口，用作发往 AWS AppConfig的流量的入口点。

有关更多信息，请参阅《AWS PrivateLink 指南》**中的[通过 AWS PrivateLink访问 AWS 服务](https://docs.aws.amazon.com/vpc/latest/privatelink/privatelink-access-aws-services.html)。

### 的注意事项 AWS AppConfig
<a name="vpc-endpoint-considerations"></a>

在为设置接口终端节点之前 AWS AppConfig，请查看*AWS PrivateLink 指南*中的[注意事项](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html#considerations-interface-endpoints)。

AWS AppConfig 支持通过接口端点对[https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_Operations_Amazon_AppConfig.html](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_Operations_Amazon_AppConfig.html)和[https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_Operations_AWS_AppConfig_Data.html](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_Operations_AWS_AppConfig_Data.html)服务进行调用。

### 为创建接口终端节点 AWS AppConfig
<a name="vpc-endpoint-create"></a>

您可以创建用于 AWS AppConfig 使用 Amazon VPC 控制台或 AWS Command Line Interface (AWS CLI) 的接口终端节点。有关更多信息，请参阅《AWS PrivateLink 指南》**中的[创建接口端点](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html#create-interface-endpoint-aws)。

 AWS AppConfig 使用以下服务名称创建接口终端节点：

```
com.amazonaws.{{region}}.appconfig
```

```
com.amazonaws.{{region}}.appconfigdata
```

如果为接口端点启用私有 DNS，则可使用其默认区域 DNS 名称向 AWS AppConfig 发出 API 请求。例如，`appconfig.us-east-1.amazonaws.com` 和 `appconfigdata.us-east-1.amazonaws.com`。

### 为接口端点创建端点策略
<a name="vpc-endpoint-policy"></a>

端点策略是一种 IAM 资源，您可以将其附加到接口端点。默认终端节点策略允许 AWS AppConfig 通过接口终端节点进行完全访问。要控制允许 AWS AppConfig 从您的 VPC 访问权限，请将自定义终端节点策略附加到接口终端节点。

端点策略指定以下信息：
+ 可执行操作的主体（AWS 账户、IAM 用户和 IAM 角色）。
+ 可执行的操作。
+ 可对其执行操作的资源。

有关更多信息，请参阅《AWS PrivateLink 指南》**中的[使用端点策略控制对服务的访问权限](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-access.html)。

**示例：用于 AWS AppConfig 操作的 VPC 终端节点策略**  
以下是自定义端点策略的一个示例。将此策略附加到接口端点时，其会向所有资源上的所有主体授予对列出的 AWS AppConfig 操作的访问权限。

```
{
   "Statement": [
      {
         "Principal": "*",
         "Effect": "Allow",
         "Action": [
            "{{appconfig}}:{{CreateApplication}}",
            "{{appconfig}}:{{CreateEnvironment}}",
            "{{appconfig}}:{{CreateConfigurationProfile}}",
            "{{appconfig}}:{{StartDeployment}}",
            "{{appconfig}}:{{GetLatestConfiguration}}"
            "{{appconfig}}:{{StartConfigurationSession}}"
         ],
         "Resource":"*"
      }
   ]
}
```

## Secrets Manager 密钥轮换
<a name="appconfig-security-secrets-manager-key-rotation"></a>

本节介绍有关与 Secrets Manager AWS AppConfig 集成的重要安全信息。有关 Secrets Manager 的信息，请参阅[什么是 AWS Secrets Manager？](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) 在《*AWS Secrets Manager 用户指南》*中。

### 设置由部署的 Secrets Manager 密钥的自动轮换 AWS AppConfig
<a name="appconfig-security-secrets-manager-key-rotation-setting-up"></a>

*Rotation* 是定期更新存储在 Secrets Manager 中的密钥的过程。当轮换密钥时，会同时更新密钥和数据库或服务中的凭据。您可以使用更新密钥和数据库的 AWS Lambda 函数在 Secrets Manager 中配置自动轮换密钥。有关更多信息，请参阅 *AWS Secrets Manager 用户指南*中的[轮换 AWS Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html)。

要启用由部署的 Secrets Manager 密钥的密钥轮换 AWS AppConfig，请更新轮换 Lambda 函数并部署轮换后的密钥。

**注意**  
在您的密钥轮换并完全更新到新版本后，部署您的 AWS AppConfig 配置文件。您可以通过 `VersionStage` 的状态从 `AWSPENDING` 变为 `AWSCURRENT` 来确定密钥是否已轮换。密钥轮换完成发生在 Secrets Manager 轮换模板 `finish_secret` 函数中。

以下是一个在密钥轮换后启动 AWS AppConfig 部署的示例函数。

```
import time
import boto3
client = boto3.client('appconfig')

def finish_secret(service_client, arn, new_version):
    """Finish the rotation by marking the pending secret as current
    This method finishes the secret rotation by staging the secret staged AWSPENDING with the AWSCURRENT stage.
    Args:
        service_client (client): The secrets manager service client
        arn (string): The secret ARN or other identifier
        new_version (string): The new version to be associated with the secret
    """
    # First describe the secret to get the current version
    metadata = service_client.describe_secret(SecretId=arn)
    current_version = None
    for version in metadata["VersionIdsToStages"]:
        if "AWSCURRENT" in metadata["VersionIdsToStages"][version]:
            if version == new_version:
                # The correct version is already marked as current, return
                logger.info("finishSecret: Version %s already marked as AWSCURRENT for %s" % (version, arn))
                return
            current_version = version
            break

    # Finalize by staging the secret version current
    service_client.update_secret_version_stage(SecretId=arn, VersionStage="AWSCURRENT", MoveToVersionId=new_version, RemoveFromVersionId=current_version)
    
    # Deploy rotated secret
    response = client.start_deployment(
            ApplicationId='TestApp',
            EnvironmentId='TestEnvironment',
            DeploymentStrategyId='TestStrategy',
            ConfigurationProfileId='ConfigurationProfileId',
            ConfigurationVersion=new_version,
            KmsKeyIdentifier=key,
            Description='Deploy secret rotated at ' + str(time.time())
        )
   
    logger.info("finishSecret: Successfully set AWSCURRENT stage to version %s for secret %s." % (new_version, arn))
```