diff --git a/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/motica1/PocDemoAppUtils.java b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/motica1/PocDemoAppUtils.java new file mode 100644 index 000000000..3ced1f629 --- /dev/null +++ b/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/motica1/PocDemoAppUtils.java @@ -0,0 +1,170 @@ +package software.amazon.cryptography.examples.motica1; + +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; +import software.amazon.awssdk.enhanced.dynamodb.Key; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedRequest; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.kms.model.DataKeySpec; +import software.amazon.awssdk.services.kms.model.DecryptRequest; +import software.amazon.awssdk.services.kms.model.DecryptResponse; +import software.amazon.awssdk.services.kms.model.GenerateDataKeyRequest; +import software.amazon.awssdk.services.kms.model.GenerateDataKeyResponse; +import software.amazon.awssdk.utils.StringUtils; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.DynamoDbEncryptionInterceptor; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.enhancedclient.CreateDynamoDbEncryptionInterceptorInput; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.enhancedclient.DynamoDbEnhancedClientEncryption; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.enhancedclient.DynamoDbEnhancedTableEncryptionConfig; +import software.amazon.cryptography.examples.enhanced.SimpleClass; +import software.amazon.cryptography.materialproviders.IKeyring; +import software.amazon.cryptography.materialproviders.MaterialProviders; +import software.amazon.cryptography.materialproviders.model.CreateAwsKmsMrkMultiKeyringInput; +import software.amazon.cryptography.materialproviders.model.DBEAlgorithmSuiteId; +import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig; + +import java.util.*; + +public class PocDemoAppUtils { + static final TableSchema tableSchema = + TableSchema.fromBean(SimpleClass .class); + static final String unsignAttrPrefix = ":"; + + // @motica1 An Alias cannot be used for Decryption +// private static String cmkAlias = "arn:aws:kms:us-east-1:<>:alias/pii-service-sse-key"; +// private static String cmkArn = "arn:aws:kms:us-east-1:<>:alias/pii-service-sse-key"; + + + /** + * @param kmsId The arn of a KMS Symmetric Key or (encrypt only) an alias to a KMS Symmetric Key + */ + private static IKeyring getKeyring(final String kmsId) { + // 1. Create a Keyring. This Keyring will be responsible for protecting the data keys that + // protect your data. + // For this example, we will create a AWS KMS Keyring with the AWS KMS Key we want to use. + // We will use the `CreateMrkMultiKeyring` method to create this keyring, + // as it will correctly handle both single region and Multi-Region KMS Keys. + final MaterialProviders matProv = + MaterialProviders.builder() + .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) + .build(); + final CreateAwsKmsMrkMultiKeyringInput keyringInput = + CreateAwsKmsMrkMultiKeyringInput.builder().generator(kmsId).build(); + return matProv.CreateAwsKmsMrkMultiKeyring(keyringInput); + } + + /** + * @param kmsIds The arns of KMS Symmetric Keys or (encrypt only) aliases to KMS Symmetric Keys. + * The first entry will be used as the generator. + */ + private static IKeyring getMultiKeyring(final String ... kmsIds) { + // 1. Create a Keyring. This Keyring will be responsible for protecting the data keys that + // protect your data. + // For this example, we will create a AWS KMS Keyring with the AWS KMS Key we want to use. + // We will use the `CreateMrkMultiKeyring` method to create this keyring, + // as it will correctly handle both single region and Multi-Region KMS Keys. + final MaterialProviders matProv = + MaterialProviders.builder() + .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) + .build(); + final String generatorArn = kmsIds[0]; + final List nonGeneratorArns = Arrays.asList(Arrays.copyOfRange(kmsIds, 1, kmsIds.length)); + final CreateAwsKmsMrkMultiKeyringInput.Builder keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder().generator(generatorArn); + if (nonGeneratorArns.size() > 0) { + keyringInput.kmsKeyIds(nonGeneratorArns); + } + return matProv.CreateAwsKmsMrkMultiKeyring(keyringInput.build()); + } + + public static void encryptNew( + final String kmsId, + final String kmsAlias, + final String tableName) { + + IKeyring keyring = getKeyring(kmsAlias); + final DynamoDbEnhancedClient encryptEnhancedClient = getDynamoDbEnhancedClient(keyring, tableName); + DynamoDbTable table = + encryptEnhancedClient.table(tableName, tableSchema); + + final SimpleClass bean = new SimpleClass(); + bean.setPartitionKey("motica1"); + bean.setSortKey(0); + + System.out.println("------"); + System.out.println(bean); + System.out.println("------"); + + table.putItem(bean); + experiment(kmsId, kmsAlias); + + IKeyring decryptKeyring = StringUtils.equals(kmsAlias, kmsId) ? keyring : getMultiKeyring(kmsAlias, kmsId); + final DynamoDbEnhancedClient enhancedClient = getDynamoDbEnhancedClient(decryptKeyring, tableName); + table = enhancedClient.table(tableName, tableSchema); + final Key key = Key.builder().partitionValue("motica1").sortValue(0).build(); + final SimpleClass result = + table.getItem((GetItemEnhancedRequest.Builder requestBuilder) -> requestBuilder.key(key)); + System.out.println(result); + } + + private static DynamoDbEnhancedClient getDynamoDbEnhancedClient(IKeyring keyring, String tableName) { + Map encryptTableConfigs = new HashMap<>(); + encryptTableConfigs.put( + tableName, + DynamoDbEnhancedTableEncryptionConfig.builder() + .logicalTableName(tableName) + .keyring(keyring) + .allowedUnsignedAttributePrefix(unsignAttrPrefix) + .schemaOnEncrypt(tableSchema) + .algorithmSuiteId( + DBEAlgorithmSuiteId + .ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384_SYMSIG_HMAC_SHA384) + .build()); + final DynamoDbEncryptionInterceptor encryptionInterceptor = + DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor( + CreateDynamoDbEncryptionInterceptorInput.builder() + .tableEncryptionConfigs(encryptTableConfigs) + .build()); + + final DynamoDbClient ddb = + DynamoDbClient.builder() + .region(Region.US_WEST_2) + .overrideConfiguration( + ClientOverrideConfiguration.builder() + .addExecutionInterceptor(encryptionInterceptor) + .build()) + .build(); + + return DynamoDbEnhancedClient.builder().dynamoDbClient(ddb).build(); + } + + private static void experiment( + final String kmsId, + final String kmsAlias + ) { + System.out.println("Running Experiment"); + System.out.println("------"); + + KmsClient kms = KmsClient.builder().region(Region.US_WEST_2).build(); + GenerateDataKeyResponse response = + kms.generateDataKey( + GenerateDataKeyRequest.builder().keyId(kmsAlias).keySpec(DataKeySpec.AES_256).build()); + System.out.println("response.keyId = " + response.keyId()); + System.out.println("------"); + System.out.printf( + "Is Response KeyId the same as Request? %s%n", + StringUtils.equals(kmsAlias, response.keyId()) + ); + + DecryptResponse decryptResponse = + kms.decrypt(DecryptRequest.builder().ciphertextBlob(response.ciphertextBlob()).keyId(kmsId).build()); + System.out.println("decryptResponse.keyId = " + decryptResponse.keyId()); + System.out.printf( + "Is Response KeyId the same as Request? %s%n", + StringUtils.equals(kmsId, response.keyId()) + ); + System.out.println("------"); + } +} diff --git a/Examples/runtimes/java/DynamoDbEncryption/src/test/java/software/amazon/cryptography/examples/TestUtils.java b/Examples/runtimes/java/DynamoDbEncryption/src/test/java/software/amazon/cryptography/examples/TestUtils.java index ce9adb2b2..75030b619 100644 --- a/Examples/runtimes/java/DynamoDbEncryption/src/test/java/software/amazon/cryptography/examples/TestUtils.java +++ b/Examples/runtimes/java/DynamoDbEncryption/src/test/java/software/amazon/cryptography/examples/TestUtils.java @@ -10,6 +10,7 @@ public class TestUtils { // These are public KMS Keys that MUST only be used for testing, and MUST NOT be used for any production data public static final String TEST_KMS_KEY_ID = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"; public static final String TEST_MRK_KEY_ID = "arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7"; + public static final String TEST_MRK_ALIAS_ID = "arn:aws:kms:us-west-2:658956600833:alias/multi-region-us-west-2"; public static final String TEST_KMS_RSA_KEY_ID = "arn:aws:kms:us-west-2:658956600833:key/8b432da4-dde4-4bc3-a794-c7d68cbab5a6"; public static final String TEST_MRK_REPLICA_KEY_ID_US_EAST_1 = "arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7"; public static final String TEST_MRK_REPLICA_KEY_ID_EU_WEST_1 = "arn:aws:kms:eu-west-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7"; diff --git a/Examples/runtimes/java/DynamoDbEncryption/src/test/java/software/amazon/cryptography/examples/motica1/TestPocDemoAppUtils.java b/Examples/runtimes/java/DynamoDbEncryption/src/test/java/software/amazon/cryptography/examples/motica1/TestPocDemoAppUtils.java new file mode 100644 index 000000000..49799d4d9 --- /dev/null +++ b/Examples/runtimes/java/DynamoDbEncryption/src/test/java/software/amazon/cryptography/examples/motica1/TestPocDemoAppUtils.java @@ -0,0 +1,16 @@ +package software.amazon.cryptography.examples.motica1; + +import org.testng.annotations.Test; +import software.amazon.cryptography.examples.TestUtils; + +public class TestPocDemoAppUtils { + @Test + public void TestEncryptNewValid() { + PocDemoAppUtils.encryptNew(TestUtils.TEST_MRK_KEY_ID, TestUtils.TEST_MRK_ALIAS_ID, TestUtils.TEST_DDB_TABLE_NAME); + } + + @Test(expectedExceptions = software.amazon.awssdk.core.exception.SdkClientException.class) + public void TestEncryptNewInValid() { + PocDemoAppUtils.encryptNew(TestUtils.TEST_MRK_ALIAS_ID, TestUtils.TEST_MRK_ALIAS_ID, TestUtils.TEST_DDB_TABLE_NAME); + } +}