Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: bump AWS SDK dependencies #384

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,25 @@
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.release>8</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<aws.java.sdk.version>2.21.46</aws.java.sdk.version>
<aws.java.crt.version>0.29.24</aws.java.crt.version>
<com.amazonaws.version>1.12.441</com.amazonaws.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>1.12.441</version>
<version>${com.amazonaws.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.20.38</version>
<version>${aws.java.sdk.version}</version>
<optional>true</optional>
<type>pom</type>
<scope>import</scope>
Expand All @@ -68,21 +71,19 @@
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.20.38</version>
</dependency>

<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>kms</artifactId>
<version>2.20.38</version>
<optional>true</optional>
</dependency>

<!-- Used when enableMultipartPutObject is configured -->
<dependency>
<groupId>software.amazon.awssdk.crt</groupId>
<artifactId>aws-crt</artifactId>
<version>0.29.24</version>
<version>${aws.java.crt.version}</version>
<optional>true</optional>
</dependency>

Expand Down Expand Up @@ -164,7 +165,6 @@
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sts</artifactId>
<version>2.20.38</version>
<optional>true</optional>
<scope>test</scope>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
import software.amazon.awssdk.services.s3.model.S3Request;
import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration;
import software.amazon.encryption.s3.internal.GetEncryptedObjectPipeline;
import software.amazon.encryption.s3.internal.NoRetriesAsyncRequestBody;
import software.amazon.encryption.s3.internal.PutEncryptedObjectPipeline;
Expand Down Expand Up @@ -71,6 +72,7 @@ public class S3AsyncEncryptionClient extends DelegatingS3AsyncClient {
private final boolean _enableDelayedAuthenticationMode;
private final boolean _enableMultipartPutObject;
private final long _bufferSize;
private final boolean _clientMultipartEnabled;

private S3AsyncEncryptionClient(Builder builder) {
super(builder._wrappedClient);
Expand All @@ -81,6 +83,7 @@ private S3AsyncEncryptionClient(Builder builder) {
_enableDelayedAuthenticationMode = builder._enableDelayedAuthenticationMode;
_enableMultipartPutObject = builder._enableMultipartPutObject;
_bufferSize = builder._bufferSize;
_clientMultipartEnabled = builder._multipartEnabled != null && builder._multipartEnabled;
}

/**
Expand Down Expand Up @@ -147,16 +150,19 @@ public CompletableFuture<PutObjectResponse> putObject(PutObjectRequest putObject
}

private CompletableFuture<PutObjectResponse> multipartPutObject(PutObjectRequest putObjectRequest, AsyncRequestBody requestBody) {
S3AsyncClient crtClient;
if (_wrappedClient instanceof S3CrtAsyncClient) {
S3AsyncClient mpuClient;
if (_wrappedClient instanceof S3CrtAsyncClient && !_clientMultipartEnabled) {
// if the wrappedClient is a CRT, use it
crtClient = _wrappedClient;
} else {
// else create a default one
crtClient = S3AsyncClient.crtCreate();
mpuClient = _wrappedClient;
} else if (_clientMultipartEnabled) {
mpuClient = _wrappedClient;
}
else {
// else create a default CRT client
mpuClient = S3AsyncClient.crtCreate();
}
PutEncryptedObjectPipeline pipeline = PutEncryptedObjectPipeline.builder()
.s3AsyncClient(crtClient)
.s3AsyncClient(mpuClient)
.cryptoMaterialsManager(_cryptoMaterialsManager)
.secureRandom(_secureRandom)
.build();
Expand Down Expand Up @@ -291,8 +297,12 @@ public static class Builder implements S3AsyncClientBuilder {
private S3Configuration _serviceConfiguration = null;
private Boolean _accelerate = null;
private Boolean _disableMultiRegionAccessPoints = null;
private Boolean _disableS3ExpressSessionAuth = null;
private Boolean _forcePathStyle = null;
private Boolean _useArnRegion = null;
private Boolean _crossRegionAccessEnabled = null;
private Boolean _multipartEnabled = null;
private MultipartConfiguration _multipartConfiguration = null;

private Builder() {
}
Expand Down Expand Up @@ -696,6 +706,12 @@ public Builder disableMultiRegionAccessPoints(Boolean disableMultiRegionAccessPo
return this;
}

@Override
public S3AsyncClientBuilder disableS3ExpressSessionAuth(Boolean disableS3ExpressSessionAuth) {
_disableS3ExpressSessionAuth = disableS3ExpressSessionAuth;
return this;
}

/**
* Forces this client to use path-style addressing for buckets.
*
Expand All @@ -719,6 +735,24 @@ public Builder useArnRegion(Boolean useArnRegion) {
return this;
}

@Override
public Builder multipartEnabled(Boolean enabled) {
_multipartEnabled = enabled;
return this;
}

@Override
public S3AsyncClientBuilder multipartConfiguration(MultipartConfiguration multipartConfiguration) {
_multipartConfiguration = multipartConfiguration;
return this;
}

@Override
public Builder crossRegionAccessEnabled(Boolean crossRegionAccessEnabled) {
_crossRegionAccessEnabled = crossRegionAccessEnabled;
return this;
}

/**
* Validates and builds the S3AsyncEncryptionClient according
* to the configuration options passed to the Builder object.
Expand All @@ -737,6 +771,12 @@ public S3AsyncEncryptionClient build() {
_bufferSize = DEFAULT_BUFFER_SIZE_BYTES;
}

// The S3 Async Client has its own multipart setting,
// we enforce that the S3EC multipart PutObject setting is enabled as well.
if (_multipartEnabled != null && _multipartEnabled && !_enableMultipartPutObject) {
throw new S3EncryptionClientException("EnableMultipartPutObject MUST be enabled when the MultipartEnabled option is set to true.");
}

if (_wrappedClient == null) {
_wrappedClient = S3AsyncClient.builder()
.credentialsProvider(_awsCredentialsProvider)
Expand All @@ -751,8 +791,12 @@ public S3AsyncEncryptionClient build() {
.serviceConfiguration(_serviceConfiguration)
.accelerate(_accelerate)
.disableMultiRegionAccessPoints(_disableMultiRegionAccessPoints)
.disableS3ExpressSessionAuth(_disableS3ExpressSessionAuth)
.forcePathStyle(_forcePathStyle)
.useArnRegion(_useArnRegion)
.crossRegionAccessEnabled(_crossRegionAccessEnabled)
.multipartEnabled(_multipartEnabled)
.multipartConfiguration(_multipartConfiguration)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,10 @@ public static class Builder implements S3BaseClientBuilder<Builder, S3Encryption
private S3Configuration _serviceConfiguration = null;
private Boolean _accelerate = null;
private Boolean _disableMultiRegionAccessPoints = null;
private Boolean _disableS3ExpressSessionAuth = null;
private Boolean _forcePathStyle = null;
private Boolean _useArnRegion = null;
private Boolean _crossRegionAccessEnabled = null;
private SdkHttpClient _httpClient = null;
private SdkHttpClient.Builder _httpClientBuilder = null;
private SdkAsyncHttpClient _asyncHttpClient = null;
Expand Down Expand Up @@ -918,6 +920,18 @@ public Builder disableMultiRegionAccessPoints(Boolean disableMultiRegionAccessPo
return this;
}

/**
* Disables this client's usage of Session Auth for S3Express buckets and reverts to using conventional SigV4 for
* those.
*
* @param disableS3ExpressSessionAuth
*/
@Override
public Builder disableS3ExpressSessionAuth(Boolean disableS3ExpressSessionAuth) {
_disableS3ExpressSessionAuth = disableS3ExpressSessionAuth;
return this;
}

/**
* Forces this client to use path-style addressing for buckets.
*
Expand All @@ -941,6 +955,17 @@ public Builder useArnRegion(Boolean useArnRegion) {
return this;
}

/**
* Enables cross-region bucket access for this client
*
* @param crossRegionAccessEnabled
*/
@Override
public Builder crossRegionAccessEnabled(Boolean crossRegionAccessEnabled) {
_crossRegionAccessEnabled = crossRegionAccessEnabled;
return this;
}

/**
* Sets the {@link SdkHttpClient} that the SDK service client will use to make HTTP calls. This HTTP client may be
* shared between multiple SDK service clients to share a common connection pool. To create a client you must use an
Expand Down Expand Up @@ -1052,6 +1077,8 @@ public S3EncryptionClient build() {
.useArnRegion(_useArnRegion)
.httpClient(_httpClient)
.httpClientBuilder(_httpClientBuilder)
.disableS3ExpressSessionAuth(_disableS3ExpressSessionAuth)
.crossRegionAccessEnabled(_crossRegionAccessEnabled)
.build();
}

Expand All @@ -1070,6 +1097,9 @@ public S3EncryptionClient build() {
.useArnRegion(_useArnRegion)
.httpClient(_asyncHttpClient)
.httpClientBuilder(_asyncHttpClientBuilder)
.disableS3ExpressSessionAuth(_disableS3ExpressSessionAuth)
.crossRegionAccessEnabled(_crossRegionAccessEnabled)
// TODO: Add MPU stuff here too
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
Expand All @@ -39,6 +40,7 @@
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration;
import software.amazon.encryption.s3.materials.KmsKeyring;
import software.amazon.encryption.s3.utils.BoundedInputStream;
import software.amazon.encryption.s3.utils.S3EncryptionClientTestResources;
Expand All @@ -52,7 +54,9 @@
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
Expand All @@ -63,6 +67,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static software.amazon.encryption.s3.S3EncryptionClient.withAdditionalConfiguration;
import static software.amazon.encryption.s3.utils.S3EncryptionClientTestResources.ALTERNATE_KMS_KEY;
import static software.amazon.encryption.s3.utils.S3EncryptionClientTestResources.BUCKET;
import static software.amazon.encryption.s3.utils.S3EncryptionClientTestResources.KMS_KEY_ID;
Expand All @@ -74,12 +79,15 @@
public class S3AsyncEncryptionClientTest {

private static SecretKey AES_KEY;
private static Provider PROVIDER;

@BeforeAll
public static void setUp() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
AES_KEY = keyGen.generateKey();
Security.addProvider(new BouncyCastleProvider());
PROVIDER = Security.getProvider("BC");
}

@Test
Expand Down Expand Up @@ -755,4 +763,50 @@ public void tinyBufferTest() throws IOException {
exec.shutdown();
}

@Test
public void wrappedClientMultipartUpload() throws IOException {
final String objectKey = appendTestSuffix("multipart-put-object-async-wrapped-client");

final long fileSizeLimit = 1024 * 1024 * 100;
final InputStream inputStream = new BoundedInputStream(fileSizeLimit);
final InputStream objectStreamForResult = new BoundedInputStream(fileSizeLimit);

S3AsyncClient v3Client = S3AsyncEncryptionClient.builder()
.kmsKeyId(KMS_KEY_ID)
.enableDelayedAuthenticationMode(true)
.cryptoProvider(PROVIDER)
// .enableMultipartPutObject(true)
// .multipartEnabled(true)
.multipartConfiguration(
MultipartConfiguration.builder()
.thresholdInBytes((long)100000000)
.minimumPartSizeInBytes((long)500000)
.build()
)
.build();

Map<String, String> encryptionContext = new HashMap<>();
encryptionContext.put("user-metadata-key", "user-metadata-value-v3-to-v3");

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

CompletableFuture<PutObjectResponse> futurePut = v3Client.putObject(builder -> builder
.bucket(BUCKET)
.overrideConfiguration(withAdditionalConfiguration(encryptionContext))
.key(objectKey), AsyncRequestBody.fromInputStream(inputStream, fileSizeLimit, singleThreadExecutor));
futurePut.join();
singleThreadExecutor.shutdown();

// Asserts
CompletableFuture<ResponseInputStream<GetObjectResponse>> getFuture = v3Client.getObject(builder -> builder
.bucket(BUCKET)
.overrideConfiguration(S3EncryptionClient.withAdditionalConfiguration(encryptionContext))
.key(objectKey), AsyncResponseTransformer.toBlockingInputStream());
ResponseInputStream<GetObjectResponse> output = getFuture.join();

assertTrue(IOUtils.contentEquals(objectStreamForResult, output));

deleteObject(BUCKET, objectKey, v3Client);
v3Client.close();
}
}
Loading