迁移到适用于 DynamoDB 的 Java 客户端加密库的版本 3.x - AWS 数据库加密 SDK

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

迁移到适用于 DynamoDB 的 Java 客户端加密库的版本 3.x

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

适用于 DynamoDB 的 Java 客户端加密库的版本 3.x 是对 2.x 代码库的重大改写。它包括许多更新,例如新的结构化数据格式、改进的多租户支持、无缝架构更改,以及可搜索的加密支持。本主题提供有关如何将代码迁移到版本 3.x 的指导。

从版本 1.x 迁移到 2.x

在迁移到版本 3.x 之前先迁移到版本 2.x。版本 2.x 已将最新提供程序的符号从 MostRecentProvider 更改为 CachingMostRecentProvider。如果您当前使用的是带有 MostRecentProvider 符号的适用于 DynamoDB 的 Java 客户端加密库的版本 1.x,必须将代码中的符号名称更新为 CachingMostRecentProvider。要了解更多信息,请参阅最新提供程序的更新

从版本 2.x 迁移到 3.x

以下步骤说明如何将您的代码从适用于 DynamoDB 的 Java 客户端加密库的版本 2.x 迁移到版本 3.x

第 1 步。准备读取新格式的项目

完成以下步骤,准备您的 AWS 数据库加密 SDK 客户端,以读取新格式的项目。部署以下更改后,您的客户端将继续以与版本 2.x 相同的行为方式运行。您的客户将继续读取和写入 2.x 格式中的项目,但是这些更改使客户端做好读取新格式项目的准备。

将你的版本更新 AWS SDK for Java 到 2.x 版

适用于 DynamoDB 的 Java 客户端加密库的版本 3.x 需要 DynamoDB 增强型客户端。DynamoDB 增强版客户端将取代先前版本中使用的 DynamoDBMapper。要使用增强型客户端,您必须使用 AWS SDK for Java 2.x。

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

有关需要哪些 AWS SDK for Java 2.x 模块的更多信息,请参阅先决条件

配置您的客户端,以读取由旧版本加密的项目

以下过程概述了以下代码示例中所演示的步骤。

  1. 创建一个密钥环

    密钥环和加密材料管理程序将取代以前版本的适用于 DynamoDB 的 Java 客户端加密库中使用的加密材料提供程序。

    重要

    您在创建密钥环时指定的包装密钥必须与版本 2.x 中用于加密材料提供程序的包装密钥相同。

  2. 创建一个带注释的类的表架构。

    此步骤用于定义开始以新格式编写项目时将使用的属性操作。

    有关使用全新 DynamoDB 增强版客户端的指南,请参阅《AWS SDK for Java 开发人员指南》中的生成一个 TableSchema

    以下示例假设您已使用新的属性操作注释从版本 2.x 中更新您的带注释类。有关为属性操作添加注释的更多指导,请参阅 使用带注释的数据类

    注意

    如果您指定了任何SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT属性,则分区和排序属性也必须是SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT。有关显示用于定义的注释的示例SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT,请参阅 SimpleClass4.java

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

  4. 配置在 2.x 版本建模类中配置的属性操作的显式映射。

    此步骤定义用于以旧格式编写项目的属性操作。

  5. 配置 DynamoDBEncryptor 您在适用于 DynamoDB 的 Java 客户端加密库的版本 2.x 中使用的 。

  6. 配置遗留行为。

  7. 创建 DynamoDbEncryptionInterceptor

  8. 创建一个新的 AWS SDK DynamoDB 客户端。

  9. 创建 DynamoDBEnhancedClient 并使用您的建模类创建表。

    要了解 DynamoDB 增强版客户端的更多信息,请参阅创建增强型客户端

public class MigrationExampleStep1 { public static void MigrationStep1(String kmsKeyId, String ddbTableName, int sortReadValue) { // 1. Create a Keyring. // This example creates an AWS KMS Keyring that specifies the // same kmsKeyId previously used in the version 2.x configuration. // It uses the 'CreateMrkMultiKeyring' method to create the // keyring, so that the keyring can correctly handle both single // region and Multi-Region KMS Keys. // Note that this example uses the AWS SDK for Java v2 KMS client. final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder() .generator(kmsKeyId) .build(); final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput); // 2. Create a Table Schema over your annotated class. // For guidance on using the new attribute actions // annotations, see SimpleClass.java in the // aws-database-encryption-sdk-dynamodb GitHub repository. // All primary key attributes must be signed but not encrypted // and by default all non-primary key attributes // are encrypted and signed (ENCRYPT_AND_SIGN). // If you want a particular non-primary key attribute to be signed but // not encrypted, use the 'DynamoDbEncryptionSignOnly' annotation. // If you want a particular attribute to be neither signed nor encrypted // (DO_NOTHING), use the 'DynamoDbEncryptionDoNothing' annotation. final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class); // 3. Define which attributes the client should expect to be excluded // from the signature when reading items. // This value represents all unsigned attributes across the entire // dataset. final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3"); // 4. Configure an explicit map of the attribute actions configured // in your version 2.x modeled class. final Map<String, CryptoAction> legacyActions = new HashMap<>(); legacyActions.put("partition_key", CryptoAction.SIGN_ONLY); legacyActions.put("sort_key", CryptoAction.SIGN_ONLY); legacyActions.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN); legacyActions.put("attribute2", CryptoAction.SIGN_ONLY); legacyActions.put("attribute3", CryptoAction.DO_NOTHING); // 5. Configure the DynamoDBEncryptor that you used in version 2.x. final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient(); final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kmsClient, kmsKeyId); final DynamoDBEncryptor oldEncryptor = DynamoDBEncryptor.getInstance(cmp); // 6. Configure the legacy behavior. // Input the DynamoDBEncryptor and attribute actions created in // the previous steps. For Legacy Policy, use // 'FORCE_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT'. This policy continues to read // and write items using the old format, but will be able to read // items written in the new format as soon as they appear. final LegacyOverride legacyOverride = LegacyOverride .builder() .encryptor(oldEncryptor) .policy(LegacyPolicy.FORCE_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT) .attributeActionsOnEncrypt(legacyActions) .build(); // 7. Create a DynamoDbEncryptionInterceptor with the above configuration. final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>(); tableConfigs.put(ddbTableName, DynamoDbEnhancedTableEncryptionConfig.builder() .logicalTableName(ddbTableName) .keyring(kmsKeyring) .allowedUnsignedAttributes(allowedUnsignedAttributes) .schemaOnEncrypt(tableSchema) .legacyOverride(legacyOverride) .build()); final DynamoDbEncryptionInterceptor interceptor = DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor( CreateDynamoDbEncryptionInterceptorInput.builder() .tableEncryptionConfigs(tableConfigs) .build() ); // 8. Create a new AWS SDK DynamoDb client using the // interceptor from Step 7. final DynamoDbClient ddb = DynamoDbClient.builder() .overrideConfiguration( ClientOverrideConfiguration.builder() .addExecutionInterceptor(interceptor) .build()) .build(); // 9. Create the DynamoDbEnhancedClient using the AWS SDK DynamoDb client // created in Step 8, and create a table with your modeled class. final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(ddb) .build(); final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema); } }

第 2 步。用新格式编写项目

将步骤 1 中的更改部署到所有读取器后,请完成以下步骤,将 AWS 数据库加密 SDK 客户端配置为以新格式写入项目。部署以下更改后,您的客户端将继续读取旧格式的项目,并且开始以新格式编写和读取项目。

以下过程概述了以下代码示例中所演示的步骤。

  1. 继续配置密钥环、表架构、旧属性操作 allowedUnsignedAttributesDynamoDBEncryptor,就像在步骤 1 中执行的操作一样。

  2. 将遗留行为更新为仅使用新格式编写新项目。

  3. 创建 DynamoDbEncryptionInterceptor

  4. 创建一个新的 AWS SDK DynamoDB 客户端。

  5. 创建 DynamoDBEnhancedClient 并使用您的建模类创建表。

    要了解 DynamoDB 增强版客户端的更多信息,请参阅创建增强型客户端

public class MigrationExampleStep2 { public static void MigrationStep2(String kmsKeyId, String ddbTableName, int sortReadValue) { // 1. Continue to configure your keyring, table schema, legacy // attribute actions, allowedUnsignedAttributes, and // DynamoDBEncryptor as you did in Step 1. final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder() .generator(kmsKeyId) .build(); final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput); final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class); final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3"); final Map<String, CryptoAction> legacyActions = new HashMap<>(); legacyActions.put("partition_key", CryptoAction.SIGN_ONLY); legacyActions.put("sort_key", CryptoAction.SIGN_ONLY); legacyActions.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN); legacyActions.put("attribute2", CryptoAction.SIGN_ONLY); legacyActions.put("attribute3", CryptoAction.DO_NOTHING); final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient(); final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kmsClient, kmsKeyId); final DynamoDBEncryptor oldEncryptor = DynamoDBEncryptor.getInstance(cmp); // 2. Update your legacy behavior to only write new items using the new // format. // For Legacy Policy, use 'FORBID_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT'. This policy // continues to read items in both formats, but will only write items // using the new format. final LegacyOverride legacyOverride = LegacyOverride .builder() .encryptor(oldEncryptor) .policy(LegacyPolicy.FORBID_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT) .attributeActionsOnEncrypt(legacyActions) .build(); // 3. Create a DynamoDbEncryptionInterceptor with the above configuration. final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>(); tableConfigs.put(ddbTableName, DynamoDbEnhancedTableEncryptionConfig.builder() .logicalTableName(ddbTableName) .keyring(kmsKeyring) .allowedUnsignedAttributes(allowedUnsignedAttributes) .schemaOnEncrypt(tableSchema) .legacyOverride(legacyOverride) .build()); final DynamoDbEncryptionInterceptor interceptor = DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor( CreateDynamoDbEncryptionInterceptorInput.builder() .tableEncryptionConfigs(tableConfigs) .build() ); // 4. Create a new AWS SDK DynamoDb client using the // interceptor from Step 3. final DynamoDbClient ddb = DynamoDbClient.builder() .overrideConfiguration( ClientOverrideConfiguration.builder() .addExecutionInterceptor(interceptor) .build()) .build(); // 5. Create the DynamoDbEnhancedClient using the AWS SDK DynamoDb Client created // in Step 4, and create a table with your modeled class. final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(ddb) .build(); final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema); } }

部署步骤 2 的更改后,必须使用新格式重新加密表中的所有旧项目,然后才能继续执行步骤 3。您无法运行单一指标或查询来快速加密您的现有项目。使用对您的系统最有意义的过程。例如,您可以使用异步过程,以缓慢扫描表,然后使用您定义的新属性操作和加密配置重写项目。

第 3 步。只能以新格式读取和编写项目

使用新格式重新加密表格中的所有项目后,您可以从配置中移除遗留行为。完成以下步骤以将客户端配置为仅以新格式读取和编写项目。

以下过程概述了以下代码示例中所演示的步骤。

  1. 继续配置密钥环、表架构和 allowedUnsignedAttributes,就像在步骤 1 中执行的操作一样。从您的配置中移除旧属性操作和 DynamoDBEncryptor

  2. 创建 DynamoDbEncryptionInterceptor

  3. 创建一个新的 AWS SDK DynamoDB 客户端。

  4. 创建 DynamoDBEnhancedClient 并使用您的建模类创建表。

    要了解 DynamoDB 增强版客户端的更多信息,请参阅创建增强型客户端

public class MigrationExampleStep3 { public static void MigrationStep3(String kmsKeyId, String ddbTableName, int sortReadValue) { // 1. Continue to configure your keyring, table schema, // and allowedUnsignedAttributes as you did in Step 1. // Do not include the configurations for the DynamoDBEncryptor or // the legacy attribute actions. final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder() .generator(kmsKeyId) .build(); final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput); final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class); final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3"); // 3. Create a DynamoDbEncryptionInterceptor with the above configuration. // Do not configure any legacy behavior. final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>(); tableConfigs.put(ddbTableName, DynamoDbEnhancedTableEncryptionConfig.builder() .logicalTableName(ddbTableName) .keyring(kmsKeyring) .allowedUnsignedAttributes(allowedUnsignedAttributes) .schemaOnEncrypt(tableSchema) .build()); final DynamoDbEncryptionInterceptor interceptor = DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor( CreateDynamoDbEncryptionInterceptorInput.builder() .tableEncryptionConfigs(tableConfigs) .build() ); // 4. Create a new AWS SDK DynamoDb client using the // interceptor from Step 3. final DynamoDbClient ddb = DynamoDbClient.builder() .overrideConfiguration( ClientOverrideConfiguration.builder() .addExecutionInterceptor(interceptor) .build()) .build(); // 5. Create the DynamoDbEnhancedClient using the AWS SDK Client // created in Step 4, and create a table with your modeled class. final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(ddb) .build(); final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema); } }