diff --git a/pom.xml b/pom.xml
index de793bbb9..98159fd1d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,7 +56,7 @@
software.amazon.awssdk
bom
- 2.31.14
+ 2.43.0
true
pom
import
@@ -68,13 +68,13 @@
software.amazon.awssdk
s3
- 2.31.14
+ 2.43.0
software.amazon.awssdk
kms
- 2.31.14
+ 2.43.0
@@ -82,7 +82,7 @@
software.amazon.awssdk.crt
aws-crt
true
- 0.37.0
+ 0.45.1
@@ -169,7 +169,7 @@
software.amazon.awssdk
sts
- 2.31.14
+ 2.43.0
true
test
diff --git a/src/main/java/software/amazon/encryption/s3/internal/PutEncryptedObjectPipeline.java b/src/main/java/software/amazon/encryption/s3/internal/PutEncryptedObjectPipeline.java
index fb2ddbae3..96be243d3 100644
--- a/src/main/java/software/amazon/encryption/s3/internal/PutEncryptedObjectPipeline.java
+++ b/src/main/java/software/amazon/encryption/s3/internal/PutEncryptedObjectPipeline.java
@@ -84,7 +84,7 @@ public CompletableFuture putObject(PutObjectRequest request,
.overrideConfiguration(API_NAME_INTERCEPTOR)
.contentLength(encryptedContent.getCiphertextLength())
.build();
- return _s3AsyncClient.putObject(encryptedPutRequest, encryptedContent.getAsyncCiphertext());
+ return _s3AsyncClient.putObject(encryptedPutRequest, new NoRetriesAsyncRequestBody(encryptedContent.getAsyncCiphertext()));
}
public static class Builder {
diff --git a/src/test/java/software/amazon/encryption/s3/S3AsyncEncryptionClientTest.java b/src/test/java/software/amazon/encryption/s3/S3AsyncEncryptionClientTest.java
index 4a9aa9483..141e3f5ca 100644
--- a/src/test/java/software/amazon/encryption/s3/S3AsyncEncryptionClientTest.java
+++ b/src/test/java/software/amazon/encryption/s3/S3AsyncEncryptionClientTest.java
@@ -46,6 +46,7 @@
import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration;
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
import software.amazon.encryption.s3.internal.InstructionFileConfig;
+import software.amazon.encryption.s3.materials.AesKeyring;
import software.amazon.encryption.s3.materials.KmsKeyring;
import software.amazon.encryption.s3.utils.BoundedInputStream;
import software.amazon.encryption.s3.utils.S3EncryptionClientTestResources;
@@ -53,6 +54,7 @@
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
@@ -349,6 +351,31 @@ public void asyncTopLevelConfigurationWrongRegion() {
}
}
+ @RetryingTest(3)
+ public void roundTripWithCrossRegionAccessEnabled() {
+ final String objectKey = appendTestSuffix("roundTripWithCrossRegionAccessEnabled-async-s3ec");
+ SecretKeySpec aesKey = new SecretKeySpec(new byte[32], "AES");
+ AesKeyring keyRing = AesKeyring.builder().wrappingKey(aesKey).build();
+
+ S3AsyncClient s3Client = S3AsyncEncryptionClient.builderV4()
+ .region(Region.EU_CENTRAL_1)
+ .crossRegionAccessEnabled(true)
+ .keyring(keyRing)
+ .build();
+
+ try {
+ PutObjectRequest request = PutObjectRequest.builder().bucket(BUCKET).key(objectKey).build();
+ CompletionException ex = assertThrows(CompletionException.class, () ->
+ s3Client.putObject(request, AsyncRequestBody.fromBytes("test".getBytes())).join());
+ // Cross-region redirect causes the SDK to re-subscribe to the request body.
+ // NoRetriesAsyncRequestBody blocks this to prevent GCM cipher key/IV reuse.
+ assertTrue(ex.getCause() instanceof S3EncryptionClientException);
+ assertTrue(ex.getCause().getMessage().contains("Re-subscription is not supported"));
+ } finally {
+ s3Client.close();
+ }
+ }
+
@RetryingTest(3)
public void asyncTopLevelConfigurationNullCreds() {
final String objectKey = appendTestSuffix("wrapped-s3-client-with-null-credentials-async");
diff --git a/src/test/java/software/amazon/encryption/s3/S3EncryptionClientTest.java b/src/test/java/software/amazon/encryption/s3/S3EncryptionClientTest.java
index ea46b7e1d..356ddbdff 100644
--- a/src/test/java/software/amazon/encryption/s3/S3EncryptionClientTest.java
+++ b/src/test/java/software/amazon/encryption/s3/S3EncryptionClientTest.java
@@ -42,6 +42,7 @@
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
import software.amazon.encryption.s3.internal.InstructionFileConfig;
import software.amazon.encryption.s3.internal.MetadataKeyConstants;
+import software.amazon.encryption.s3.materials.AesKeyring;
import software.amazon.encryption.s3.materials.CryptographicMaterialsManager;
import software.amazon.encryption.s3.materials.DefaultCryptoMaterialsManager;
import software.amazon.encryption.s3.materials.KmsKeyring;
@@ -52,6 +53,7 @@
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
@@ -964,6 +966,30 @@ public void s3EncryptionClientTopLevelCredentialsWrongRegion() {
}
}
+ @RetryingTest(3)
+ public void roundTripWithCrossRegionAccessEnabled() {
+ final String objectKey = appendTestSuffix("roundTripWithCrossRegionAccessEnabled-sync-s3ec");
+ SecretKeySpec aesKey = new SecretKeySpec(new byte[32], "AES");
+ AesKeyring keyRing = AesKeyring.builder().wrappingKey(aesKey).build();
+
+ S3Client s3 = S3EncryptionClient.builderV4()
+ .region(Region.EU_CENTRAL_1)
+ .crossRegionAccessEnabled(true)
+ .keyring(keyRing)
+ .build();
+
+ try {
+ PutObjectRequest request = PutObjectRequest.builder().bucket(BUCKET).key(objectKey).build();
+ S3EncryptionClientException ex = assertThrows(S3EncryptionClientException.class, () ->
+ s3.putObject(request, RequestBody.fromBytes("test".getBytes())));
+ // Cross-region redirect causes the SDK to re-subscribe to the request body.
+ // S3EC blocks this to prevent GCM cipher key/IV reuse.
+ assertTrue(ex.getCause().getMessage().contains("Re-subscription is not supported"));
+ } finally {
+ s3.close();
+ }
+ }
+
@RetryingTest(3)
public void s3EncryptionClientTopLevelCredentialsNullCreds() {
final String objectKey = appendTestSuffix("wrapped-s3-client-with-null-credentials");