diff --git a/pom.xml b/pom.xml index 383b65c07..a9c6935c8 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,14 @@ UTF-8 + + + + + + + + diff --git a/src/examples/java/com/amazonaws/crypto/examples/v2/RestrictRegionExample.java b/src/examples/java/com/amazonaws/crypto/examples/v2/RestrictRegionExample.java index 900fcd939..8bc489056 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/v2/RestrictRegionExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/v2/RestrictRegionExample.java @@ -15,6 +15,7 @@ import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.CommitmentPolicy; import com.amazonaws.encryptionsdk.kms.DiscoveryFilter; +import com.amazonaws.encryptionsdk.kmssdkv2.RegionalClientSupplier; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.kms.KmsClient; @@ -48,6 +49,8 @@ public static void main(final String[] args) { encryptAndDecrypt(keyName, partition, accountId, region); } + + static void encryptAndDecrypt(final String keyName, final String partition, final String accountId, final Region region) { // Instantiate the SDK. // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy, @@ -101,15 +104,7 @@ static void encryptAndDecrypt(final String keyName, final String partition, fina // This example also configures the AWS KMS master key provider with a Discovery Filter to limit // the attempted AWS KMS CMKs to a particular partition and account. final KmsMasterKeyProvider decryptingKeyProvider = KmsMasterKeyProvider.builder() - .customRegionalClientSupplier(cmkRegion -> { - if(cmkRegion.equals(region)) { - // return the previously built AWS KMS client so that we do - // not create a new client on every decrypt call. - return kmsClient; - } - - throw new AwsCryptoException("Only " + region.id() + " is supported"); - }) + .customRegionalClientSupplier(new ARegionalClientSupplier(region, kmsClient)) .buildDiscovery(discoveryFilter); // 8. Decrypt the data @@ -127,4 +122,30 @@ static void encryptAndDecrypt(final String keyName, final String partition, fina // 10. Verify that the decrypted plaintext matches the original plaintext assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA); } + + + /** + * This class is Thread Safe, as both of its members are thread safe. + * KMS Client Builders are NOT thread safe, and can lead to unexpected behavior if concurrently used. + */ + private static class ARegionalClientSupplier implements RegionalClientSupplier { + private final Region region; + private final KmsClient kmsClient; + + public ARegionalClientSupplier(Region region, KmsClient kmsClient) { + this.region = region; + this.kmsClient = kmsClient; + } + + @Override + public KmsClient getClient(Region cmkRegion) { + if (cmkRegion.equals(region)) { + // return the previously built AWS KMS client so that we do + // not create a new client on every decrypt call. + return kmsClient; + } + + throw new AwsCryptoException("Only " + region.id() + " is supported"); + } + } } diff --git a/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java b/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java index e502e5b16..823ec2a9d 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java +++ b/src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java @@ -172,6 +172,10 @@ public AwsKmsMrkAwareMasterKeyProvider.Builder withCredentials(AWSCredentials cr *

This method will overwrite any credentials set using {@link * #withCredentials(AWSCredentialsProvider)}. * + *

WARNING: {@link AWSKMSClientBuilder}s are NOT thread safe. If {@link KmsMasterKeyProvider} + * is going to be used concurrently, a proper supplier MUST be provided, or use a {@link + * #withCustomClientFactory(KmsMasterKeyProvider.RegionalClientSupplier)} + * * @see KmsMasterKeyProvider.Builder#withClientBuilder(AWSKMSClientBuilder) */ public AwsKmsMrkAwareMasterKeyProvider.Builder withClientBuilder(AWSKMSClientBuilder builder) { diff --git a/src/main/java/com/amazonaws/encryptionsdk/kms/KmsMasterKeyProvider.java b/src/main/java/com/amazonaws/encryptionsdk/kms/KmsMasterKeyProvider.java index 10aa8f985..bbc420e06 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/kms/KmsMasterKeyProvider.java +++ b/src/main/java/com/amazonaws/encryptionsdk/kms/KmsMasterKeyProvider.java @@ -173,6 +173,10 @@ public Builder withCredentials(AWSCredentials credentials) { *

This method will overwrite any credentials set using {@link * #withCredentials(AWSCredentialsProvider)}. * + *

WARNING: {@link AWSKMSClientBuilder}s are NOT thread safe. If {@link KmsMasterKeyProvider} + * is going to be used concurrently, a proper supplier MUST be provided, or use a {@link + * #withCustomClientFactory(KmsMasterKeyProvider.RegionalClientSupplier)} + * * @param builder * @return */ diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java index 0fcbef2e9..39b015344 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java @@ -131,6 +131,10 @@ public Builder customRegionalClientSupplier(RegionalClientSupplier regionalClien *

Note: The AWS Encryption SDK for Java does not support the {@code KmsAsyncClient} * interface. * + *

WARNING: {@link KmsClientBuilder}s are NOT thread safe. If {@link KmsMasterKeyProvider} is + * going to be used concurrently, a proper supplier MUST be provided, or use a {@link + * #customRegionalClientSupplier(RegionalClientSupplier)} + * * @see KmsMasterKeyProvider.Builder#builderSupplier(Supplier) */ public Builder builderSupplier(Supplier supplier) { diff --git a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProvider.java b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProvider.java index 50923113e..10c662811 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProvider.java +++ b/src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/KmsMasterKeyProvider.java @@ -116,6 +116,10 @@ public Builder customRegionalClientSupplier(RegionalClientSupplier regionalClien *

Note: The AWS Encryption SDK for Java does not support the {@code KmsAsyncClient} * interface. * + *

WARNING: {@link KmsClientBuilder}s are NOT thread safe. If {@link KmsMasterKeyProvider} is + * going to be used concurrently, a proper supplier MUST be provided, or use a {@link + * #customRegionalClientSupplier(RegionalClientSupplier)} + * * @param supplier Should return a new {@link KmsClientBuilder} on each invocation. * @return */