Skip to content

Commit 488b723

Browse files
committed
Fixes after merge
1 parent 119cfbf commit 488b723

File tree

10 files changed

+129
-106
lines changed

10 files changed

+129
-106
lines changed

.changes/next-release/feature-AWSSDKForJavav2-3b0176a.json

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Add support for payload signing of async streaming requests signed with SigV4 using default `AwsV4HttpSigner` (using `AwsV4HttpSigner.create()`). Note, requests using the `http` URI scheme will not be signed regardless of the value of `AwsV4FamilyHttpSigner.PAYLOAD_SIGNING_ENABLED` to remain consistent with existing behavior. This may change in a future release."
6+
}

core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultAwsV4HttpSigner.java

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ public SignedRequest sign(SignRequest<? extends AwsCredentialsIdentity> request)
6969

7070
@Override
7171
public CompletableFuture<AsyncSignedRequest> signAsync(AsyncSignRequest<? extends AwsCredentialsIdentity> request) {
72-
Checksummer checksummer = checksummer(request, null, checksumStore(request));
72+
Checksummer checksummer = asyncChecksummer(request, checksumStore(request));
7373
V4Properties v4Properties = v4Properties(request);
7474
V4RequestSigner v4RequestSigner = v4RequestSigner(request, v4Properties);
75-
V4PayloadSigner payloadSigner = v4PayloadAsyncSigner(request, v4Properties);
75+
V4PayloadSigner payloadSigner = v4PayloadSigner(request, v4Properties);
7676

7777
return doSignAsync(request, checksummer, v4RequestSigner, payloadSigner);
7878
}
@@ -81,7 +81,7 @@ private static V4Properties v4Properties(BaseSignRequest<?, ? extends AwsCredent
8181
Clock signingClock = request.requireProperty(SIGNING_CLOCK, Clock.systemUTC());
8282
Instant signingInstant = signingClock.instant();
8383
AwsCredentialsIdentity credentials = sanitizeCredentials(request.identity());
84-
String regionName = request.requireProperty(AwsV4HttpSigner.REGION_NAME);
84+
String regionName = request.requireProperty(REGION_NAME);
8585
String serviceSigningName = request.requireProperty(SERVICE_SIGNING_NAME);
8686
CredentialScope credentialScope = new CredentialScope(regionName, serviceSigningName, signingInstant);
8787
boolean doubleUrlEncode = request.requireProperty(DOUBLE_URL_ENCODE, true);
@@ -129,42 +129,22 @@ private static V4RequestSigner v4RequestSigner(
129129
return requestSigner.apply(v4Properties);
130130
}
131131

132-
private static V4PayloadSigner v4PayloadSigner(
133-
SignRequest<? extends AwsCredentialsIdentity> request,
134-
V4Properties properties) {
135-
132+
private static Checksummer asyncChecksummer(BaseSignRequest<?, ? extends AwsCredentialsIdentity> request,
133+
PayloadChecksumStore checksumStore) {
134+
boolean isHttp = !"https".equals(request.request().protocol());
136135
boolean isPayloadSigning = isPayloadSigning(request);
137-
boolean isEventStreaming = isEventStreaming(request.request());
138136
boolean isChunkEncoding = request.requireProperty(CHUNK_ENCODING_ENABLED, false);
139-
boolean isTrailing = request.request().firstMatchingHeader(X_AMZ_TRAILER).isPresent();
140-
boolean isFlexible = request.hasProperty(CHECKSUM_ALGORITHM) && !hasChecksumHeader(request);
137+
boolean shouldTreatAsUnsigned = isHttp && isPayloadSigning && isChunkEncoding;
141138

142-
if (isEventStreaming) {
143-
if (isPayloadSigning) {
144-
return getEventStreamV4PayloadSigner(
145-
properties.getCredentials(),
146-
properties.getCredentialScope(),
147-
properties.getSigningClock()
148-
);
149-
}
150-
throw new UnsupportedOperationException("Unsigned payload is not supported with event-streaming.");
151-
}
152-
153-
if (useChunkEncoding(isPayloadSigning, isChunkEncoding, isTrailing || isFlexible)) {
154-
return AwsChunkedV4PayloadSigner.builder()
155-
.credentialScope(properties.getCredentialScope())
156-
.chunkSize(DEFAULT_CHUNK_SIZE_IN_BYTES)
157-
.checksumStore(checksumStore(request))
158-
.checksumAlgorithm(request.property(CHECKSUM_ALGORITHM))
159-
.build();
160-
}
139+
// set the override to false if it should be treated as unsigned, otherwise, null should be passed so that the normal
140+
// check for payload signing is done.
141+
Boolean overridePayloadSigning = shouldTreatAsUnsigned ? false : null;
161142

162-
return V4PayloadSigner.create();
143+
return checksummer(request, overridePayloadSigning, checksumStore);
163144
}
164145

165-
private static V4PayloadSigner v4PayloadAsyncSigner(
166-
AsyncSignRequest<? extends AwsCredentialsIdentity> request,
167-
V4Properties properties) {
146+
private static V4PayloadSigner v4PayloadSigner(
147+
BaseSignRequest<?, ? extends AwsCredentialsIdentity> request, V4Properties properties) {
168148

169149
boolean isPayloadSigning = isPayloadSigning(request);
170150
boolean isEventStreaming = isEventStreaming(request.request());
@@ -187,6 +167,7 @@ private static V4PayloadSigner v4PayloadAsyncSigner(
187167
return AwsChunkedV4PayloadSigner.builder()
188168
.credentialScope(properties.getCredentialScope())
189169
.chunkSize(DEFAULT_CHUNK_SIZE_IN_BYTES)
170+
.checksumStore(checksumStore(request))
190171
.checksumAlgorithm(request.property(CHECKSUM_ALGORITHM))
191172
.build();
192173
}

core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/TestUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner.SERVICE_SIGNING_NAME;
55
import static software.amazon.awssdk.http.auth.spi.signer.HttpSigner.SIGNING_CLOCK;
66

7+
import io.reactivex.Flowable;
78
import java.io.ByteArrayInputStream;
89
import java.net.URI;
910
import java.nio.ByteBuffer;
@@ -13,6 +14,7 @@
1314
import java.time.ZoneId;
1415
import java.time.ZoneOffset;
1516
import java.util.function.Consumer;
17+
import org.reactivestreams.Publisher;
1618
import software.amazon.awssdk.http.SdkHttpMethod;
1719
import software.amazon.awssdk.http.SdkHttpRequest;
1820
import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest;
@@ -58,10 +60,8 @@ public static <T extends AwsCredentialsIdentity> AsyncSignRequest<T> generateBas
5860
Consumer<? super SdkHttpRequest.Builder> requestOverrides,
5961
Consumer<? super AsyncSignRequest.Builder<T>> signRequestOverrides
6062
) {
61-
SimplePublisher<ByteBuffer> publisher = new SimplePublisher<>();
6263

63-
publisher.send(ByteBuffer.wrap(testPayload()));
64-
publisher.complete();
64+
Publisher<ByteBuffer> publisher = Flowable.just(ByteBuffer.wrap(testPayload()));
6565

6666
return AsyncSignRequest.builder(credentials)
6767
.request(SdkHttpRequest.builder()

core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultAwsV4HttpSignerTest.java

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,21 @@
3030
import static software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner.PAYLOAD_SIGNING_ENABLED;
3131
import static software.amazon.awssdk.http.auth.spi.signer.SdkInternalHttpSignerProperty.CHECKSUM_STORE;
3232

33+
import io.reactivex.Flowable;
3334
import java.io.IOException;
3435
import java.net.URI;
36+
import java.nio.ByteBuffer;
3537
import java.nio.charset.StandardCharsets;
3638
import java.time.Duration;
37-
import java.util.Optional;
39+
import java.util.List;
40+
import java.util.stream.Collectors;
3841
import org.junit.jupiter.api.Disabled;
3942
import org.junit.jupiter.api.Test;
4043
import org.junit.jupiter.params.ParameterizedTest;
4144
import org.junit.jupiter.params.provider.ValueSource;
4245
import org.mockito.MockedStatic;
4346
import org.mockito.Mockito;
47+
import org.reactivestreams.Publisher;
4448
import software.amazon.awssdk.checksums.SdkChecksum;
4549
import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm;
4650
import software.amazon.awssdk.http.Header;
@@ -709,7 +713,9 @@ void sign_WithPayloadSigningTrueAndChunkEncodingTrueAndHttp_SignsPayload() {
709713
}
710714

711715
@Test
712-
void signAsync_WithPayloadSigningTrueAndChunkEncodingTrueAndHttp_IgnoresPayloadSigning() {
716+
@Disabled("Fallback to signing is disabled to match pre-SRA behavior")
717+
// TODO: Enable this test once we figure out what the expected behavior is post SRA. See JAVA-8078
718+
void signAsync_WithPayloadSigningTrueAndChunkEncodingTrueAndHttp_RespectsPayloadSigning() {
713719
AsyncSignRequest<? extends AwsCredentialsIdentity> request = generateBasicAsyncRequest(
714720
AwsCredentialsIdentity.create("access", "secret"),
715721
httpRequest -> httpRequest.uri(URI.create("http://demo.us-east-1.amazonaws.com")),
@@ -727,6 +733,8 @@ void signAsync_WithPayloadSigningTrueAndChunkEncodingTrueAndHttp_IgnoresPayloadS
727733
}
728734

729735
@Test
736+
@Disabled("Fallback to signing is disabled to match pre-SRA behavior")
737+
// TODO: Enable this test once we figure out what the expected behavior is post SRA. See JAVA-8078
730738
void sign_WithPayloadSigningFalseAndChunkEncodingTrueAndHttp_SignsPayload() {
731739
SignRequest<? extends AwsCredentialsIdentity> request = generateBasicRequest(
732740
AwsCredentialsIdentity.create("access", "secret"),
@@ -745,7 +753,9 @@ void sign_WithPayloadSigningFalseAndChunkEncodingTrueAndHttp_SignsPayload() {
745753
}
746754

747755
@Test
748-
void signAsync_WithPayloadSigningFalseAndChunkEncodingTrueAndHttp_DoesNotFallBackToPayloadSigning() {
756+
@Disabled("Fallback to signing is disabled to match pre-SRA behavior")
757+
// TODO: Enable this test once we figure out what the expected behavior is post SRA. See JAVA-8078
758+
void signAsync_WithPayloadSigningFalseAndChunkEncodingTrueAndHttp_FallsBackToPayloadSigning() {
749759
AsyncSignRequest<? extends AwsCredentialsIdentity> request = generateBasicAsyncRequest(
750760
AwsCredentialsIdentity.create("access", "secret"),
751761
httpRequest -> httpRequest.uri(URI.create("http://demo.us-east-1.amazonaws.com")),
@@ -783,7 +793,9 @@ void sign_WithPayloadSigningFalseAndChunkEncodingTrueAndFlexibleChecksumAndHttp_
783793
}
784794

785795
@Test
786-
void signAsync_WithPayloadSigningFalseAndChunkEncodingTrueAndFlexibleChecksumAndHttp_DoesNotFallBackToPayloadSigning() {
796+
@Disabled("Fallback to signing is disabled to match pre-SRA behavior")
797+
// TODO: Enable this test once we figure out what the expected behavior is post SRA. See JAVA-8078
798+
void signAsync_WithPayloadSigningFalseAndChunkEncodingTrueAndFlexibleChecksumAndHttp_FallsBackToPayloadSigning() {
787799
AsyncSignRequest<? extends AwsCredentialsIdentity> request = generateBasicAsyncRequest(
788800
AwsCredentialsIdentity.create("access", "secret"),
789801
httpRequest -> httpRequest.uri(URI.create("http://demo.us-east-1.amazonaws.com")),
@@ -900,9 +912,61 @@ void sign_withPayloadSigningTrue_chunkEncodingFalse_withChecksum_cacheEmpty_stor
900912
assertThat(cache.getChecksumValue(CRC32)).isEqualTo(crc32Value);
901913
}
902914

915+
@Test
916+
void signAsync_WithPayloadSigningFalse_chunkEncodingTrue_cacheEmpty_storesComputedChecksum() throws IOException {
917+
PayloadChecksumStore cache = PayloadChecksumStore.create();
918+
919+
AsyncSignRequest<? extends AwsCredentialsIdentity> request = generateBasicAsyncRequest(
920+
AwsCredentialsIdentity.create("access", "secret"),
921+
httpRequest -> httpRequest.uri(URI.create("http://demo.us-east-1.amazonaws.com")),
922+
signRequest -> signRequest
923+
.putProperty(PAYLOAD_SIGNING_ENABLED, false)
924+
.putProperty(CHUNK_ENCODING_ENABLED, true)
925+
.putProperty(CHECKSUM_ALGORITHM, CRC32)
926+
.putProperty(CHECKSUM_STORE, cache)
927+
);
928+
929+
AsyncSignedRequest signedRequest = signer.signAsync(request).join();
930+
931+
getAllItems(signedRequest.payload().get());
932+
assertThat(cache.getChecksumValue(CRC32)).isEqualTo(computeChecksum(CRC32, testPayload()));
933+
}
934+
935+
@Test
936+
void signAsync_WithPayloadSigningFalse_chunkEncodingTrue_cacheContainsChecksum_usesCachedValue() throws IOException {
937+
PayloadChecksumStore cache = PayloadChecksumStore.create();
938+
939+
byte[] checksumValue = "my-checksum".getBytes(StandardCharsets.UTF_8);
940+
cache.putChecksumValue(CRC32, checksumValue);
941+
942+
AsyncSignRequest<? extends AwsCredentialsIdentity> request = generateBasicAsyncRequest(
943+
AwsCredentialsIdentity.create("access", "secret"),
944+
httpRequest -> httpRequest.uri(URI.create("http://demo.us-east-1.amazonaws.com")),
945+
signRequest -> signRequest
946+
.putProperty(PAYLOAD_SIGNING_ENABLED, false)
947+
.putProperty(CHUNK_ENCODING_ENABLED, true)
948+
.putProperty(CHECKSUM_ALGORITHM, CRC32)
949+
.putProperty(CHECKSUM_STORE, cache)
950+
);
951+
952+
AsyncSignedRequest signedRequest = signer.signAsync(request).join();
953+
954+
List<ByteBuffer> content = getAllItems(signedRequest.payload().get());
955+
String contentAsString = content.stream().map(DefaultAwsV4HttpSignerTest::bufferAsString).collect(Collectors.joining());
956+
assertThat(contentAsString).contains("x-amz-checksum-crc32:" + BinaryUtils.toBase64(checksumValue) + "\r\n");
957+
}
958+
903959
private static byte[] computeChecksum(ChecksumAlgorithm algorithm, byte[] data) {
904960
SdkChecksum checksum = SdkChecksum.forAlgorithm(algorithm);
905961
checksum.update(data, 0, data.length);
906962
return checksum.getChecksumBytes();
907963
}
964+
965+
private List<ByteBuffer> getAllItems(Publisher<ByteBuffer> publisher) {
966+
return Flowable.fromPublisher(publisher).toList().blockingGet();
967+
}
968+
969+
private static String bufferAsString(ByteBuffer buffer) {
970+
return StandardCharsets.UTF_8.decode(buffer.duplicate()).toString();
971+
}
908972
}

0 commit comments

Comments
 (0)