diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java index 254169ea84c..7fb66d4a542 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java @@ -31,6 +31,7 @@ import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute; import software.amazon.awssdk.awscore.AwsExecutionAttribute; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.internal.authcontext.AuthorizationStrategy; import software.amazon.awssdk.awscore.internal.authcontext.AuthorizationStrategyFactory; @@ -307,7 +308,7 @@ private static void putAuthSchemeResolutionAttributes(ExecutionAttributes execut // request preferred over client. Map> authSchemes = clientConfig.option(SdkClientOption.AUTH_SCHEMES); - IdentityProviders identityProviders = clientConfig.option(SdkClientOption.IDENTITY_PROVIDERS); + IdentityProviders identityProviders = resolveIdentityProviders(originalRequest, clientConfig); executionAttributes .putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER, authSchemeProvider) @@ -315,6 +316,28 @@ private static void putAuthSchemeResolutionAttributes(ExecutionAttributes execut .putAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS, identityProviders); } + private static IdentityProviders resolveIdentityProviders(SdkRequest originalRequest, + SdkClientConfiguration clientConfig) { + IdentityProviders identityProviders = clientConfig.option(SdkClientOption.IDENTITY_PROVIDERS); + + // identityProviders can be null, for new core with old client. In this case, even if AwsRequestOverrideConfiguration + // has credentialsIdentityProvider set (because it is in new core), it is ok to not setup IDENTITY_PROVIDERS, as old + // client won't have AUTH_SCHEME_PROVIDER/AUTH_SCHEMES set either, which are also needed for SRA logic. + if (identityProviders == null) { + return null; + } + + return originalRequest + .overrideConfiguration() + .filter(c -> c instanceof AwsRequestOverrideConfiguration) + .map(c -> (AwsRequestOverrideConfiguration) c) + .map(c -> identityProviders.copy(b -> { + c.credentialsIdentityProvider().ifPresent(b::putIdentityProvider); + c.tokenIdentityProvider().ifPresent(b::putIdentityProvider); + })) + .orElse(identityProviders); + } + /** * Finalize {@link SdkRequest} by running beforeExecution and modifyRequest interceptors. * diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilderTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilderTest.java index bbd3358059a..04f546f0c8c 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilderTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilderTest.java @@ -581,6 +581,45 @@ public void invokeInterceptorsAndCreateExecutionContext_noAuthSchemeProviderRequ assertThat(actualProvider).isSameAs(clientAuthSchemeProvider); } + /** + * Per-request credential override via AwsRequestOverrideConfiguration.credentialsProvider() must be + * reflected in IDENTITY_PROVIDERS even when AUTH_SCHEME_OPTIONS_RESOLVER is not set (old service client). + */ + @Test + public void postSra_requestCredentialOverride_withoutAuthSchemeOptionsResolver_identityProvidersHasOverride() { + IdentityProvider requestCredsProvider = + StaticCredentialsProvider.create(AwsBasicCredentials.create("request-akid", "request-skid")); + + SdkRequest request = NoopTestAwsRequest.builder() + .overrideConfiguration(AwsRequestOverrideConfiguration.builder() + .credentialsProvider(requestCredsProvider) + .build()) + .build(); + + IdentityProviders clientIdentityProviders = IdentityProviders.builder() + .putIdentityProvider(defaultCredentialsProvider) + .build(); + + SdkClientConfiguration clientConfig = testClientConfiguration() + .option(SdkClientOption.IDENTITY_PROVIDERS, clientIdentityProviders) + .option(SdkClientOption.EXECUTION_INTERCEPTORS, Collections.emptyList()) + .build(); + + // No AUTH_SCHEME_OPTIONS_RESOLVER set — simulates old service client + ClientExecutionParams executionParams = clientExecutionParams(request); + + ExecutionContext executionContext = + AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext(executionParams, clientConfig); + + IdentityProviders resolvedProviders = + executionContext.executionAttributes().getAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS); + + // The per-request credential override must be reflected in IDENTITY_PROVIDERS + IdentityProvider resolvedCredProvider = + resolvedProviders.identityProvider(AwsCredentialsIdentity.class); + assertThat(resolvedCredProvider).isSameAs(requestCredsProvider); + } + private ClientExecutionParams clientExecutionParams() { return clientExecutionParams(sdkRequest); }