Skip to content

Commit 8dd837d

Browse files
authored
Add a test that the selected auth scheme signing clock will not be overwritten (#4389)
* Add a test that the selected auth scheme signing clock will not be overwritten * Update tests after downstream changes
1 parent b811e88 commit 8dd837d

File tree

2 files changed

+132
-11
lines changed

2 files changed

+132
-11
lines changed

core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStageTest.java

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static software.amazon.awssdk.core.metrics.CoreMetric.SIGNING_DURATION;
3030

3131
import java.nio.ByteBuffer;
32+
import java.time.Clock;
3233
import java.time.Instant;
3334
import java.time.temporal.ChronoUnit;
3435
import java.util.concurrent.CompletableFuture;
@@ -148,9 +149,9 @@ public void execute_selectedAuthScheme_doesSraSign() throws Exception {
148149
verifyNoInteractions(oldSigner);
149150
}
150151

151-
152152
@Test
153153
public void execute_selectedAuthSchemeAndTimeOffsetSet_doesSraSignAndAdjustTheSigningClock() throws Exception {
154+
AsyncRequestBody asyncPayload = AsyncRequestBody.fromString("async request body");
154155
// Set up a scheme with a signer property
155156
SelectedAuthScheme<Identity> selectedAuthScheme = new SelectedAuthScheme<>(
156157
CompletableFuture.completedFuture(identity),
@@ -159,17 +160,19 @@ public void execute_selectedAuthSchemeAndTimeOffsetSet_doesSraSignAndAdjustTheSi
159160
.schemeId("my.auth#myAuth")
160161
.putSignerProperty(SIGNER_PROPERTY, "value")
161162
.build());
162-
RequestExecutionContext context = createContext(selectedAuthScheme, (Signer) null);
163-
164-
// Setup the timeoffset to test that the clock is setup properly.
165-
httpClientDependencies.updateTimeOffset(TEST_TIME_OFFSET);
163+
RequestExecutionContext context = createContext(selectedAuthScheme, asyncPayload, null);
166164

167165
SdkHttpRequest signedRequest = ValidSdkObjects.sdkHttpFullRequest().build();
168-
when(signer.sign(Mockito.<SignRequest<? extends Identity>>any()))
169-
.thenReturn(SignedRequest.builder()
170-
.request(signedRequest)
171-
.build());
166+
Publisher<ByteBuffer> signedPayload = AsyncRequestBody.fromString("signed async request body");
167+
when(signer.signAsync(Mockito.<AsyncSignRequest<? extends Identity>>any()))
168+
.thenReturn(
169+
CompletableFuture.completedFuture(AsyncSignedRequest.builder()
170+
.request(signedRequest)
171+
.payload(signedPayload)
172+
.build()));
172173

174+
// Setup the timeoffset to test that the clock is setup properly.
175+
httpClientDependencies.updateTimeOffset(TEST_TIME_OFFSET);
173176
SdkHttpFullRequest request = ValidSdkObjects.sdkHttpFullRequest().build();
174177
SdkHttpFullRequest result = stage.execute(request, context).join();
175178

@@ -178,8 +181,8 @@ public void execute_selectedAuthSchemeAndTimeOffsetSet_doesSraSignAndAdjustTheSi
178181
assertThat(context.executionContext().interceptorContext().httpRequest()).isSameAs(result);
179182

180183
// assert that the input to the signer is as expected, including that signer properties are set
181-
verify(signer).sign(signRequestCaptor.capture());
182-
SignRequest<? extends Identity> signRequest = signRequestCaptor.getValue();
184+
verify(signer).signAsync(asyncSignRequestCaptor.capture());
185+
AsyncSignRequest<? extends Identity> signRequest = asyncSignRequestCaptor.getValue();
183186
assertThat(signRequest.identity()).isSameAs(identity);
184187
assertThat(signRequest.request()).isSameAs(request);
185188
assertThat(signRequest.property(SIGNER_PROPERTY)).isEqualTo("value");
@@ -196,6 +199,58 @@ public void execute_selectedAuthSchemeAndTimeOffsetSet_doesSraSignAndAdjustTheSi
196199
verifyNoInteractions(oldSigner);
197200
}
198201

202+
@Test
203+
public void execute_selectedAuthScheme_doesSraSignAndDoesNotOverrideAuthSchemeOptionClock() throws Exception {
204+
AsyncRequestBody asyncPayload = AsyncRequestBody.fromString("async request body");
205+
// Set up a scheme with a signer property and the signing clock set
206+
Clock clock = SigningStageTest.testClock();
207+
SelectedAuthScheme<Identity> selectedAuthScheme = new SelectedAuthScheme<>(
208+
CompletableFuture.completedFuture(identity),
209+
signer,
210+
AuthSchemeOption.builder()
211+
.schemeId("my.auth#myAuth")
212+
.putSignerProperty(SIGNER_PROPERTY, "value")
213+
// The auth scheme option includes the signing clock property
214+
.putSignerProperty(HttpSigner.SIGNING_CLOCK, clock)
215+
.build());
216+
217+
RequestExecutionContext context = createContext(selectedAuthScheme, asyncPayload, null);
218+
219+
SdkHttpRequest signedRequest = ValidSdkObjects.sdkHttpFullRequest().build();
220+
when(signer.signAsync(Mockito.<AsyncSignRequest<? extends Identity>>any()))
221+
.thenReturn(
222+
CompletableFuture.completedFuture(AsyncSignedRequest.builder()
223+
.request(signedRequest)
224+
.build()));
225+
226+
SdkHttpFullRequest request = ValidSdkObjects.sdkHttpFullRequest().build();
227+
SdkHttpFullRequest result = stage.execute(request, context).join();
228+
229+
assertThat(result).isSameAs(signedRequest);
230+
// assert that interceptor context is updated with result
231+
assertThat(context.executionContext().interceptorContext().httpRequest()).isSameAs(result);
232+
233+
// assert that the input to the signer is as expected, including that signer properties are set
234+
verify(signer).signAsync(asyncSignRequestCaptor.capture());
235+
AsyncSignRequest<? extends Identity> signRequest = asyncSignRequestCaptor.getValue();
236+
assertThat(signRequest.identity()).isSameAs(identity);
237+
assertThat(signRequest.request()).isSameAs(request);
238+
assertThat(signRequest.property(SIGNER_PROPERTY)).isEqualTo("value");
239+
240+
// Assert that the time offset set was zero
241+
assertThat(signRequest.property(HttpSigner.SIGNING_CLOCK)).isNotNull();
242+
assertThat(signRequest.property(HttpSigner.SIGNING_CLOCK).instant())
243+
.isCloseTo(Instant.now(), within(10, ChronoUnit.MILLIS));
244+
245+
// assert that the signing stage does not override the auth-option provided clock.
246+
assertThat(signRequest.property(HttpSigner.SIGNING_CLOCK)).isSameAs(clock);
247+
248+
// assert that metrics are collected
249+
verify(metricCollector).reportMetric(eq(SIGNING_DURATION), any());
250+
251+
verifyNoInteractions(oldSigner);
252+
}
253+
199254
@Test
200255
public void execute_selectedAuthScheme_asyncRequestBody_doesSraSignAsync() throws Exception {
201256
AsyncRequestBody asyncPayload = AsyncRequestBody.fromString("async request body");

core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/SigningStageTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME;
2828
import static software.amazon.awssdk.core.metrics.CoreMetric.SIGNING_DURATION;
2929

30+
import java.time.Clock;
3031
import java.time.Instant;
32+
import java.time.ZoneId;
3133
import java.time.temporal.ChronoUnit;
3234
import java.util.concurrent.CompletableFuture;
3335
import org.junit.Before;
@@ -183,6 +185,51 @@ public void execute_selectedAuthSchemeAndTimeOffsetSet_doesSraSignAndAdjustTheSi
183185
verifyNoInteractions(oldSigner);
184186
}
185187

188+
@Test
189+
public void execute_selectedAuthScheme_doesSraSignAndDoesNotOverrideAuthSchemeOptionClock() throws Exception {
190+
// Set up a scheme with a signer property and the signing clock set
191+
Clock clock = testClock();
192+
SelectedAuthScheme<Identity> selectedAuthScheme = new SelectedAuthScheme<>(
193+
CompletableFuture.completedFuture(identity),
194+
signer,
195+
AuthSchemeOption.builder()
196+
.schemeId("my.auth#myAuth")
197+
.putSignerProperty(SIGNER_PROPERTY, "value")
198+
// The auth scheme option includes the signing clock property
199+
.putSignerProperty(HttpSigner.SIGNING_CLOCK, clock)
200+
.build());
201+
RequestExecutionContext context = createContext(selectedAuthScheme);
202+
203+
SdkHttpRequest signedRequest = ValidSdkObjects.sdkHttpFullRequest().build();
204+
when(signer.sign(Mockito.<SignRequest<? extends Identity>>any()))
205+
.thenReturn(SignedRequest.builder()
206+
.request(signedRequest)
207+
.build());
208+
209+
SdkHttpFullRequest request = ValidSdkObjects.sdkHttpFullRequest().build();
210+
SdkHttpFullRequest result = stage.execute(request, context);
211+
212+
assertThat(result).isSameAs(signedRequest);
213+
// assert that interceptor context is updated with result
214+
assertThat(context.executionContext().interceptorContext().httpRequest()).isSameAs(result);
215+
216+
// assert that the input to the signer is as expected, including that signer properties are set
217+
verify(signer).sign(signRequestCaptor.capture());
218+
SignRequest<? extends Identity> signRequest = signRequestCaptor.getValue();
219+
assertThat(signRequest.identity()).isSameAs(identity);
220+
assertThat(signRequest.request()).isSameAs(request);
221+
assertThat(signRequest.property(SIGNER_PROPERTY)).isEqualTo("value");
222+
assertThat(signRequest.property(HttpSigner.SIGNING_CLOCK)).isNotNull();
223+
224+
// assert that the signing stage does not override the auth-option provided clock.
225+
assertThat(signRequest.property(HttpSigner.SIGNING_CLOCK)).isSameAs(clock);
226+
227+
// assert that metrics are collected
228+
verify(metricCollector).reportMetric(eq(SIGNING_DURATION), any());
229+
230+
verifyNoInteractions(oldSigner);
231+
}
232+
186233
@Test
187234
public void execute_selectedNoAuthAuthScheme_doesSraSign() throws Exception {
188235
// Set up a scheme with smithy.api#noAuth
@@ -395,4 +442,23 @@ private RequestExecutionContext createContext(SelectedAuthScheme<Identity> selec
395442
context.attemptMetricCollector(metricCollector);
396443
return context;
397444
}
445+
446+
public static Clock testClock() {
447+
return new Clock() {
448+
@Override
449+
public ZoneId getZone() {
450+
throw new UnsupportedOperationException();
451+
}
452+
453+
@Override
454+
public Clock withZone(ZoneId zone) {
455+
throw new UnsupportedOperationException();
456+
}
457+
458+
@Override
459+
public Instant instant() {
460+
return Instant.now();
461+
}
462+
};
463+
}
398464
}

0 commit comments

Comments
 (0)