Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
"hasChecksumValidationEnabledProperty":true
},
"skipEndpointTests": {
"Access points when Access points explicitly disabled (used for CreateBucket)": "CreateBucketInterceptor validates bucket name before endpoint resolution stage runs",
"Invalid access point ARN: Not S3": "Test assumes UseArnRegion is true but SDK defaults to false",
"Invalid access point ARN: AccountId is invalid": "Test assumes UseArnRegion is true but SDK defaults to false",
"Invalid access point ARN: access point name is invalid": "Test assumes UseArnRegion is true but SDK defaults to false",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import software.amazon.awssdk.services.s3.internal.crossregion.endpointprovider.BucketEndpointProvider;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.S3Response;
Expand Down Expand Up @@ -487,10 +488,10 @@ void given_globalRegion_Client_Updates_region_to_useast1_and_useGlobalEndpointFl
assertThat(captureInterceptor.endpointProvider).isInstanceOf(BucketEndpointProvider.class);
ArgumentCaptor<S3EndpointParams> collectionCaptor = ArgumentCaptor.forClass(S3EndpointParams.class);
verify(mockEndpointProvider, atLeastOnce()).resolveEndpoint(collectionCaptor.capture());
collectionCaptor.getAllValues().forEach(resolvedParams -> {
assertThat(resolvedParams.region()).isEqualTo(Region.US_EAST_1);
assertThat(resolvedParams.useGlobalEndpoint()).isFalse();
});
S3EndpointParams lastResolvedParams = collectionCaptor.getAllValues()
.get(collectionCaptor.getAllValues().size() - 1);
assertThat(lastResolvedParams.region()).isEqualTo(Region.US_EAST_1);
assertThat(lastResolvedParams.useGlobalEndpoint()).isFalse();

}

Expand Down Expand Up @@ -529,7 +530,9 @@ private static final class CaptureInterceptor implements ExecutionInterceptor {

@Override
public void beforeMarshalling(Context.BeforeMarshalling context, ExecutionAttributes executionAttributes) {
endpointProvider = executionAttributes.getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER);
if (!(context.request() instanceof HeadBucketRequest)) {
endpointProvider = executionAttributes.getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import software.amazon.awssdk.services.s3.endpoints.internal.DefaultS3EndpointProvider;
import software.amazon.awssdk.services.s3.internal.crossregion.endpointprovider.BucketEndpointProvider;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;
Expand Down Expand Up @@ -303,10 +304,10 @@ void given_globalRegion_Client_Updates_region_to_useast1_and_useGlobalEndpointFl
assertThat(captureInterceptor.endpointProvider).isInstanceOf(BucketEndpointProvider.class);
ArgumentCaptor<S3EndpointParams> collectionCaptor = ArgumentCaptor.forClass(S3EndpointParams.class);
verify(mockEndpointProvider, atLeastOnce()).resolveEndpoint(collectionCaptor.capture());
collectionCaptor.getAllValues().forEach(resolvedParams ->{
assertThat(resolvedParams.region()).isEqualTo(Region.US_EAST_1);
assertThat(resolvedParams.useGlobalEndpoint()).isFalse();
});
S3EndpointParams lastResolvedParams = collectionCaptor.getAllValues()
.get(collectionCaptor.getAllValues().size() - 1);
assertThat(lastResolvedParams.region()).isEqualTo(Region.US_EAST_1);
assertThat(lastResolvedParams.useGlobalEndpoint()).isFalse();
}

private static GetObjectRequest.Builder getObjectBuilder() {
Expand Down Expand Up @@ -509,7 +510,9 @@ private static final class CaptureInterceptor implements ExecutionInterceptor {

@Override
public void beforeMarshalling(Context.BeforeMarshalling context, ExecutionAttributes executionAttributes) {
endpointProvider = executionAttributes.getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER);
if (!(context.request() instanceof HeadBucketRequest)) {
endpointProvider = executionAttributes.getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,119 +18,74 @@
import static java.util.Arrays.asList;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.SdkPlugin;
import software.amazon.awssdk.core.SdkServiceClientConfiguration;
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
import software.amazon.awssdk.awscore.AwsExecutionAttribute;
import software.amazon.awssdk.core.ClientEndpointProvider;
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.S3ServiceClientConfiguration;
import software.amazon.awssdk.services.s3.auth.scheme.S3AuthSchemeParams;
import software.amazon.awssdk.services.s3.auth.scheme.S3AuthSchemeProvider;
import software.amazon.awssdk.services.s3.endpoints.S3EndpointParams;
import software.amazon.awssdk.services.s3.endpoints.internal.S3EndpointResolverUtils;
import software.amazon.awssdk.services.s3.model.Delete;
import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest;
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
import software.amazon.awssdk.utils.AttributeMap;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate import


@WireMockTest
class ListOfStringsAuthParamPluginTest {

private static S3AsyncClient s3Client;
private ListOfStringsParamPlugin plugin;

@BeforeEach
public void init(WireMockRuntimeInfo wm) {
plugin = new ListOfStringsParamPlugin();

AwsBasicCredentials credentials = AwsBasicCredentials.create("key", "secret");
s3Client = S3AsyncClient.builder()
.region(Region.US_EAST_1)
.endpointOverride(URI.create(wm.getHttpBaseUrl()))
.addPlugin(plugin)
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.build();
}

@Test
void callingDeleteObjects_requestWithCompleteListOfKey_returnsRightValues() {
s3Client.deleteObjects(r -> r.bucket("test").delete(o -> o.objects(
DeleteObjectsRequest request = DeleteObjectsRequest.builder().bucket("test").delete(d -> d.objects(
ObjectIdentifier.builder().key("x").versionId("1").build(),
ObjectIdentifier.builder().key("y").versionId("2").build()
)));
assertThat(plugin.storedKeys()).isEqualTo(asList("x", "y"));
)).build();
S3EndpointParams params = S3EndpointResolverUtils.ruleParams(request, deleteObjectsAttributes());
assertThat(params.deleteObjectKeys()).isEqualTo(asList("x", "y"));
}

@Test
void callingDeleteObjects_requestWithInCompleteListOfKey_returnsRightValues() {
s3Client.deleteObjects(r -> r.bucket("test").delete(o -> o.objects(
DeleteObjectsRequest request = DeleteObjectsRequest.builder().bucket("test").delete(d -> d.objects(
ObjectIdentifier.builder().versionId("1").build(),
ObjectIdentifier.builder().key("y").versionId("2").build()
)));
assertThat(plugin.storedKeys()).isEqualTo(asList("y"));
)).build();
S3EndpointParams params = S3EndpointResolverUtils.ruleParams(request, deleteObjectsAttributes());
assertThat(params.deleteObjectKeys()).isEqualTo(asList("y"));
}

@Test
void callingDeleteObjects_requestWithNoList_returnsRightValues() {
s3Client.deleteObjects(DeleteObjectsRequest.builder().delete(Delete.builder().build()).build());
assertThat(plugin.storedKeys()).asList().isEmpty();
DeleteObjectsRequest request = DeleteObjectsRequest.builder().delete(Delete.builder().build()).build();
S3EndpointParams params = S3EndpointResolverUtils.ruleParams(request, deleteObjectsAttributes());
assertThat(params.deleteObjectKeys()).asList().isEmpty();
}

@Test
void callingDeleteObjects_requestWithoutEmptyList_returnsRightValues() {
s3Client.deleteObjects(DeleteObjectsRequest.builder().delete(Delete.builder().objects(Collections.emptyList()).build()).build());
assertThat(plugin.storedKeys()).asList().isEmpty();
DeleteObjectsRequest request = DeleteObjectsRequest.builder().delete(Delete.builder().objects(Collections.emptyList()).build()).build();
S3EndpointParams params = S3EndpointResolverUtils.ruleParams(request, deleteObjectsAttributes());
assertThat(params.deleteObjectKeys()).asList().isEmpty();
}

@Test
void callingDeleteObjects_requestWithListButNoKey_returnsRightValues() {
List<ObjectIdentifier> objects = asList(ObjectIdentifier.builder().build());
s3Client.deleteObjects(DeleteObjectsRequest.builder().delete(Delete.builder().objects(objects).build()).build());
assertThat(plugin.storedKeys()).asList().isEmpty();
DeleteObjectsRequest request = DeleteObjectsRequest.builder().delete(Delete.builder().objects(objects).build()).build();
S3EndpointParams params = S3EndpointResolverUtils.ruleParams(request, deleteObjectsAttributes());
assertThat(params.deleteObjectKeys()).asList().isEmpty();
}

private static class ListOfStringsParamPlugin implements SdkPlugin {

private ListOfStringsParamAuthSchemeProvider localProvider;

@Override
public void configureClient(SdkServiceClientConfiguration.Builder config) {
S3ServiceClientConfiguration.Builder serviceClientConfiguration = (S3ServiceClientConfiguration.Builder) config;
S3AuthSchemeProvider defaultProvider = serviceClientConfiguration.authSchemeProvider();
localProvider = new ListOfStringsParamAuthSchemeProvider(defaultProvider);
serviceClientConfiguration.authSchemeProvider(localProvider);
}

List<String> storedKeys() {
return localProvider.storedKeys;
}

private static class ListOfStringsParamAuthSchemeProvider implements S3AuthSchemeProvider {

private List<String> storedKeys;
S3AuthSchemeProvider delegate;

public ListOfStringsParamAuthSchemeProvider(S3AuthSchemeProvider authSchemeProvider) {
this.delegate = authSchemeProvider;
}

@Override
public List<AuthSchemeOption> resolveAuthScheme(S3AuthSchemeParams authSchemeParams) {
List<AuthSchemeOption> availableAuthSchemes = delegate.resolveAuthScheme(authSchemeParams);

List<String> keys = authSchemeParams.deleteObjectKeys();
if (keys != null) {
storedKeys = keys;
}
return availableAuthSchemes;
}
}
private static ExecutionAttributes deleteObjectsAttributes() {
ExecutionAttributes attrs = new ExecutionAttributes();
attrs.putAttribute(SdkExecutionAttribute.OPERATION_NAME, "DeleteObjects");
attrs.putAttribute(AwsExecutionAttribute.AWS_REGION, Region.US_EAST_1);
attrs.putAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER,
ClientEndpointProvider.forEndpointOverride(URI.create("https://s3.us-east-1.amazonaws.com")));
attrs.putAttribute(SdkInternalExecutionAttribute.CLIENT_CONTEXT_PARAMS, AttributeMap.empty());
return attrs;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import software.amazon.awssdk.core.interceptor.Context;
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
import software.amazon.awssdk.endpoints.Endpoint;
import software.amazon.awssdk.http.SdkHttpRequest;

/**
Expand All @@ -25,12 +27,21 @@ public class S3ControlWireMockRerouteInterceptor implements ExecutionInterceptor
public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) {

SdkHttpRequest request = context.httpRequest();
recordedEndpoints.add(request.getUri());
recordedRequests.add(request);

return request.toBuilder().uri(rerouteEndpoint).build();
}

@Override
public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) {
Endpoint resolvedEndpoint = executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT);
if (resolvedEndpoint != null) {
recordedEndpoints.add(resolvedEndpoint.url());
} else {
recordedEndpoints.add(context.httpRequest().getUri());
}
}

public List<SdkHttpRequest> getRecordedRequests() {
return recordedRequests;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private static class ExecutionAttributeInterceptor implements ExecutionIntercept
}

@Override
public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) {
signerDoubleUrlEncode = executionAttributes.getAttribute(AwsSignerExecutionAttribute.SIGNER_DOUBLE_URL_ENCODE);
}

Expand Down
Loading