diff --git a/codebuild/corretto11.yml b/codebuild/corretto11.yml index 6c394676..ca0781bc 100644 --- a/codebuild/corretto11.yml +++ b/codebuild/corretto11.yml @@ -6,4 +6,4 @@ phases: java: corretto11 build: commands: - - mvn install + - mvn install --no-transfer-progress diff --git a/codebuild/corretto8.yml b/codebuild/corretto8.yml index 3c14db6e..3114bc7e 100644 --- a/codebuild/corretto8.yml +++ b/codebuild/corretto8.yml @@ -6,4 +6,4 @@ phases: java: corretto8 build: commands: - - mvn install + - mvn install --no-transfer-progress diff --git a/codebuild/openjdk11.yml b/codebuild/openjdk11.yml index 9e184d25..04317a17 100644 --- a/codebuild/openjdk11.yml +++ b/codebuild/openjdk11.yml @@ -6,4 +6,4 @@ phases: java: openjdk11 build: commands: - - mvn install + - mvn install --no-transfer-progress diff --git a/codebuild/openjdk8.yml b/codebuild/openjdk8.yml index 2157de50..c2ee268b 100644 --- a/codebuild/openjdk8.yml +++ b/codebuild/openjdk8.yml @@ -6,4 +6,4 @@ phases: java: openjdk8 build: commands: - - mvn install + - mvn install --no-transfer-progress diff --git a/codebuild/release/release-prod.yml b/codebuild/release/release-prod.yml index bc25225b..2459c20d 100644 --- a/codebuild/release/release-prod.yml +++ b/codebuild/release/release-prod.yml @@ -41,7 +41,8 @@ phases: -Dgpg.passphrase="$GPG_PASS" \ -Dsonatype.username="$SONA_USERNAME" \ -Dsonatype.password="$SONA_PASSWORD" \ - -s $SETTINGS_FILE + -s $SETTINGS_FILE \ + --no-transfer-progress batch: diff --git a/codebuild/release/release-staging.yml b/codebuild/release/release-staging.yml index be1f68e2..ccfcee64 100644 --- a/codebuild/release/release-staging.yml +++ b/codebuild/release/release-staging.yml @@ -47,7 +47,8 @@ phases: -Dgpg.passphrase="$GPG_PASS" \ -Dcodeartifact.token=$CODEARTIFACT_TOKEN \ -DaltDeploymentRepository=codeartifact::default::$CODEARTIFACT_REPO_URL \ - -s $SETTINGS_FILE + -s $SETTINGS_FILE \ + --no-transfer-progress batch: fast-fail: false diff --git a/codebuild/release/validate-prod.yml b/codebuild/release/validate-prod.yml index b43a2638..a1bfaa91 100644 --- a/codebuild/release/validate-prod.yml +++ b/codebuild/release/validate-prod.yml @@ -15,4 +15,5 @@ phases: -Dcheckstyle.skip \ -Dddbec.version=$VERSION \ -Dmaven.compiler.target=$JAVA_NUMERIC_VERSION \ - -Dmaven.compiler.source=$JAVA_NUMERIC_VERSION + -Dmaven.compiler.source=$JAVA_NUMERIC_VERSION \ + --no-transfer-progress diff --git a/codebuild/release/validate-staging.yml b/codebuild/release/validate-staging.yml index f967acf5..001c8cbc 100644 --- a/codebuild/release/validate-staging.yml +++ b/codebuild/release/validate-staging.yml @@ -32,4 +32,5 @@ phases: -Dmaven.compiler.source=$JAVA_NUMERIC_VERSION \ -Dcodeartifact.token=$CODEARTIFACT_TOKEN \ -Dcodeartifact.url=$CODEARTIFACT_REPO_URL \ - -s $SETTINGS_FILE + -s $SETTINGS_FILE \ + --no-transfer-progress diff --git a/codebuild/static-analysis.yml b/codebuild/static-analysis.yml index 3c3b2f38..6a94423d 100644 --- a/codebuild/static-analysis.yml +++ b/codebuild/static-analysis.yml @@ -6,4 +6,4 @@ phases: java: corretto11 build: commands: - - mvn com.coveo:fmt-maven-plugin:check + - mvn com.coveo:fmt-maven-plugin:check --no-transfer-progress diff --git a/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedGlobal2017Object.java b/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedGlobal2017Object.java new file mode 100644 index 00000000..28c5edae --- /dev/null +++ b/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedGlobal2017Object.java @@ -0,0 +1,124 @@ +/* + * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.amazonaws.examples; + +import com.amazonaws.services.dynamodbv2.datamodeling.AttributeEncryptor; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIgnore; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DoNotTouch; + +/** + * This demonstrates how to use the {@link DynamoDBMapper} with the {@link AttributeEncryptor} to + * encrypt your data. Before you can use this you need to set up a DynamoDB table called + * "ExampleTable" to hold the encrypted data. "ExampleTable" should have a partition key named + * "partition_attribute" for Strings and a sort (range) key named "sort_attribute" for numbers. + */ +public class AwsKmsEncryptedGlobal2017Object { + public static final String EXAMPLE_TABLE_NAME = "ExampleTable"; + public static final String PARTITION_ATTRIBUTE = "partition_attribute"; + public static final String SORT_ATTRIBUTE = "sort_attribute"; + + private static final String AWS_DYNAMODB_REPLICATION_DELETING_ATTRIBUTE = "aws:rep:deleting"; + private static final String AWS_DYNAMODB_REPLICATION_UPDATETIME_ATTRIBUTE = "aws:rep:updatetime"; + private static final String AWS_DYNAMODB_REPLICATION_UPDATEREGION_ATTRIBUTE = + "aws:rep:updateregion"; + + private static final String STRING_FIELD_NAME = "example"; + + @DynamoDBTable(tableName = EXAMPLE_TABLE_NAME) + public static final class DataPoJo { + private String partitionAttribute; + private int sortAttribute; + private String example; + private boolean aws_dynamodb_replication_deleting; + private float aws_dynamodb_replication_updatetime; + private String aws_dynamodb_replication_updateregion; + + @DynamoDBHashKey(attributeName = PARTITION_ATTRIBUTE) + public String getPartitionAttribute() { + return partitionAttribute; + } + + public void setPartitionAttribute(String partitionAttribute) { + this.partitionAttribute = partitionAttribute; + } + + @DynamoDBRangeKey(attributeName = SORT_ATTRIBUTE) + public int getSortAttribute() { + return sortAttribute; + } + + public void setSortAttribute(int sortAttribute) { + this.sortAttribute = sortAttribute; + } + + @DynamoDBAttribute(attributeName = STRING_FIELD_NAME) + public String getExample() { + return example; + } + + public void setExample(String example) { + this.example = example; + } + + @DynamoDBAttribute(attributeName = AWS_DYNAMODB_REPLICATION_DELETING_ATTRIBUTE) + @DynamoDBIgnore + @DoNotTouch + public boolean getAws_dynamodb_replication_deleting() { + return aws_dynamodb_replication_deleting; + } + + public void setAws_dynamodb_replication_deleting(boolean deleting) { + this.aws_dynamodb_replication_deleting = deleting; + } + + @DynamoDBAttribute(attributeName = AWS_DYNAMODB_REPLICATION_UPDATETIME_ATTRIBUTE) + @DynamoDBIgnore + @DoNotTouch + public float getAws_dynamodb_replication_updatetime() { + return aws_dynamodb_replication_updatetime; + } + + public void setAws_dynamodb_replication_updatetime(float updatetime) { + this.aws_dynamodb_replication_updatetime = updatetime; + } + + @DynamoDBAttribute(attributeName = AWS_DYNAMODB_REPLICATION_UPDATEREGION_ATTRIBUTE) + @DynamoDBIgnore + @DoNotTouch + public String getAws_dynamodb_replication_updateregion() { + return aws_dynamodb_replication_updateregion; + } + + public void setAws_dynamodb_replication_updateregion(String updateregion) { + this.aws_dynamodb_replication_updateregion = updateregion; + } + + @Override + public String toString() { + return "DataPoJo [partitionAttribute=" + + partitionAttribute + + ", sortAttribute=" + + sortAttribute + + ", example=" + + example + + "]"; + } + } +} diff --git a/examples/src/main/java/com/amazonaws/examples/AwsKmsMultiRegionKey.java b/examples/src/main/java/com/amazonaws/examples/AwsKmsMultiRegionKey.java index b9173a69..57a0cdeb 100644 --- a/examples/src/main/java/com/amazonaws/examples/AwsKmsMultiRegionKey.java +++ b/examples/src/main/java/com/amazonaws/examples/AwsKmsMultiRegionKey.java @@ -39,6 +39,7 @@ public static void encryptRecord( AWSKMS kmsEncrypt = null; AmazonDynamoDB ddbEncrypt = null; AmazonDynamoDB ddbDecrypt = null; + //noinspection DuplicatedCode try { // Sample object to be encrypted AwsKmsEncryptedObject.DataPoJo record = new AwsKmsEncryptedObject.DataPoJo(); @@ -52,6 +53,7 @@ public static void encryptRecord( // Set up clients and configuration in the first region. All of this is thread-safe and can be // reused // across calls + @SuppressWarnings("DuplicatedCode") final String encryptRegion = cmkArnEncrypt.split(":")[3]; kmsEncrypt = AWSKMSClientBuilder.standard().withRegion(encryptRegion).build(); ddbEncrypt = AmazonDynamoDBClientBuilder.standard().withRegion(encryptRegion).build(); @@ -79,7 +81,7 @@ public static void encryptRecord( // to the second region try { Thread.sleep(1000); - } catch (InterruptedException e) { + } catch (InterruptedException ignored) { } // Set up clients and configuration in the second region diff --git a/examples/src/main/java/com/amazonaws/examples/AwsKmsMultiRegionKeyGlobal2017.java b/examples/src/main/java/com/amazonaws/examples/AwsKmsMultiRegionKeyGlobal2017.java new file mode 100644 index 00000000..ec63e83f --- /dev/null +++ b/examples/src/main/java/com/amazonaws/examples/AwsKmsMultiRegionKeyGlobal2017.java @@ -0,0 +1,134 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package com.amazonaws.examples; + +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; +import com.amazonaws.services.dynamodbv2.datamodeling.AttributeEncryptor; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.TableNameOverride; +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DynamoDBEncryptor; +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.DirectKmsMaterialProvider; +import com.amazonaws.services.kms.AWSKMS; +import com.amazonaws.services.kms.AWSKMSClientBuilder; +import java.security.GeneralSecurityException; +import java.util.Random; + +/** + * Example showing use of AWS KMS CMP with an AWS KMS Multi-Region Key. We encrypt a record with a + * key in one region, then decrypt the ciphertext with the same key replicated to another region. + * + *

This example assumes that you have a DDB Global Table replicated to two regions, and an AWS + * KMS Multi-Region Key replicated to the same regions. + */ +public class AwsKmsMultiRegionKeyGlobal2017 { + + public static void main(String[] args) throws GeneralSecurityException { + final String tableName = args[0]; + final String cmkArn1 = args[1]; + final String cmkArn2 = args[2]; + + encryptAndDecrypt(tableName, cmkArn1, cmkArn2); + } + + public static void encryptAndDecrypt( + final String tableName, final String cmkArnEncrypt, final String cmkArnDecrypt) + throws GeneralSecurityException { + AWSKMS kmsDecrypt = null; + AWSKMS kmsEncrypt = null; + AmazonDynamoDB ddbEncrypt = null; + AmazonDynamoDB ddbDecrypt = null; + //noinspection DuplicatedCode + try { + Random random = new Random(); + int sort_value = random.nextInt(); + // Sample object to be encrypted + AwsKmsEncryptedGlobal2017Object.DataPoJo record = + new AwsKmsEncryptedGlobal2017Object.DataPoJo(); + record.setPartitionAttribute("is this"); + record.setSortAttribute(sort_value); + record.setExample("data"); + + // Set up clients and configuration in the first region. All of this is thread-safe and can be + // reused + // across calls + final String encryptRegion = cmkArnEncrypt.split(":")[3]; + kmsEncrypt = AWSKMSClientBuilder.standard().withRegion(encryptRegion).build(); + ddbEncrypt = AmazonDynamoDBClientBuilder.standard().withRegion(encryptRegion).build(); + final DirectKmsMaterialProvider cmpEncrypt = + new DirectKmsMaterialProvider(kmsEncrypt, cmkArnEncrypt); + final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmpEncrypt); + + // Mapper Creation + // Please note the use of SaveBehavior.PUT (SaveBehavior.CLOBBER works as well). + // Omitting this can result in data-corruption. + DynamoDBMapperConfig mapperConfig = + DynamoDBMapperConfig.builder() + .withSaveBehavior(DynamoDBMapperConfig.SaveBehavior.PUT) + .withTableNameOverride(TableNameOverride.withTableNameReplacement(tableName)) + .build(); + DynamoDBMapper encryptMapper = + new DynamoDBMapper(ddbEncrypt, mapperConfig, new AttributeEncryptor(encryptor)); + + System.out.println("Global 2017 Plaintext Record: " + record); + // Save the item to the DynamoDB table + encryptMapper.save(record); + + // DDB Global Table replication takes some time. Sleep for a moment to give the item a chance + // to replicate + // to the second region + try { + Thread.sleep(5000); + } catch (InterruptedException ignored) { + } + + // Set up clients and configuration in the second region + final String decryptRegion = cmkArnDecrypt.split(":")[3]; + kmsDecrypt = AWSKMSClientBuilder.standard().withRegion(decryptRegion).build(); + ddbDecrypt = AmazonDynamoDBClientBuilder.standard().withRegion(decryptRegion).build(); + final DirectKmsMaterialProvider cmpDecrypt = + new DirectKmsMaterialProvider(kmsDecrypt, cmkArnDecrypt); + final DynamoDBEncryptor decryptor = DynamoDBEncryptor.getInstance(cmpDecrypt); + + DynamoDBMapper decryptMapper = + new DynamoDBMapper(ddbDecrypt, mapperConfig, new AttributeEncryptor(decryptor)); + + // Retrieve (and decrypt) it in the second region. This allows you to avoid a cross-region KMS + // call to the + // first region if your application is running in the second region + AwsKmsEncryptedGlobal2017Object.DataPoJo decryptedRecord = + decryptMapper.load(AwsKmsEncryptedGlobal2017Object.DataPoJo.class, "is this", sort_value); + System.out.println("Global 2017 Decrypted Record: " + decryptedRecord); + + // The decrypted fields match the original fields before encryption + assert record.getExample().equals(decryptedRecord.getExample()); + + decryptedRecord.setExample("Howdy"); + encryptMapper.save(decryptedRecord); + try { + Thread.sleep(5000); + } catch (InterruptedException ignored) { + } + AwsKmsEncryptedGlobal2017Object.DataPoJo decryptedRecordTwo = + decryptMapper.load(AwsKmsEncryptedGlobal2017Object.DataPoJo.class, "is this", sort_value); + System.out.println("Global 2017 Decrypted Record: " + decryptedRecord); + assert decryptedRecordTwo.getExample().equals(decryptedRecord.getExample()); + + encryptMapper.delete(decryptedRecordTwo); + } finally { + if (kmsDecrypt != null) { + kmsDecrypt.shutdown(); + } + if (kmsEncrypt != null) { + kmsEncrypt.shutdown(); + } + if (ddbEncrypt != null) { + ddbEncrypt.shutdown(); + } + if (ddbDecrypt != null) { + ddbDecrypt.shutdown(); + } + } + } +} diff --git a/examples/src/test/java/com/amazonaws/examples/AwsKmsMultiRegionKeyGlobal2017IT.java b/examples/src/test/java/com/amazonaws/examples/AwsKmsMultiRegionKeyGlobal2017IT.java new file mode 100644 index 00000000..9b4c3677 --- /dev/null +++ b/examples/src/test/java/com/amazonaws/examples/AwsKmsMultiRegionKeyGlobal2017IT.java @@ -0,0 +1,20 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.examples; + +import static com.amazonaws.examples.TestUtils.US_EAST_1_MRK_KEY_ID; +import static com.amazonaws.examples.TestUtils.US_WEST_2_MRK_KEY_ID; + +import java.security.GeneralSecurityException; +import org.testng.annotations.Test; + +public class AwsKmsMultiRegionKeyGlobal2017IT { + private static final String TABLE_NAME = "tonyknap-manual-mrk-global-2017"; + + @Test + public void testEncryptAndDecrypt() throws GeneralSecurityException { + AwsKmsMultiRegionKeyGlobal2017.encryptAndDecrypt( + TABLE_NAME, US_EAST_1_MRK_KEY_ID, US_WEST_2_MRK_KEY_ID); + } +}