Skip to content

Commit 0fb9a9f

Browse files
committed
fix: preserve override configuration
1 parent 35f1192 commit 0fb9a9f

7 files changed

Lines changed: 224 additions & 25 deletions

File tree

src/main/java/software/amazon/encryption/s3/S3AsyncEncryptionClient.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.DEFAULT_BUFFER_SIZE_BYTES;
66
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.MAX_ALLOWED_BUFFER_SIZE_BYTES;
77
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.MIN_ALLOWED_BUFFER_SIZE_BYTES;
8-
import static software.amazon.encryption.s3.internal.ApiNameVersion.API_NAME_INTERCEPTOR;
98

109
import java.net.URI;
1110
import java.security.KeyPair;
@@ -56,6 +55,7 @@
5655
import software.amazon.awssdk.services.s3.model.UploadPartResponse;
5756
import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration;
5857
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
58+
import software.amazon.encryption.s3.internal.ApiNameVersion;
5959
import software.amazon.encryption.s3.internal.GetEncryptedObjectPipeline;
6060
import software.amazon.encryption.s3.internal.InstructionFileConfig;
6161
import software.amazon.encryption.s3.internal.NoRetriesAsyncRequestBody;
@@ -248,12 +248,12 @@ public <T> CompletableFuture<T> getObject(GetObjectRequest getObjectRequest,
248248
@Override
249249
public CompletableFuture<DeleteObjectResponse> deleteObject(DeleteObjectRequest deleteObjectRequest) {
250250
final DeleteObjectRequest actualRequest = deleteObjectRequest.toBuilder()
251-
.overrideConfiguration(API_NAME_INTERCEPTOR)
251+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(deleteObjectRequest.overrideConfiguration()))
252252
.build();
253253
final CompletableFuture<DeleteObjectResponse> response = _wrappedClient.deleteObject(actualRequest);
254254
final String instructionObjectKey = deleteObjectRequest.key() + ".instruction";
255255
final CompletableFuture<DeleteObjectResponse> instructionResponse = _wrappedClient.deleteObject(builder -> builder
256-
.overrideConfiguration(API_NAME_INTERCEPTOR)
256+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(deleteObjectRequest.overrideConfiguration()))
257257
.bucket(deleteObjectRequest.bucket())
258258
.key(instructionObjectKey));
259259
// Delete the instruction file, then delete the object
@@ -279,7 +279,7 @@ public CompletableFuture<DeleteObjectsResponse> deleteObjects(DeleteObjectsReque
279279
// Add the original objects
280280
objectsToDelete.addAll(deleteObjectsRequest.delete().objects());
281281
return _wrappedClient.deleteObjects(deleteObjectsRequest.toBuilder()
282-
.overrideConfiguration(API_NAME_INTERCEPTOR)
282+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(deleteObjectsRequest.overrideConfiguration()))
283283
.delete(builder -> builder.objects(objectsToDelete))
284284
.build());
285285
}

src/main/java/software/amazon/encryption/s3/S3EncryptionClient.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import software.amazon.awssdk.services.s3.model.UploadPartRequest;
4848
import software.amazon.awssdk.services.s3.model.UploadPartResponse;
4949
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
50+
import software.amazon.encryption.s3.internal.ApiNameVersion;
5051
import software.amazon.encryption.s3.internal.ContentMetadata;
5152
import software.amazon.encryption.s3.internal.ContentMetadataDecodingStrategy;
5253
import software.amazon.encryption.s3.internal.ContentMetadataEncodingStrategy;
@@ -99,7 +100,6 @@
99100
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.MAX_ALLOWED_BUFFER_SIZE_BYTES;
100101
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.MIN_ALLOWED_BUFFER_SIZE_BYTES;
101102
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.instructionFileKeysToDelete;
102-
import static software.amazon.encryption.s3.internal.ApiNameVersion.API_NAME_INTERCEPTOR;
103103

104104

105105
//= specification/s3-encryption/client.md#aws-sdk-compatibility
@@ -561,7 +561,7 @@ private <T extends Throwable> T onAbort(UploadObjectObserver observer, T t) {
561561
public DeleteObjectResponse deleteObject(DeleteObjectRequest deleteObjectRequest) throws AwsServiceException,
562562
SdkClientException {
563563
DeleteObjectRequest actualRequest = deleteObjectRequest.toBuilder()
564-
.overrideConfiguration(API_NAME_INTERCEPTOR)
564+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(deleteObjectRequest.overrideConfiguration()))
565565
.build();
566566

567567
try {
@@ -574,7 +574,7 @@ public DeleteObjectResponse deleteObject(DeleteObjectRequest deleteObjectRequest
574574
//# - DeleteObject MUST delete the associated instruction file using the default instruction file suffix.
575575
String instructionObjectKey = deleteObjectRequest.key() + DEFAULT_INSTRUCTION_FILE_SUFFIX;
576576
_wrappedAsyncClient.deleteObject(builder -> builder
577-
.overrideConfiguration(API_NAME_INTERCEPTOR)
577+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(deleteObjectRequest.overrideConfiguration()))
578578
.bucket(deleteObjectRequest.bucket())
579579
.key(instructionObjectKey)).join();
580580
// Return original deletion
@@ -603,7 +603,7 @@ public DeleteObjectResponse deleteObject(DeleteObjectRequest deleteObjectRequest
603603
public DeleteObjectsResponse deleteObjects(DeleteObjectsRequest deleteObjectsRequest) throws AwsServiceException,
604604
SdkClientException {
605605
DeleteObjectsRequest actualRequest = deleteObjectsRequest.toBuilder()
606-
.overrideConfiguration(API_NAME_INTERCEPTOR)
606+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(deleteObjectsRequest.overrideConfiguration()))
607607
.build();
608608
try {
609609
//= specification/s3-encryption/client.md#required-api-operations
@@ -615,7 +615,7 @@ public DeleteObjectsResponse deleteObjects(DeleteObjectsRequest deleteObjectsReq
615615
//# - DeleteObjects MUST delete each of the corresponding instruction files using the default instruction file suffix.
616616
List<ObjectIdentifier> deleteObjects = instructionFileKeysToDelete(deleteObjectsRequest);
617617
_wrappedAsyncClient.deleteObjects(DeleteObjectsRequest.builder()
618-
.overrideConfiguration(API_NAME_INTERCEPTOR)
618+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(deleteObjectsRequest.overrideConfiguration()))
619619
.bucket(deleteObjectsRequest.bucket())
620620
.delete(builder -> builder.objects(deleteObjects))
621621
.build()).join();

src/main/java/software/amazon/encryption/s3/internal/ApiNameVersion.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,36 @@
99
import java.io.IOException;
1010
import java.net.URL;
1111
import java.util.Enumeration;
12+
import java.util.Optional;
1213
import java.util.Properties;
13-
import java.util.function.Consumer;
1414

1515
/**
1616
* Provides the information for the ApiName APIs for the AWS SDK
1717
*/
1818
public class ApiNameVersion {
1919
private static final ApiName API_NAME = ApiNameVersion.apiNameWithVersion();
20-
// This is used in overrideConfiguration
21-
public static final Consumer<AwsRequestOverrideConfiguration.Builder> API_NAME_INTERCEPTOR =
22-
builder -> builder.addApiName(API_NAME);
2320

2421
public static final String NAME = "AmazonS3Encrypt";
2522
public static final String API_VERSION_UNKNOWN = "3-unknown";
2623

24+
/**
25+
* Returns an {@link AwsRequestOverrideConfiguration} which includes the S3EC API name while
26+
* preserving any override configuration the caller already set on their request. This ensures
27+
* caller-supplied configuration (e.g. custom headers, credentials providers, or signer
28+
* overrides) is not dropped when the S3EC adds its API name.
29+
*
30+
* @param existingOverrideConfiguration the override configuration from the original request, if any
31+
* @return an override configuration containing the S3EC API name merged with the existing configuration
32+
*/
33+
public static AwsRequestOverrideConfiguration addApiNameToOverrideConfiguration(
34+
Optional<AwsRequestOverrideConfiguration> existingOverrideConfiguration) {
35+
return existingOverrideConfiguration
36+
.map(AwsRequestOverrideConfiguration::toBuilder)
37+
.orElseGet(AwsRequestOverrideConfiguration::builder)
38+
.addApiName(API_NAME)
39+
.build();
40+
}
41+
2742
public static ApiName apiNameWithVersion() {
2843
return ApiName.builder()
2944
.name(NAME)

src/main/java/software/amazon/encryption/s3/internal/GetEncryptedObjectPipeline.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
import java.util.List;
2525
import java.util.concurrent.CompletableFuture;
2626

27-
import static software.amazon.encryption.s3.internal.ApiNameVersion.API_NAME_INTERCEPTOR;
28-
2927
/**
3028
* This class will determine the necessary mechanisms to decrypt objects returned from S3.
3129
* Due to supporting various legacy modes, this is not a predefined pipeline like
@@ -64,7 +62,7 @@ public <T> CompletableFuture<T> getObject(GetObjectRequest getObjectRequest, Asy
6462
//# and end of the cipher blocks for the given range.
6563
String cryptoRange = RangedGetUtils.getCryptoRangeAsString(getObjectRequest.range());
6664
GetObjectRequest adjustedRangeRequest = getObjectRequest.toBuilder()
67-
.overrideConfiguration(API_NAME_INTERCEPTOR)
65+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(getObjectRequest.overrideConfiguration()))
6866
.range(cryptoRange)
6967
.build();
7068
if (!_enableLegacyUnauthenticatedModes && getObjectRequest.range() != null) {

src/main/java/software/amazon/encryption/s3/internal/MultipartUploadObjectPipeline.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// SPDX-License-Identifier: Apache-2.0
33
package software.amazon.encryption.s3.internal;
44

5-
import static software.amazon.encryption.s3.internal.ApiNameVersion.API_NAME_INTERCEPTOR;
6-
75
import java.io.IOException;
86
import java.io.InputStream;
97
import java.io.OutputStream;
@@ -75,7 +73,7 @@ public CreateMultipartUploadResponse createMultipartUpload(CreateMultipartUpload
7573

7674
CreateMultipartUploadRequest createMpuRequest = _contentMetadataEncodingStrategy.encodeMetadata(materials, encryptedContent.iv(), request);
7775
request = createMpuRequest.toBuilder()
78-
.overrideConfiguration(API_NAME_INTERCEPTOR)
76+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(createMpuRequest.overrideConfiguration()))
7977
.build();
8078

8179
//= specification/s3-encryption/client.md#optional-api-operations
@@ -129,7 +127,7 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
129127

130128
// Once we have (a valid) ciphertext length, set the request contentLength
131129
UploadPartRequest actualRequest = request.toBuilder()
132-
.overrideConfiguration(API_NAME_INTERCEPTOR)
130+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(request.overrideConfiguration()))
133131
.contentLength(ciphertextLength)
134132
.build();
135133

@@ -195,7 +193,7 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
195193
}
196194

197195
CompleteMultipartUploadRequest actualRequest = request.toBuilder()
198-
.overrideConfiguration(API_NAME_INTERCEPTOR)
196+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(request.overrideConfiguration()))
199197
.build();
200198

201199
//= specification/s3-encryption/client.md#optional-api-operations
@@ -209,7 +207,7 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
209207
public AbortMultipartUploadResponse abortMultipartUpload(AbortMultipartUploadRequest request) {
210208
_multipartUploadMaterials.remove(request.uploadId());
211209
AbortMultipartUploadRequest actualRequest = request.toBuilder()
212-
.overrideConfiguration(API_NAME_INTERCEPTOR)
210+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(request.overrideConfiguration()))
213211
.build();
214212
//= specification/s3-encryption/client.md#optional-api-operations
215213
//# - AbortMultipartUpload MUST abort the multipart upload.

src/main/java/software/amazon/encryption/s3/internal/PutEncryptedObjectPipeline.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// SPDX-License-Identifier: Apache-2.0
33
package software.amazon.encryption.s3.internal;
44

5-
import static software.amazon.encryption.s3.internal.ApiNameVersion.API_NAME_INTERCEPTOR;
6-
75
import java.security.SecureRandom;
86
import java.util.concurrent.CompletableFuture;
97

@@ -75,7 +73,7 @@ public CompletableFuture<PutObjectResponse> putObject(PutObjectRequest request,
7573

7674
PutObjectRequest modifiedRequest = _contentMetadataEncodingStrategy.encodeMetadata(materials, encryptedContent.iv(), request);
7775
PutObjectRequest encryptedPutRequest = modifiedRequest.toBuilder()
78-
.overrideConfiguration(API_NAME_INTERCEPTOR)
76+
.overrideConfiguration(ApiNameVersion.addApiNameToOverrideConfiguration(request.overrideConfiguration()))
7977
.contentLength(encryptedContent.getCiphertextLength())
8078
.build();
8179
return _s3AsyncClient.putObject(encryptedPutRequest, encryptedContent.getAsyncCiphertext());

0 commit comments

Comments
 (0)