Skip to content

Commit d7d3892

Browse files
authored
If authType=none don't use the old signer, even if overridden (#4523)
* Add authType=none tests to AwsExecutionContentBuilderTest Some of these tests are failing. Will fix them in next commit * If authType=none don't use the old signer, even if overridden * Update signing stage logic for authType=none * Add asserts on identity resolution for authType=none
1 parent b3b383f commit d7d3892

File tree

7 files changed

+275
-85
lines changed

7 files changed

+275
-85
lines changed

core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import software.amazon.awssdk.core.RequestOverrideConfiguration;
3232
import software.amazon.awssdk.core.SdkRequest;
3333
import software.amazon.awssdk.core.SdkResponse;
34+
import software.amazon.awssdk.core.SelectedAuthScheme;
3435
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
3536
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
3637
import software.amazon.awssdk.core.client.config.SdkClientOption;
@@ -45,6 +46,7 @@
4546
import software.amazon.awssdk.core.internal.util.HttpChecksumResolver;
4647
import software.amazon.awssdk.core.signer.Signer;
4748
import software.amazon.awssdk.endpoints.EndpointProvider;
49+
import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
4850
import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
4951
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
5052
import software.amazon.awssdk.identity.spi.IdentityProviders;
@@ -152,10 +154,28 @@ private AwsExecutionContextBuilder() {
152154
/**
153155
* We will load the old (non-SRA) signer if this client seems like an old version or the customer has provided a signer
154156
* override. We assume that if there's no auth schemes defined, we're on the old code path.
157+
* <p>
158+
* In addition, if authType=none, we don't need to use the old signer, even if overridden.
155159
*/
156160
private static boolean loadOldSigner(ExecutionAttributes attributes, SdkRequest request) {
157-
return attributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES) == null ||
158-
SignerOverrideUtils.isSignerOverridden(request, attributes);
161+
Map<String, AuthScheme<?>> authSchemes = attributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES);
162+
if (authSchemes == null) {
163+
// pre SRA case.
164+
// We used to set IS_NONE_AUTH_TYPE_REQUEST = false when authType=none. Yes, false.
165+
return attributes.getOptionalAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST).orElse(true);
166+
}
167+
168+
// post SRA case.
169+
// By default, SRA uses new HttpSigner, so we shouldn't use old non-SRA Signer, unless the customer has provided a signer
170+
// override.
171+
// But, if the operation was modeled as authTpye=None, we don't want to use the provided overridden Signer either. In
172+
// post SRA, modeled authType=None would default to NoAuthAuthScheme.
173+
// Note, for authType=None operation, technically, customer could override the AuthSchemeProvider and select a different
174+
// AuthScheme (than NoAuthAuthScheme). In this case, we are choosing to use the customer's overridden Signer.
175+
SelectedAuthScheme<?> selectedAuthScheme = attributes.getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME);
176+
return SignerOverrideUtils.isSignerOverridden(request, attributes) &&
177+
selectedAuthScheme != null &&
178+
!NoAuthAuthScheme.SCHEME_ID.equals(selectedAuthScheme.authSchemeOption().schemeId());
159179
}
160180

161181
private static void putAuthSchemeResolutionAttributes(ExecutionAttributes executionAttributes,

core/aws-core/src/test/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilderTest.java

Lines changed: 181 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,29 @@
1717

1818
import static org.assertj.core.api.Assertions.assertThat;
1919
import static org.mockito.ArgumentMatchers.any;
20+
import static org.mockito.Mockito.mock;
2021
import static org.mockito.Mockito.times;
2122
import static org.mockito.Mockito.verify;
2223
import static org.mockito.Mockito.when;
2324

24-
import java.util.ArrayList;
2525
import java.util.Collections;
2626
import java.util.List;
27+
import java.util.Map;
2728
import java.util.Optional;
29+
import java.util.concurrent.CompletableFuture;
2830
import java.util.function.Supplier;
2931
import org.junit.Before;
3032
import org.junit.Test;
3133
import org.junit.runner.RunWith;
3234
import org.mockito.Mock;
3335
import org.mockito.junit.MockitoJUnitRunner;
3436
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
35-
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
3637
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
3738
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
3839
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
3940
import software.amazon.awssdk.core.SdkRequest;
4041
import software.amazon.awssdk.core.SdkResponse;
42+
import software.amazon.awssdk.core.SelectedAuthScheme;
4143
import software.amazon.awssdk.core.checksums.ChecksumSpecs;
4244
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
4345
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
@@ -51,6 +53,11 @@
5153
import software.amazon.awssdk.core.interceptor.trait.HttpChecksum;
5254
import software.amazon.awssdk.core.internal.util.HttpChecksumUtils;
5355
import software.amazon.awssdk.core.signer.Signer;
56+
import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
57+
import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
58+
import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
59+
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
60+
import software.amazon.awssdk.http.auth.spi.signer.HttpSigner;
5461
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
5562
import software.amazon.awssdk.identity.spi.IdentityProvider;
5663
import software.amazon.awssdk.identity.spi.IdentityProviders;
@@ -65,16 +72,25 @@ public class AwsExecutionContextBuilderTest {
6572
@Mock
6673
ExecutionInterceptor interceptor;
6774

75+
@Mock
76+
IdentityProvider<AwsCredentialsIdentity> defaultCredentialsProvider;
77+
6878
@Mock
6979
Signer defaultSigner;
7080

7181
@Mock
7282
Signer clientOverrideSigner;
7383

84+
@Mock
85+
Map<String, AuthScheme<?>> defaultAuthSchemes;
86+
7487
@Before
7588
public void setUp() throws Exception {
7689
when(sdkRequest.overrideConfiguration()).thenReturn(Optional.empty());
7790
when(interceptor.modifyRequest(any(), any())).thenReturn(sdkRequest);
91+
when(defaultCredentialsProvider.resolveIdentity()).thenAnswer(
92+
invocationOnMock -> CompletableFuture.completedFuture(AwsCredentialsIdentity.create("ak", "sk")));
93+
7894
}
7995

8096
@Test
@@ -109,17 +125,45 @@ public void verifyCoreExecutionAttributesTakePrecedence() {
109125
assertThat(executionContext.executionAttributes().getAttribute(SdkExecutionAttribute.SERVICE_NAME)).isEqualTo("DoNotOverrideService");
110126
}
111127

128+
// pre SRA, AuthorizationStrategy would setup the signer and resolve identity.
112129
@Test
113-
public void signing_ifNoOverrides_assignDefaultSigner() {
130+
public void preSra_signing_ifNoOverrides_assignDefaultSigner_resolveIdentity() {
114131
ExecutionContext executionContext =
115132
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
116-
testClientConfiguration().build());
133+
preSraClientConfiguration().build());
117134

118135
assertThat(executionContext.signer()).isEqualTo(defaultSigner);
136+
verify(defaultCredentialsProvider, times(1)).resolveIdentity();
119137
}
120138

139+
// This is post SRA case. This is asserting that AuthorizationStrategy is not used.
121140
@Test
122-
public void signing_ifClientOverride_assignClientOverrideSigner() {
141+
public void postSra_ifNoOverrides_doesNotResolveIdentity_doesNotAssignSigner() {
142+
ExecutionContext executionContext =
143+
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
144+
testClientConfiguration().build());
145+
146+
assertThat(executionContext.signer()).isNull();
147+
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
148+
}
149+
150+
@Test
151+
public void preSra_signing_ifClientOverride_assignClientOverrideSigner_resolveIdentity() {
152+
Optional overrideConfiguration = Optional.of(AwsRequestOverrideConfiguration.builder()
153+
.signer(clientOverrideSigner)
154+
.build());
155+
when(sdkRequest.overrideConfiguration()).thenReturn(overrideConfiguration);
156+
157+
ExecutionContext executionContext =
158+
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
159+
preSraClientConfiguration().build());
160+
161+
assertThat(executionContext.signer()).isEqualTo(clientOverrideSigner);
162+
verify(defaultCredentialsProvider, times(1)).resolveIdentity();
163+
}
164+
165+
@Test
166+
public void postSra_signing_ifClientOverride_assignClientOverrideSigner_resolveIdentity() {
123167
Optional overrideConfiguration = Optional.of(AwsRequestOverrideConfiguration.builder()
124168
.signer(clientOverrideSigner)
125169
.build());
@@ -130,6 +174,102 @@ public void signing_ifClientOverride_assignClientOverrideSigner() {
130174
testClientConfiguration().build());
131175

132176
assertThat(executionContext.signer()).isEqualTo(clientOverrideSigner);
177+
verify(defaultCredentialsProvider, times(1)).resolveIdentity();
178+
}
179+
180+
@Test
181+
public void preSra_authTypeNone_doesNotAssignSigner_doesNotResolveIdentity() {
182+
SdkClientConfiguration.Builder clientConfig = preSraClientConfiguration();
183+
clientConfig.option(SdkClientOption.EXECUTION_ATTRIBUTES)
184+
// yes, our code would put false instead of true
185+
.putAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false);
186+
187+
ExecutionContext executionContext =
188+
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
189+
clientConfig.build());
190+
191+
assertThat(executionContext.signer()).isNull();
192+
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
193+
}
194+
195+
@Test
196+
public void postSra_authTypeNone_doesNotAssignSigner_doesNotResolveIdentity() {
197+
SdkClientConfiguration.Builder clientConfig = noAuthAuthSchemeClientConfiguration();
198+
199+
ExecutionContext executionContext =
200+
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
201+
clientConfig.build());
202+
203+
assertThat(executionContext.signer()).isNull();
204+
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
205+
}
206+
207+
@Test
208+
public void preSra_authTypeNone_signerClientOverride_doesNotAssignSigner_doesNotResolveIdentity() {
209+
SdkClientConfiguration.Builder clientConfig = preSraClientConfiguration();
210+
clientConfig.option(SdkClientOption.EXECUTION_ATTRIBUTES)
211+
// yes, our code would put false instead of true
212+
.putAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false);
213+
clientConfig.option(SdkAdvancedClientOption.SIGNER, this.clientOverrideSigner)
214+
.option(SdkClientOption.SIGNER_OVERRIDDEN, true);
215+
216+
ExecutionContext executionContext =
217+
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
218+
clientConfig.build());
219+
220+
assertThat(executionContext.signer()).isNull();
221+
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
222+
}
223+
224+
@Test
225+
public void postSra_authTypeNone_signerClientOverride_doesNotAssignSigner_doesNotResolveIdentity() {
226+
SdkClientConfiguration.Builder clientConfig = noAuthAuthSchemeClientConfiguration();
227+
clientConfig.option(SdkAdvancedClientOption.SIGNER, this.clientOverrideSigner)
228+
.option(SdkClientOption.SIGNER_OVERRIDDEN, true);
229+
230+
ExecutionContext executionContext =
231+
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
232+
clientConfig.build());
233+
234+
assertThat(executionContext.signer()).isNull();
235+
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
236+
}
237+
238+
@Test
239+
public void preSra_authTypeNone_signerRequestOverride_doesNotAssignSigner_doesNotResolveIdentity() {
240+
SdkClientConfiguration.Builder clientConfig = preSraClientConfiguration();
241+
clientConfig.option(SdkClientOption.EXECUTION_ATTRIBUTES)
242+
// yes, our code would put false instead of true
243+
.putAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false);
244+
245+
Optional overrideConfiguration = Optional.of(AwsRequestOverrideConfiguration.builder()
246+
.signer(clientOverrideSigner)
247+
.build());
248+
when(sdkRequest.overrideConfiguration()).thenReturn(overrideConfiguration);
249+
250+
ExecutionContext executionContext =
251+
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
252+
clientConfig.build());
253+
254+
assertThat(executionContext.signer()).isNull();
255+
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
256+
}
257+
258+
@Test
259+
public void postSra_authTypeNone_signerRequestOverride_doesNotAssignSigner_doesNotResolveIdentity() {
260+
SdkClientConfiguration.Builder clientConfig = noAuthAuthSchemeClientConfiguration();
261+
262+
Optional overrideConfiguration = Optional.of(AwsRequestOverrideConfiguration.builder()
263+
.signer(clientOverrideSigner)
264+
.build());
265+
when(sdkRequest.overrideConfiguration()).thenReturn(overrideConfiguration);
266+
267+
ExecutionContext executionContext =
268+
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
269+
clientConfig.build());
270+
271+
assertThat(executionContext.signer()).isNull();
272+
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
133273
}
134274

135275
@Test
@@ -255,11 +395,44 @@ private ClientExecutionParams<SdkRequest, SdkResponse> clientExecutionParams() {
255395
}
256396

257397
private SdkClientConfiguration.Builder testClientConfiguration() {
398+
// In real SRA case, SelectedAuthScheme is setup as an executionAttribute by {Service}AuthSchemeInterceptor that is setup
399+
// in EXECUTION_INTERCEPTORS. But, faking it here for unit test, by already setting SELECTED_AUTH_SCHEME into the
400+
// executionAttributes.
401+
SelectedAuthScheme<?> selectedAuthScheme = new SelectedAuthScheme<>(
402+
CompletableFuture.completedFuture(AwsCredentialsIdentity.create("ak", "sk")),
403+
mock(HttpSigner.class),
404+
AuthSchemeOption.builder().schemeId(AwsV4AuthScheme.SCHEME_ID).build()
405+
);
406+
ExecutionAttributes executionAttributes =
407+
ExecutionAttributes.builder()
408+
.put(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, selectedAuthScheme)
409+
.build();
410+
258411
List<ExecutionInterceptor> interceptorList = Collections.singletonList(interceptor);
259412
return SdkClientConfiguration.builder()
260-
.option(SdkClientOption.EXECUTION_INTERCEPTORS, new ArrayList<>())
261413
.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptorList)
262-
.option(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER, DefaultCredentialsProvider.create())
263-
.option(SdkAdvancedClientOption.SIGNER, this.defaultSigner);
414+
.option(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER, defaultCredentialsProvider)
415+
.option(SdkClientOption.AUTH_SCHEMES, defaultAuthSchemes)
416+
.option(SdkClientOption.EXECUTION_ATTRIBUTES, executionAttributes);
417+
}
418+
419+
private SdkClientConfiguration.Builder noAuthAuthSchemeClientConfiguration() {
420+
SdkClientConfiguration.Builder clientConfig = testClientConfiguration();
421+
SelectedAuthScheme<?> selectedNoAuthScheme = new SelectedAuthScheme<>(
422+
CompletableFuture.completedFuture(AwsCredentialsIdentity.create("ak", "sk")),
423+
mock(HttpSigner.class),
424+
AuthSchemeOption.builder().schemeId(NoAuthAuthScheme.SCHEME_ID).build()
425+
);
426+
clientConfig.option(SdkClientOption.EXECUTION_ATTRIBUTES)
427+
.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, selectedNoAuthScheme);
428+
return clientConfig;
429+
}
430+
431+
private SdkClientConfiguration.Builder preSraClientConfiguration() {
432+
SdkClientConfiguration.Builder clientConfiguration = testClientConfiguration();
433+
clientConfiguration.option(SdkClientOption.EXECUTION_ATTRIBUTES)
434+
.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, null);
435+
return clientConfiguration.option(SdkClientOption.AUTH_SCHEMES, null)
436+
.option(SdkAdvancedClientOption.SIGNER, this.defaultSigner);
264437
}
265438
}

0 commit comments

Comments
 (0)