将现有 DynamoDB 表配置为使用适用于 DynamoDB AWS 的数据库加密 SDK - AWS 数据库加密 SDK

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

将现有 DynamoDB 表配置为使用适用于 DynamoDB AWS 的数据库加密 SDK

我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 DynamoDB 加密客户端的信息。

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

先决条件

适用于 DynamoDB 的 Java 客户端加密库中的版本 3.x 需要 AWS SDK for Java 2.x 中提供的 DynamoDB 增强型客户端。如果您仍在使用 DynamoDBMapper,则必须迁移到 AWS SDK for Java 2.x 才能使用 DynamoDB 增强型客户端。

按照从 AWS SDK for Java的版本 1.x 迁移到 2.x 的说明进行操作。

然后,按照说明开始使用 DynamoDB 增强型客户端 API

在将表配置为使用适用于 DynamoDB 的 Java 客户端加密库之前,您需要使用带注释的数据类生成 TableSchema,并且需要创建增强型客户端

步骤 1:准备读取和写入加密项目

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

1. 定义您的属性操作

更新带注释的数据类以包含属性操作,这些操作定义哪些属性值将被加密和签名,哪些将仅被签名,哪些将被忽略。

有关 DynamoDB 增强型客户端注释的更多指导,请参阅 aws-database-encryption-sdk-dynamodb 存储库中的 SimpleClass.java。 GitHub

默认情况下,主键属性已签名但未加密(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

有关注释的示例,请参阅 使用带注释的数据类

2. 定义从签名中将可以排除哪些属性

以下示例假设所有 DO_NOTHING 属性共享不同的前缀“:”,并使用该前缀定义允许的未签名属性。客户端将假设任何带有“:”前缀的属性名称都被排除在签名之外。有关更多信息,请参阅 允许的未签名属性

final String unsignedAttrPrefix = ":";
3. 创建密钥环

以下示例创建一个 AWS KMS 密钥环。 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 表名称指定为逻辑表名称。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息,请参阅 适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置

必须指定 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:写入已加密和签名项目

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

在继续执行步骤 3 之前,您必须对表格中所有现有的明文项目进行加密和签名。您无法运行单一指标或查询来快速加密您的现有明文项目。使用对您的系统最有意义的过程。例如,您可以使用异步过程,以缓慢扫描表,然后使用您定义的属性操作和加密配置重写项目。要识别表中的纯文本项目,我们建议您扫描所有不包含 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:仅读取已加密和签名项目

在对所有项目进行加密和签名后,请更新 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);