Skip to content

Commit 40aaa1e

Browse files
ysaito1001jdisanti
andauthored
Ensure identity resolver exists when a credentials provider is given only at operation level (#3021)
## Motivation and Context Fixes awslabs/aws-sdk-rust#901 ## Description When a credentials provider is specified _only_ at the operation level (but not at the service config level), the code in the above PR fails on request dispatch, saying `NoMatchingAuthScheme`. This occurs today because if we [do not set a credentials provider at the service config level](https://github.com/awslabs/aws-sdk-rust/blob/main/sdk/kms/src/config.rs#L757-L769), we will [not set the identity resolver for sigv4](https://github.com/awslabs/aws-sdk-rust/blob/main/sdk/kms/src/config.rs#L811-L818). The same goes for configuring a `SigningRegion` when it is only supplied at the operation level. This PR fixes the said issue so that `config_override` sets - the identity resolver for sigv4 when a credentials provider is supplied only at the operation config level - a `SigningRegion` when a `Region` is given only at the operation level ## Testing Added a Kotlin integ test `test_specifying_credentials_provider_only_at_operation_level_should_work` based on the customer reported PR. ## Checklist - [x] I have updated `CHANGELOG.next.toml` if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._ --------- Co-authored-by: John DiSanti <[email protected]>
1 parent cd09fd2 commit 40aaa1e

File tree

4 files changed

+69
-57
lines changed

4 files changed

+69
-57
lines changed

CHANGELOG.next.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,9 @@ message = "Fix code generation for union members with the `@httpPayload` trait."
4646
references = ["smithy-rs#2969", "smithy-rs#1896"]
4747
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "all" }
4848
author = "jdisanti"
49+
50+
[[aws-sdk-rust]]
51+
message = "Fix exclusively setting the credentials provider and/or region at operation config-override time. It's now possible to set the region or credentials when an operation is sent (via `.config_override()`), rather than at client-creation time."
52+
references = ["smithy-rs#3021", "aws-sdk-rust#901"]
53+
meta = { "breaking" = false, "tada" = false, "bug" = true }
54+
author = "ysaito1001"

aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/CredentialCaches.kt

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,17 @@ class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustom
5757
private val codegenScope = arrayOf(
5858
*preludeScope,
5959
"CredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("cache::CredentialsCache"),
60+
"CredentialsIdentityResolver" to AwsRuntimeType.awsRuntime(runtimeConfig)
61+
.resolve("identity::credentials::CredentialsIdentityResolver"),
6062
"DefaultProvider" to defaultProvider(),
63+
"SIGV4_SCHEME_ID" to AwsRuntimeType.awsRuntime(runtimeConfig).resolve("auth::sigv4::SCHEME_ID"),
6164
"SharedAsyncSleep" to RuntimeType.smithyAsync(runtimeConfig).resolve("rt::sleep::SharedAsyncSleep"),
62-
"SharedCredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("cache::SharedCredentialsCache"),
63-
"SharedCredentialsProvider" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("provider::SharedCredentialsProvider"),
65+
"SharedCredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig)
66+
.resolve("cache::SharedCredentialsCache"),
67+
"SharedCredentialsProvider" to AwsRuntimeType.awsCredentialTypes(runtimeConfig)
68+
.resolve("provider::SharedCredentialsProvider"),
69+
"SharedIdentityResolver" to RuntimeType.smithyRuntimeApi(runtimeConfig)
70+
.resolve("client::identity::SharedIdentityResolver"),
6471
)
6572

6673
override fun section(section: ServiceConfig) = writable {
@@ -209,7 +216,13 @@ class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustom
209216
#{Some}(credentials_cache),
210217
#{Some}(credentials_provider),
211218
) => {
212-
resolver.config_mut().store_put(credentials_cache.create_cache(credentials_provider));
219+
let credentials_cache = credentials_cache.create_cache(credentials_provider);
220+
resolver.runtime_components_mut().push_identity_resolver(
221+
#{SIGV4_SCHEME_ID},
222+
#{SharedIdentityResolver}::new(
223+
#{CredentialsIdentityResolver}::new(credentials_cache),
224+
),
225+
);
213226
}
214227
}
215228
""",

aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SigV4SigningDecorator.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ class SigV4SigningConfig(
120120
)
121121
}
122122
}
123+
is ServiceConfig.OperationConfigOverride -> {
124+
if (runtimeMode.generateOrchestrator) {
125+
rustTemplate(
126+
"""
127+
resolver.config_mut()
128+
.load::<#{Region}>()
129+
.cloned()
130+
.map(|r| resolver.config_mut().store_put(#{SigningRegion}::from(r)));
131+
""",
132+
*codegenScope,
133+
)
134+
}
135+
}
123136

124137
else -> emptySection
125138
}

aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/CredentialCacheConfigTest.kt

Lines changed: 34 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ internal class CredentialCacheConfigTest {
1919
namespace com.example
2020
use aws.protocols#awsJson1_0
2121
use aws.api#service
22+
use aws.auth#sigv4
2223
use smithy.rules#endpointRuleSet
2324
2425
@service(sdkId: "Some Value")
2526
@awsJson1_0
27+
@sigv4(name: "dontcare")
28+
@auth([sigv4])
2629
@endpointRuleSet({
2730
"version": "1.0",
2831
"rules": [{
@@ -39,7 +42,6 @@ internal class CredentialCacheConfigTest {
3942
version: "1"
4043
}
4144
42-
@optionalAuth
4345
operation SayHello { input: TestInput }
4446
structure TestInput {
4547
foo: String,
@@ -56,14 +58,11 @@ internal class CredentialCacheConfigTest {
5658
.resolve("Credentials"),
5759
"CredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig)
5860
.resolve("cache::CredentialsCache"),
59-
"ProvideCachedCredentials" to AwsRuntimeType.awsCredentialTypes(runtimeConfig)
60-
.resolve("cache::ProvideCachedCredentials"),
61+
"Region" to AwsRuntimeType.awsTypes(runtimeConfig).resolve("region::Region"),
6162
"RuntimePlugin" to RuntimeType.smithyRuntimeApi(runtimeConfig)
6263
.resolve("client::runtime_plugin::RuntimePlugin"),
6364
"SharedCredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig)
6465
.resolve("cache::SharedCredentialsCache"),
65-
"SharedCredentialsProvider" to AwsRuntimeType.awsCredentialTypes(runtimeConfig)
66-
.resolve("provider::SharedCredentialsProvider"),
6766
)
6867
rustCrate.testModule {
6968
unitTest(
@@ -114,74 +113,55 @@ internal class CredentialCacheConfigTest {
114113
)
115114
}
116115

117-
tokioTest("test_overriding_cache_and_provider_leads_to_shared_credentials_cache_in_layer") {
116+
unitTest("test_not_overriding_cache_and_provider_leads_to_no_shared_credentials_cache_in_layer") {
118117
rustTemplate(
119118
"""
120-
use #{ProvideCachedCredentials};
121119
use #{RuntimePlugin};
122120
123-
let client_config = crate::config::Config::builder()
124-
.credentials_provider(#{Credentials}::for_tests())
125-
.build();
126-
let client_config_layer = client_config.config;
127-
128-
// make sure test credentials are set in the client config level
129-
assert_eq!(#{Credentials}::for_tests(),
130-
client_config_layer
131-
.load::<#{SharedCredentialsCache}>()
132-
.unwrap()
133-
.provide_cached_credentials()
134-
.await
135-
.unwrap()
136-
);
137-
138-
let credentials = #{Credentials}::new(
139-
"test",
140-
"test",
141-
#{None},
142-
#{None},
143-
"test",
144-
);
145-
let config_override = crate::config::Config::builder()
146-
.credentials_cache(#{CredentialsCache}::lazy())
147-
.credentials_provider(credentials.clone());
121+
let client_config = crate::config::Config::builder().build();
122+
let config_override = crate::config::Config::builder();
148123
let sut = crate::config::ConfigOverrideRuntimePlugin::new(
149124
config_override,
150-
client_config_layer,
125+
client_config.config,
151126
&client_config.runtime_components,
152127
);
153128
let sut_layer = sut.config().unwrap();
154-
155-
// make sure `.provide_cached_credentials` returns credentials set through `config_override`
156-
assert_eq!(credentials,
157-
sut_layer
129+
assert!(sut_layer
158130
.load::<#{SharedCredentialsCache}>()
159-
.unwrap()
160-
.provide_cached_credentials()
161-
.await
162-
.unwrap()
163-
);
131+
.is_none());
164132
""",
165133
*codegenScope,
166134
)
167135
}
168136

169-
unitTest("test_not_overriding_cache_and_provider_leads_to_no_shared_credentials_cache_in_layer") {
137+
tokioTest("test_specifying_credentials_provider_only_at_operation_level_should_work") {
138+
// per https://github.com/awslabs/aws-sdk-rust/issues/901
170139
rustTemplate(
171140
"""
172-
use #{RuntimePlugin};
173-
174141
let client_config = crate::config::Config::builder().build();
175-
let config_override = crate::config::Config::builder();
176-
let sut = crate::config::ConfigOverrideRuntimePlugin::new(
177-
config_override,
178-
client_config.config,
179-
&client_config.runtime_components,
142+
let client = crate::client::Client::from_conf(client_config);
143+
144+
let credentials = #{Credentials}::new(
145+
"test",
146+
"test",
147+
#{None},
148+
#{None},
149+
"test",
180150
);
181-
let sut_layer = sut.config().unwrap();
182-
assert!(sut_layer
183-
.load::<#{SharedCredentialsCache}>()
184-
.is_none());
151+
let operation_config_override = crate::config::Config::builder()
152+
.credentials_cache(#{CredentialsCache}::no_caching())
153+
.credentials_provider(credentials.clone())
154+
.region(#{Region}::new("us-west-2"));
155+
156+
let _ = client
157+
.say_hello()
158+
.customize()
159+
.await
160+
.unwrap()
161+
.config_override(operation_config_override)
162+
.send()
163+
.await
164+
.expect("success");
185165
""",
186166
*codegenScope,
187167
)

0 commit comments

Comments
 (0)