3030import software .amazon .awssdk .services .s3 .model .PutObjectRequest ;
3131import software .amazon .awssdk .services .s3 .model .PutObjectResponse ;
3232import software .amazon .awssdk .services .s3 .model .S3Request ;
33+ import software .amazon .awssdk .services .s3 .multipart .MultipartConfiguration ;
3334import software .amazon .encryption .s3 .internal .GetEncryptedObjectPipeline ;
3435import software .amazon .encryption .s3 .internal .NoRetriesAsyncRequestBody ;
3536import software .amazon .encryption .s3 .internal .PutEncryptedObjectPipeline ;
@@ -71,6 +72,7 @@ public class S3AsyncEncryptionClient extends DelegatingS3AsyncClient {
7172 private final boolean _enableDelayedAuthenticationMode ;
7273 private final boolean _enableMultipartPutObject ;
7374 private final long _bufferSize ;
75+ private final boolean _clientMultipartEnabled ;
7476
7577 private S3AsyncEncryptionClient (Builder builder ) {
7678 super (builder ._wrappedClient );
@@ -81,6 +83,7 @@ private S3AsyncEncryptionClient(Builder builder) {
8183 _enableDelayedAuthenticationMode = builder ._enableDelayedAuthenticationMode ;
8284 _enableMultipartPutObject = builder ._enableMultipartPutObject ;
8385 _bufferSize = builder ._bufferSize ;
86+ _clientMultipartEnabled = builder ._multipartEnabled != null && builder ._multipartEnabled ;
8487 }
8588
8689 /**
@@ -147,16 +150,19 @@ public CompletableFuture<PutObjectResponse> putObject(PutObjectRequest putObject
147150 }
148151
149152 private CompletableFuture <PutObjectResponse > multipartPutObject (PutObjectRequest putObjectRequest , AsyncRequestBody requestBody ) {
150- S3AsyncClient crtClient ;
151- if (_wrappedClient instanceof S3CrtAsyncClient ) {
153+ S3AsyncClient mpuClient ;
154+ if (_wrappedClient instanceof S3CrtAsyncClient && ! _clientMultipartEnabled ) {
152155 // if the wrappedClient is a CRT, use it
153- crtClient = _wrappedClient ;
154- } else {
155- // else create a default one
156- crtClient = S3AsyncClient .crtCreate ();
156+ mpuClient = _wrappedClient ;
157+ } else if (_clientMultipartEnabled ) {
158+ mpuClient = _wrappedClient ;
159+ }
160+ else {
161+ // else create a default CRT client
162+ mpuClient = S3AsyncClient .crtCreate ();
157163 }
158164 PutEncryptedObjectPipeline pipeline = PutEncryptedObjectPipeline .builder ()
159- .s3AsyncClient (crtClient )
165+ .s3AsyncClient (mpuClient )
160166 .cryptoMaterialsManager (_cryptoMaterialsManager )
161167 .secureRandom (_secureRandom )
162168 .build ();
@@ -291,8 +297,12 @@ public static class Builder implements S3AsyncClientBuilder {
291297 private S3Configuration _serviceConfiguration = null ;
292298 private Boolean _accelerate = null ;
293299 private Boolean _disableMultiRegionAccessPoints = null ;
300+ private Boolean _disableS3ExpressSessionAuth = null ;
294301 private Boolean _forcePathStyle = null ;
295302 private Boolean _useArnRegion = null ;
303+ private Boolean _crossRegionAccessEnabled = null ;
304+ private Boolean _multipartEnabled = null ;
305+ private MultipartConfiguration _multipartConfiguration = null ;
296306
297307 private Builder () {
298308 }
@@ -696,6 +706,12 @@ public Builder disableMultiRegionAccessPoints(Boolean disableMultiRegionAccessPo
696706 return this ;
697707 }
698708
709+ @ Override
710+ public S3AsyncClientBuilder disableS3ExpressSessionAuth (Boolean disableS3ExpressSessionAuth ) {
711+ _disableS3ExpressSessionAuth = disableS3ExpressSessionAuth ;
712+ return this ;
713+ }
714+
699715 /**
700716 * Forces this client to use path-style addressing for buckets.
701717 *
@@ -719,6 +735,24 @@ public Builder useArnRegion(Boolean useArnRegion) {
719735 return this ;
720736 }
721737
738+ @ Override
739+ public Builder multipartEnabled (Boolean enabled ) {
740+ _multipartEnabled = enabled ;
741+ return this ;
742+ }
743+
744+ @ Override
745+ public S3AsyncClientBuilder multipartConfiguration (MultipartConfiguration multipartConfiguration ) {
746+ _multipartConfiguration = multipartConfiguration ;
747+ return this ;
748+ }
749+
750+ @ Override
751+ public Builder crossRegionAccessEnabled (Boolean crossRegionAccessEnabled ) {
752+ _crossRegionAccessEnabled = crossRegionAccessEnabled ;
753+ return this ;
754+ }
755+
722756 /**
723757 * Validates and builds the S3AsyncEncryptionClient according
724758 * to the configuration options passed to the Builder object.
@@ -737,6 +771,12 @@ public S3AsyncEncryptionClient build() {
737771 _bufferSize = DEFAULT_BUFFER_SIZE_BYTES ;
738772 }
739773
774+ // The S3 Async Client has its own multipart setting,
775+ // we enforce that the S3EC multipart PutObject setting is enabled as well.
776+ if (_multipartEnabled != null && _multipartEnabled && !_enableMultipartPutObject ) {
777+ throw new S3EncryptionClientException ("EnableMultipartPutObject MUST be enabled when the MultipartEnabled option is set to true." );
778+ }
779+
740780 if (_wrappedClient == null ) {
741781 _wrappedClient = S3AsyncClient .builder ()
742782 .credentialsProvider (_awsCredentialsProvider )
@@ -751,8 +791,12 @@ public S3AsyncEncryptionClient build() {
751791 .serviceConfiguration (_serviceConfiguration )
752792 .accelerate (_accelerate )
753793 .disableMultiRegionAccessPoints (_disableMultiRegionAccessPoints )
794+ .disableS3ExpressSessionAuth (_disableS3ExpressSessionAuth )
754795 .forcePathStyle (_forcePathStyle )
755796 .useArnRegion (_useArnRegion )
797+ .crossRegionAccessEnabled (_crossRegionAccessEnabled )
798+ .multipartEnabled (_multipartEnabled )
799+ .multipartConfiguration (_multipartConfiguration )
756800 .build ();
757801 }
758802
0 commit comments