Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gosar/sra ia auth type none sra #4530

Closed
Closed
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 @@ -31,6 +31,7 @@
import software.amazon.awssdk.core.RequestOverrideConfiguration;
import software.amazon.awssdk.core.SdkRequest;
import software.amazon.awssdk.core.SdkResponse;
import software.amazon.awssdk.core.SelectedAuthScheme;
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
import software.amazon.awssdk.core.client.config.SdkClientOption;
Expand All @@ -45,6 +46,7 @@
import software.amazon.awssdk.core.internal.util.HttpChecksumResolver;
import software.amazon.awssdk.core.signer.Signer;
import software.amazon.awssdk.endpoints.EndpointProvider;
import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
import software.amazon.awssdk.identity.spi.IdentityProviders;
Expand Down Expand Up @@ -152,10 +154,28 @@ private AwsExecutionContextBuilder() {
/**
* We will load the old (non-SRA) signer if this client seems like an old version or the customer has provided a signer
* override. We assume that if there's no auth schemes defined, we're on the old code path.
* <p>
* In addition, if authType=none, we don't need to use the old signer, even if overridden.
*/
private static boolean loadOldSigner(ExecutionAttributes attributes, SdkRequest request) {
return attributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES) == null ||
SignerOverrideUtils.isSignerOverridden(request, attributes);
Map<String, AuthScheme<?>> authSchemes = attributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES);
if (authSchemes == null) {
// pre SRA case.
// We used to set IS_NONE_AUTH_TYPE_REQUEST = false when authType=none. Yes, false.
return attributes.getOptionalAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST).orElse(true);
}

// post SRA case.
// By default, SRA uses new HttpSigner, so we shouldn't use old non-SRA Signer, unless the customer has provided a signer
// override.
// But, if the operation was modeled as authTpye=None, we don't want to use the provided overridden Signer either. In
// post SRA, modeled authType=None would default to NoAuthAuthScheme.
// Note, for authType=None operation, technically, customer could override the AuthSchemeProvider and select a different
// AuthScheme (than NoAuthAuthScheme). In this case, we are choosing to use the customer's overridden Signer.
SelectedAuthScheme<?> selectedAuthScheme = attributes.getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME);
return SignerOverrideUtils.isSignerOverridden(request, attributes) &&
selectedAuthScheme != null &&
!NoAuthAuthScheme.SCHEME_ID.equals(selectedAuthScheme.authSchemeOption().schemeId());
}

private static void putAuthSchemeResolutionAttributes(ExecutionAttributes executionAttributes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,29 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.core.SdkRequest;
import software.amazon.awssdk.core.SdkResponse;
import software.amazon.awssdk.core.SelectedAuthScheme;
import software.amazon.awssdk.core.checksums.ChecksumSpecs;
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
Expand All @@ -51,6 +53,11 @@
import software.amazon.awssdk.core.interceptor.trait.HttpChecksum;
import software.amazon.awssdk.core.internal.util.HttpChecksumUtils;
import software.amazon.awssdk.core.signer.Signer;
import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
import software.amazon.awssdk.http.auth.spi.signer.HttpSigner;
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
import software.amazon.awssdk.identity.spi.IdentityProvider;
import software.amazon.awssdk.identity.spi.IdentityProviders;
Expand All @@ -65,16 +72,25 @@ public class AwsExecutionContextBuilderTest {
@Mock
ExecutionInterceptor interceptor;

@Mock
IdentityProvider<AwsCredentialsIdentity> defaultCredentialsProvider;

@Mock
Signer defaultSigner;

@Mock
Signer clientOverrideSigner;

@Mock
Map<String, AuthScheme<?>> defaultAuthSchemes;

@Before
public void setUp() throws Exception {
when(sdkRequest.overrideConfiguration()).thenReturn(Optional.empty());
when(interceptor.modifyRequest(any(), any())).thenReturn(sdkRequest);
when(defaultCredentialsProvider.resolveIdentity()).thenAnswer(
invocationOnMock -> CompletableFuture.completedFuture(AwsCredentialsIdentity.create("ak", "sk")));

}

@Test
Expand Down Expand Up @@ -109,17 +125,45 @@ public void verifyCoreExecutionAttributesTakePrecedence() {
assertThat(executionContext.executionAttributes().getAttribute(SdkExecutionAttribute.SERVICE_NAME)).isEqualTo("DoNotOverrideService");
}

// pre SRA, AuthorizationStrategy would setup the signer and resolve identity.
@Test
public void signing_ifNoOverrides_assignDefaultSigner() {
public void preSra_signing_ifNoOverrides_assignDefaultSigner_resolveIdentity() {
ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
testClientConfiguration().build());
preSraClientConfiguration().build());

assertThat(executionContext.signer()).isEqualTo(defaultSigner);
verify(defaultCredentialsProvider, times(1)).resolveIdentity();
}

// This is post SRA case. This is asserting that AuthorizationStrategy is not used.
@Test
public void signing_ifClientOverride_assignClientOverrideSigner() {
public void postSra_ifNoOverrides_doesNotResolveIdentity_doesNotAssignSigner() {
ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
testClientConfiguration().build());

assertThat(executionContext.signer()).isNull();
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
}

@Test
public void preSra_signing_ifClientOverride_assignClientOverrideSigner_resolveIdentity() {
Optional overrideConfiguration = Optional.of(AwsRequestOverrideConfiguration.builder()
.signer(clientOverrideSigner)
.build());
when(sdkRequest.overrideConfiguration()).thenReturn(overrideConfiguration);

ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
preSraClientConfiguration().build());

assertThat(executionContext.signer()).isEqualTo(clientOverrideSigner);
verify(defaultCredentialsProvider, times(1)).resolveIdentity();
}

@Test
public void postSra_signing_ifClientOverride_assignClientOverrideSigner_resolveIdentity() {
Optional overrideConfiguration = Optional.of(AwsRequestOverrideConfiguration.builder()
.signer(clientOverrideSigner)
.build());
Expand All @@ -130,6 +174,102 @@ public void signing_ifClientOverride_assignClientOverrideSigner() {
testClientConfiguration().build());

assertThat(executionContext.signer()).isEqualTo(clientOverrideSigner);
verify(defaultCredentialsProvider, times(1)).resolveIdentity();
}

@Test
public void preSra_authTypeNone_doesNotAssignSigner_doesNotResolveIdentity() {
SdkClientConfiguration.Builder clientConfig = preSraClientConfiguration();
clientConfig.option(SdkClientOption.EXECUTION_ATTRIBUTES)
// yes, our code would put false instead of true
.putAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false);

ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
clientConfig.build());

assertThat(executionContext.signer()).isNull();
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
}

@Test
public void postSra_authTypeNone_doesNotAssignSigner_doesNotResolveIdentity() {
SdkClientConfiguration.Builder clientConfig = noAuthAuthSchemeClientConfiguration();

ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
clientConfig.build());

assertThat(executionContext.signer()).isNull();
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
}

@Test
public void preSra_authTypeNone_signerClientOverride_doesNotAssignSigner_doesNotResolveIdentity() {
SdkClientConfiguration.Builder clientConfig = preSraClientConfiguration();
clientConfig.option(SdkClientOption.EXECUTION_ATTRIBUTES)
// yes, our code would put false instead of true
.putAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false);
clientConfig.option(SdkAdvancedClientOption.SIGNER, this.clientOverrideSigner)
.option(SdkClientOption.SIGNER_OVERRIDDEN, true);

ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
clientConfig.build());

assertThat(executionContext.signer()).isNull();
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
}

@Test
public void postSra_authTypeNone_signerClientOverride_doesNotAssignSigner_doesNotResolveIdentity() {
SdkClientConfiguration.Builder clientConfig = noAuthAuthSchemeClientConfiguration();
clientConfig.option(SdkAdvancedClientOption.SIGNER, this.clientOverrideSigner)
.option(SdkClientOption.SIGNER_OVERRIDDEN, true);

ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
clientConfig.build());

assertThat(executionContext.signer()).isNull();
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
}

@Test
public void preSra_authTypeNone_signerRequestOverride_doesNotAssignSigner_doesNotResolveIdentity() {
SdkClientConfiguration.Builder clientConfig = preSraClientConfiguration();
clientConfig.option(SdkClientOption.EXECUTION_ATTRIBUTES)
// yes, our code would put false instead of true
.putAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false);

Optional overrideConfiguration = Optional.of(AwsRequestOverrideConfiguration.builder()
.signer(clientOverrideSigner)
.build());
when(sdkRequest.overrideConfiguration()).thenReturn(overrideConfiguration);

ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
clientConfig.build());

assertThat(executionContext.signer()).isNull();
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
}

@Test
public void postSra_authTypeNone_signerRequestOverride_doesNotAssignSigner_doesNotResolveIdentity() {
SdkClientConfiguration.Builder clientConfig = noAuthAuthSchemeClientConfiguration();

Optional overrideConfiguration = Optional.of(AwsRequestOverrideConfiguration.builder()
.signer(clientOverrideSigner)
.build());
when(sdkRequest.overrideConfiguration()).thenReturn(overrideConfiguration);

ExecutionContext executionContext =
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(clientExecutionParams(),
clientConfig.build());

assertThat(executionContext.signer()).isNull();
verify(defaultCredentialsProvider, times(0)).resolveIdentity();
}

@Test
Expand Down Expand Up @@ -255,11 +395,44 @@ private ClientExecutionParams<SdkRequest, SdkResponse> clientExecutionParams() {
}

private SdkClientConfiguration.Builder testClientConfiguration() {
// In real SRA case, SelectedAuthScheme is setup as an executionAttribute by {Service}AuthSchemeInterceptor that is setup
// in EXECUTION_INTERCEPTORS. But, faking it here for unit test, by already setting SELECTED_AUTH_SCHEME into the
// executionAttributes.
SelectedAuthScheme<?> selectedAuthScheme = new SelectedAuthScheme<>(
CompletableFuture.completedFuture(AwsCredentialsIdentity.create("ak", "sk")),
mock(HttpSigner.class),
AuthSchemeOption.builder().schemeId(AwsV4AuthScheme.SCHEME_ID).build()
);
ExecutionAttributes executionAttributes =
ExecutionAttributes.builder()
.put(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, selectedAuthScheme)
.build();

List<ExecutionInterceptor> interceptorList = Collections.singletonList(interceptor);
return SdkClientConfiguration.builder()
.option(SdkClientOption.EXECUTION_INTERCEPTORS, new ArrayList<>())
.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptorList)
.option(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER, DefaultCredentialsProvider.create())
.option(SdkAdvancedClientOption.SIGNER, this.defaultSigner);
.option(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER, defaultCredentialsProvider)
.option(SdkClientOption.AUTH_SCHEMES, defaultAuthSchemes)
.option(SdkClientOption.EXECUTION_ATTRIBUTES, executionAttributes);
}

private SdkClientConfiguration.Builder noAuthAuthSchemeClientConfiguration() {
SdkClientConfiguration.Builder clientConfig = testClientConfiguration();
SelectedAuthScheme<?> selectedNoAuthScheme = new SelectedAuthScheme<>(
CompletableFuture.completedFuture(AwsCredentialsIdentity.create("ak", "sk")),
mock(HttpSigner.class),
AuthSchemeOption.builder().schemeId(NoAuthAuthScheme.SCHEME_ID).build()
);
clientConfig.option(SdkClientOption.EXECUTION_ATTRIBUTES)
.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, selectedNoAuthScheme);
return clientConfig;
}

private SdkClientConfiguration.Builder preSraClientConfiguration() {
SdkClientConfiguration.Builder clientConfiguration = testClientConfiguration();
clientConfiguration.option(SdkClientOption.EXECUTION_ATTRIBUTES)
.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, null);
return clientConfiguration.option(SdkClientOption.AUTH_SCHEMES, null)
.option(SdkAdvancedClientOption.SIGNER, this.defaultSigner);
}
}
Loading
Loading