Skip to content

Commit 2eeda1c

Browse files
authored
Added disableS3ExpressSessionAuth field to S3CrtAsyncClientBuilder (#5887)
* added disableS3ExpressSessionAuth field * unit test added * changelog added * minor change * doc change * change log change
1 parent 9fa37f9 commit 2eeda1c

File tree

4 files changed

+131
-1
lines changed

4 files changed

+131
-1
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "Amazon S3",
4+
"contributor": "",
5+
"description": "Allow users to configure disableS3ExpressSessionAuth for S3CrtAsyncClient"
6+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.s3.s3express;
17+
18+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
19+
import static software.amazon.awssdk.testutils.service.S3BucketUtils.temporaryBucketName;
20+
21+
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
22+
import java.net.URI;
23+
import org.junit.jupiter.api.AfterAll;
24+
import org.junit.jupiter.api.BeforeAll;
25+
import org.junit.jupiter.api.Test;
26+
import org.junit.jupiter.api.extension.RegisterExtension;
27+
import software.amazon.awssdk.core.SdkSystemSetting;
28+
import software.amazon.awssdk.regions.Region;
29+
import software.amazon.awssdk.services.s3.S3AsyncClient;
30+
31+
import software.amazon.awssdk.testutils.EnvironmentVariableHelper;
32+
import static com.github.tomakehurst.wiremock.client.WireMock.*;
33+
34+
35+
public class DisableS3ExpressSessionAuthTest extends S3ExpressIntegrationTestBase {
36+
37+
@RegisterExtension
38+
static WireMockExtension s3WireMock = WireMockExtension.newInstance()
39+
.options(wireMockConfig().dynamicPort())
40+
.build();
41+
42+
private static final Region TEST_REGION = Region.US_EAST_1;
43+
private static final String AZ = "use1-az4";
44+
private static S3AsyncClient s3CrtAsync;
45+
private static S3AsyncClient s3CrtAsyncDefault;
46+
private static String testBucket;
47+
48+
private static final EnvironmentVariableHelper ENVIRONMENT_VARIABLE_HELPER = new EnvironmentVariableHelper();
49+
50+
private static final String S3EXPRESS_BUCKET_PATTERN = temporaryBucketName(S3ExpressIntegrationTest.class) +"--%s--x-s3";
51+
52+
53+
private static String getS3ExpressBucketNameForAz(String az) {
54+
return String.format(S3EXPRESS_BUCKET_PATTERN, az);
55+
}
56+
57+
private static final String CREATE_SESSION_RESPONSE =
58+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
59+
+ "<CreateSessionResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">\n"
60+
+ "<Credentials><SessionToken>TheToken</SessionToken><SecretAccessKey>TheSecret"
61+
+ "</SecretAccessKey><AccessKeyId>TheAccessKey</AccessKeyId><Expiration>2025-02-19T00:23:59Z</Expiration></Credentials>\n"
62+
+ "</CreateSessionResult>";
63+
64+
@BeforeAll
65+
static void setup() {
66+
ENVIRONMENT_VARIABLE_HELPER.reset();
67+
ENVIRONMENT_VARIABLE_HELPER.set(SdkSystemSetting.AWS_S3_DISABLE_EXPRESS_SESSION_AUTH.environmentVariable(), "false");
68+
69+
testBucket = getS3ExpressBucketNameForAz(AZ);
70+
71+
s3CrtAsyncDefault = s3CrtAsyncClientBuilder(TEST_REGION).endpointOverride(URI.create("http://s3.localhost.localstack.cloud:" + s3WireMock.getPort())).build();
72+
s3CrtAsync = s3CrtAsyncClientBuilder(TEST_REGION).disableS3ExpressSessionAuth(true)
73+
.endpointOverride(URI.create("http://s3.localhost.localstack.cloud:" + s3WireMock.getPort())).build();
74+
75+
}
76+
77+
@AfterAll
78+
static void clear() {
79+
ENVIRONMENT_VARIABLE_HELPER.reset();
80+
s3CrtAsync.close();
81+
s3CrtAsyncDefault.close();
82+
}
83+
84+
private void setupWireMockStub() {
85+
s3WireMock.stubFor(get(anyUrl()).willReturn(aResponse().withStatus(200).withBody(CREATE_SESSION_RESPONSE)));
86+
}
87+
88+
89+
@Test
90+
void defaultS3CrtAsyncClient_useS3ExpressAuth() {
91+
//x-amz-s3session-token will be there
92+
setupWireMockStub();
93+
s3CrtAsyncDefault.listObjectsV2(r -> r.bucket(testBucket)).join();
94+
s3WireMock.verify(1,getRequestedFor(urlPathMatching(".*"))
95+
.withHeader("x-amz-s3session-token", matching(".*")));
96+
}
97+
98+
99+
@Test
100+
void disabledS3CrtAsyncClient_NotUseS3ExpressAuth() {
101+
//x-amz-s3session-token will not be there
102+
setupWireMockStub();
103+
s3CrtAsync.listObjectsV2(r -> r.bucket(testBucket)).join();
104+
s3WireMock.verify(1,getRequestedFor(urlPathMatching(".*"))
105+
.withoutHeader("x-amz-s3session-token"));
106+
}
107+
}

services/s3/src/main/java/software/amazon/awssdk/services/s3/S3CrtAsyncClientBuilder.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,15 @@ default S3CrtAsyncClientBuilder retryConfiguration(Consumer<S3CrtRetryConfigurat
352352
*/
353353
S3CrtAsyncClientBuilder futureCompletionExecutor(Executor futureCompletionExecutor);
354354

355+
/**
356+
* Configure whether to disable this client's usage of Session Auth for S3Express buckets and reverts to using conventional
357+
* SigV4 for those.
358+
*
359+
* @param disableS3ExpressSessionAuth whether Session Auth for S3Express should be disabled
360+
* @return an instance of this builder
361+
*/
362+
S3CrtAsyncClientBuilder disableS3ExpressSessionAuth(Boolean disableS3ExpressSessionAuth);
363+
355364

356365
@Override
357366
S3AsyncClient build();

services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClient.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ private static S3AsyncClient initializeS3AsyncClient(DefaultS3CrtClientBuilder b
140140
.forcePathStyle(finalBuilder.forcePathStyle)
141141
.crossRegionAccessEnabled(finalBuilder.crossRegionAccessEnabled)
142142
.putAuthScheme(new CrtS3ExpressNoOpAuthScheme())
143-
.httpClientBuilder(initializeS3CrtAsyncHttpClient(finalBuilder));
143+
.httpClientBuilder(initializeS3CrtAsyncHttpClient(finalBuilder))
144+
.disableS3ExpressSessionAuth(finalBuilder.disableS3ExpressSessionAuth);
144145

145146

146147
if (finalBuilder.futureCompletionExecutor != null) {
@@ -225,6 +226,7 @@ public static final class DefaultS3CrtClientBuilder implements S3CrtAsyncClientB
225226
private boolean crossRegionAccessEnabled;
226227
private Long thresholdInBytes;
227228
private Executor futureCompletionExecutor;
229+
private Boolean disableS3ExpressSessionAuth;
228230

229231
@Override
230232
public DefaultS3CrtClientBuilder credentialsProvider(
@@ -344,6 +346,12 @@ public DefaultS3CrtClientBuilder futureCompletionExecutor(Executor futureComplet
344346
return this;
345347
}
346348

349+
@Override
350+
public DefaultS3CrtClientBuilder disableS3ExpressSessionAuth(Boolean disableS3ExpressSessionAuth) {
351+
this.disableS3ExpressSessionAuth = disableS3ExpressSessionAuth;
352+
return this;
353+
}
354+
347355
@Override
348356
public S3CrtAsyncClient build() {
349357
return new DefaultS3CrtAsyncClient(this);

0 commit comments

Comments
 (0)