

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

# 将现有 DynamoDB 表配置为使用适用于 DynamoDB AWS 的数据库加密 SDK
<a name="ddb-java-config-existing-table"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

使用适用于 DynamoDB 的 Java 客户端加密库的 3.*x* 版本，您可以配置现有的 Amazon DynamoDB 表以进行客户端加密。本主题提供有关添加版本 3.*x* 到已填充的现有 DynamoDB 表要采取的三个步骤的指导。

**先决条件**  
适用于 DynamoDB 的 Java 客户端加密库中的版本 3.*x* 需要 AWS SDK for Java 2.x 中提供的 [DynamoDB 增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)。如果您仍在使用 [Dynamo DBMapper](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html)，则必须迁移 AWS SDK for Java 2.x 到才能使用 DynamoDB 增强型客户端。

 按照[从 适用于 Java 的 AWS SDK的版本 1.x 迁移到 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html) 的说明进行操作。

然后，按照说明[开始使用 DynamoDB 增强型客户端 API](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started.html)。

在将表配置为使用适用于 DynamoDB 的 Java 客户端加密库之前，您需要[使用带注释的数据类](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html#ddb-en-client-gs-tableschema-anno-bean)生成 `TableSchema`，并且需要[创建增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

## 步骤 1：准备读取和写入加密项目
<a name="ddb-java-add-step1"></a>

完成以下步骤，为 AWS 数据库加密 SDK 客户端做好读取和写入加密项目的准备。部署以下更改后，您的客户端将继续读取和写入明文项目。它不会对写入表中的任何新项目进行加密或签名，但却能够在加密项目显示后立即对其进行解密。这些更改使得客户端为开始[加密新项目](#ddb-java-add-step2)做好准备。在继续执行下一步操作之前，必须将以下更改部署到每一个读取器。

**1. 定义您的[属性操作](concepts.md#crypt-actions)**  
更新带注释的数据类以包含属性操作，这些操作定义哪些属性值将被加密和签名，哪些将仅被签名，哪些将被忽略。  
有关 DynamoDB 增强型客户端注释的更多指导，请参阅上 GitHub的 aws-database-encryption-sdk-dynamodb 存储库中的 [SimpleClass.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass.java)。  
默认情况下，主键属性已签名但未加密（`SIGN_ONLY`），而所有其他属性均经过加密和签名（`ENCRYPT_AND_SIGN`）。要指定例外情况，请使用在适用于 DynamoDB 的 Java 客户端加密库中定义的加密注释。例如，如果您只想对某个特定属性进行签名，请使用 `@DynamoDbEncryptionSignOnly` 注释。如果要对特定属性进行签名并将其包含在加密上下文中，请使用`@DynamoDbEncryptionSignAndIncludeInEncryptionContext`注释。如果对特定属性既不要签名也不要加密（`DO_NOTHING`），请使用 `@DynamoDbEncryptionDoNothing` 注释。  
如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。有关显示用于定义的注释的示例`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，请参阅 [SimpleClass4.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass4.java)。
有关注释的示例，请参阅 [使用带注释的数据类](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。

**2. 定义从签名中将可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端将假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**3. 创建[密钥环](keyrings.md)**  
以下示例创建一个 [AWS KMS 密钥环](use-kms-keyring.md)。 AWS KMS 密钥环使用对称加密或非对称 RSA AWS KMS keys 来生成、加密和解密数据密钥。  
该示例使用 `CreateMrkMultiKeyring` 创建带有对称加密 KMS 密钥的 AWS KMS 密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**4. 定义 DynamoDB 表的加密配置 **  
以下示例定义了一个 `tableConfigs` 映射，该映射表示此 DynamoDB 表的加密配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-java-using.md#logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  
必须指定 `FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT` 作为明文替代。此策略继续读取和写入明文项目，读取加密项目，并使客户端做好准备以写入加密项目。  

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .plaintextOverride(PlaintextOverride.FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```

**5. 创建 `DynamoDbEncryptionInterceptor`**  
以下示例使用**步骤 3** 中的 `tableConfigs` 创建 `DynamoDbEncryptionInterceptor`。  

```
DynamoDbEncryptionInterceptor interceptor = DynamoDbEncryptionInterceptor.builder()
        .config(DynamoDbTablesEncryptionConfig.builder()
                .tableEncryptionConfigs(tableConfigs)                
                .build())
        .build();
```

## 步骤 2：写入已加密和签名项目
<a name="ddb-java-add-step2"></a>

更新 `DynamoDbEncryptionInterceptor` 配置中的明文策略，以允许客户端写入已加密和签名的项目。部署好以下更改后，客户端将根据您在**步骤 1** 中配置的属性操作对新项目进行加密和签名。客户将能够读取明文项目以及已加密和签名的项目。

在继续执行[步骤 3](#ddb-java-add-step3) 之前，您必须对表格中所有现有的明文项目进行加密和签名。您无法运行单一指标或查询来快速加密您的现有明文项目。使用对您的系统最有意义的过程。例如，您可以使用异步过程，以缓慢扫描表，然后使用您定义的属性操作和加密配置重写项目。要识别表中的纯文本项目，我们建议您扫描所有不包含 AWS 数据库加密 SDK 在项目加密`aws_dbe_head`和签名时添加的和`aws_dbe_foot`属性的项目。

以下示例更新了**步骤 1** 中的表加密配置。您必须使用 `FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT` 更新明文替代。该策略继续读取明文项目，但也会读取和写入加密项目。`DynamoDbEncryptionInterceptor`使用更新的内容创建一个新的`tableConfigs`。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .plaintextOverride(PlaintextOverride.FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```

## 步骤 3：仅读取已加密和签名项目
<a name="ddb-java-add-step3"></a>

在对所有项目进行加密和签名后，请更新 `DynamoDbEncryptionInterceptor` 配置中的明文替代，以便仅允许客户端读取和写入已加密和签名的项目。部署好以下更改后，客户端将根据您在**步骤 1** 中配置的属性操作对新项目进行加密和签名。客户只能够读取已加密和签名的项目。

以下示例更新了**步骤 2** 中的表加密配置。您可以使用 `FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT` 更新明文替代，也可以从配置中移除明文策略。默认情况下，客户端仅读取和写入已加密和签名的项目。`DynamoDbEncryptionInterceptor`使用更新的内容创建一个新的`tableConfigs`。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        // Optional: you can also remove the plaintext policy from your configuration
        .plaintextOverride(PlaintextOverride.FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```