Skip to content

Commit 78e6636

Browse files
Align auth implementation with SRA (#4198)
## Motivation and Context This PR makes the auth implementation aligned with our design specifications. The code changes in the PR consolidate the previous sub-PRs that have been reviewed already: - #4161 - #4175 - #4182 - #4183 For auth-related types users directly interact with in service config such as `AuthScheme`, `AuthSchemeOption`, we can re-export them in a client SDK upon a customer request. ## Testing - All tests added in the sub-PRs above ## Checklist <!--- If a checkbox below is not applicable, then please DELETE it rather than leaving it unchecked --> - [x] For changes to the smithy-rs codegen or runtime crates, I have created a changelog entry Markdown file in the `.changelog` directory, specifying "client," "server," or both in the `applies_to` key. - [x] For changes to the AWS SDK, generated SDK code, or SDK runtime crates, I have created a changelog entry Markdown file in the `.changelog` directory, specifying "aws-sdk-rust" in the `applies_to` key. ---- _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: AWS SDK Rust Bot <97246200+aws-sdk-rust-ci@users.noreply.github.com>
1 parent a98b5b6 commit 78e6636

File tree

48 files changed

+2222
-564
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2222
-564
lines changed

.changelog/1751334589.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
applies_to:
3+
- aws-sdk-rust
4+
- client
5+
authors:
6+
- ysaito1001
7+
references:
8+
- smithy-rs#4076
9+
- smithy-rs#4198
10+
breaking: false
11+
new_feature: false
12+
bug_fix: false
13+
---
14+
Allows customers to configure the auth schemes and auth scheme resolver. For more information see the GitHub [discussion](https://github.com/smithy-lang/smithy-rs/discussions/4197).

aws/rust-runtime/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
use std::borrow::Cow;
7+
8+
use aws_smithy_runtime_api::{
9+
box_error::BoxError,
10+
client::{
11+
auth::{AuthSchemeId, AuthSchemeOption},
12+
endpoint::{EndpointResolverParams, ResolveEndpoint},
13+
runtime_components::RuntimeComponents,
14+
},
15+
};
16+
use aws_smithy_types::config_bag::ConfigBag;
17+
18+
pub(crate) async fn resolve_endpoint_based_auth_scheme_options<'a>(
19+
modeled_auth_scheme_options: &'a [AuthSchemeOption],
20+
cfg: &'a ConfigBag,
21+
runtime_components: &'a RuntimeComponents,
22+
) -> Result<Vec<AuthSchemeOption>, BoxError> {
23+
let endpoint_params = cfg
24+
.load::<EndpointResolverParams>()
25+
.expect("endpoint resolver params must be set");
26+
27+
tracing::debug!(endpoint_params = ?endpoint_params, "resolving endpoint for auth scheme selection");
28+
29+
let endpoint = runtime_components
30+
.endpoint_resolver()
31+
.resolve_endpoint(endpoint_params)
32+
.await?;
33+
34+
let mut endpoint_auth_scheme_ids = Vec::new();
35+
36+
// Note that we're not constructing the `properties` for `endpoint_auth_schemes` here—only collecting
37+
// auth scheme IDs but not properties. This is because, at this stage, we're only determining which auth schemes will be candidates.
38+
// Any `authSchemes` list properties that influence the signing context will be extracted later
39+
// in `AuthSchemeEndpointConfig`, and passed by the orchestrator to the signer's `sign_http_request` method.
40+
if let Some(aws_smithy_types::Document::Array(endpoint_auth_schemes)) =
41+
endpoint.properties().get("authSchemes")
42+
{
43+
for endpoint_auth_scheme in endpoint_auth_schemes {
44+
let scheme_id_str = endpoint_auth_scheme
45+
.as_object()
46+
.and_then(|object| object.get("name"))
47+
.and_then(aws_smithy_types::Document::as_string);
48+
if let Some(scheme_id_str) = scheme_id_str {
49+
endpoint_auth_scheme_ids
50+
.push(AuthSchemeId::from(Cow::Owned(scheme_id_str.to_owned())));
51+
}
52+
}
53+
}
54+
55+
Ok(merge_auth_scheme_options(
56+
modeled_auth_scheme_options,
57+
endpoint_auth_scheme_ids,
58+
))
59+
}
60+
61+
// Returns a list of merged auth scheme options from `modeled_auth_scheme_options` and `endpoint_auth_scheme_ids`,
62+
// copying properties from the modeled auth scheme options into the endpoint auth scheme options as they are built.
63+
//
64+
// Note: We only extract properties from the modeled auth schemes. Pulling properties from the endpoint auth schemes
65+
// would result in duplication; they would be added here and again in the `extract_operation_config` function during signing.
66+
fn merge_auth_scheme_options(
67+
modeled_auth_scheme_options: &[AuthSchemeOption],
68+
endpoint_auth_scheme_ids: Vec<AuthSchemeId>,
69+
) -> Vec<AuthSchemeOption> {
70+
let (common_auth_scheme_options, model_only_auth_scheme_options): (Vec<_>, Vec<_>) =
71+
modeled_auth_scheme_options
72+
.iter()
73+
.partition(|auth_scheme_option| {
74+
endpoint_auth_scheme_ids.contains(auth_scheme_option.scheme_id())
75+
});
76+
77+
let mut endpoint_auth_scheme_options = endpoint_auth_scheme_ids
78+
.into_iter()
79+
.map(|id| {
80+
let modelded = common_auth_scheme_options
81+
.iter()
82+
.find(|opt| opt.scheme_id() == &id)
83+
.cloned();
84+
let mut builder = AuthSchemeOption::builder().scheme_id(id);
85+
builder.set_properties(modelded.and_then(|m| m.properties()));
86+
builder.build().unwrap()
87+
})
88+
.collect::<Vec<_>>();
89+
90+
endpoint_auth_scheme_options.extend(model_only_auth_scheme_options.into_iter().cloned());
91+
92+
endpoint_auth_scheme_options
93+
}
94+
95+
#[cfg(test)]
96+
mod tests {
97+
use aws_runtime::auth::PayloadSigningOverride;
98+
use aws_smithy_types::config_bag::Layer;
99+
100+
use super::*;
101+
102+
fn into_auth_scheme_ids<const N: usize>(strs: [&'static str; N]) -> Vec<AuthSchemeId> {
103+
strs.into_iter().map(AuthSchemeId::from).collect::<Vec<_>>()
104+
}
105+
106+
fn into_auth_scheme_options<const N: usize>(strs: [&'static str; N]) -> Vec<AuthSchemeOption> {
107+
strs.into_iter()
108+
.map(|s| AuthSchemeOption::from(AuthSchemeId::from(s)))
109+
.collect::<Vec<_>>()
110+
}
111+
112+
#[test]
113+
fn merge_auth_scheme_options_basic() {
114+
let modeled_auth_scheme_options =
115+
into_auth_scheme_options(["schemeA", "schemeX", "schemeB", "schemeY"]);
116+
let endpoint_auth_scheme_ids = into_auth_scheme_ids(["schemeY", "schemeX"]);
117+
let expected = ["schemeY", "schemeX", "schemeA", "schemeB"];
118+
let actual =
119+
merge_auth_scheme_options(&modeled_auth_scheme_options, endpoint_auth_scheme_ids);
120+
assert_eq!(
121+
expected.to_vec(),
122+
actual
123+
.iter()
124+
.map(|opt| opt.scheme_id().inner())
125+
.collect::<Vec<_>>()
126+
);
127+
}
128+
129+
#[test]
130+
fn merge_auth_scheme_options_preserving_modeled_auth_properties() {
131+
let mut modeled_auth_scheme_options =
132+
into_auth_scheme_options(["schemeA", "schemeX", "schemeB"]);
133+
modeled_auth_scheme_options.push(
134+
AuthSchemeOption::builder()
135+
.scheme_id(AuthSchemeId::new("schemeY"))
136+
.properties({
137+
let mut layer = Layer::new("TestAuthSchemeProperties");
138+
layer.store_put(PayloadSigningOverride::unsigned_payload());
139+
layer.freeze()
140+
})
141+
.build()
142+
.unwrap(),
143+
);
144+
let endpoint_auth_scheme_ids = into_auth_scheme_ids(["schemeY", "schemeX"]);
145+
let expected = ["schemeY", "schemeX", "schemeA", "schemeB"];
146+
let actual =
147+
merge_auth_scheme_options(&modeled_auth_scheme_options, endpoint_auth_scheme_ids);
148+
assert_eq!(
149+
expected.to_vec(),
150+
actual
151+
.iter()
152+
.map(|opt| opt.scheme_id().inner())
153+
.collect::<Vec<_>>()
154+
);
155+
let prop = actual.first().unwrap().properties().unwrap();
156+
assert!(matches!(
157+
prop.load::<PayloadSigningOverride>().unwrap(),
158+
PayloadSigningOverride::UnsignedPayload
159+
));
160+
}
161+
162+
#[test]
163+
fn merge_auth_scheme_options_with_empty_endpoint_auth_scheme_options() {
164+
let expected = ["schemeA", "schemeX", "schemeB", "schemeY"];
165+
let modeled_auth_scheme_options = into_auth_scheme_options(expected);
166+
let endpoint_auth_scheme_ids = Vec::new();
167+
let actual =
168+
merge_auth_scheme_options(&modeled_auth_scheme_options, endpoint_auth_scheme_ids);
169+
assert_eq!(
170+
expected.to_vec(),
171+
actual
172+
.iter()
173+
.map(|opt| opt.scheme_id().inner())
174+
.collect::<Vec<_>>()
175+
);
176+
}
177+
178+
#[test]
179+
fn merge_auth_scheme_options_should_also_include_those_only_in_endpoint_auth_scheme_options() {
180+
let modeled_auth_scheme_ids =
181+
into_auth_scheme_options(["schemeA", "schemeX", "schemeB", "schemeY"]);
182+
let endpoint_auth_scheme_ids = into_auth_scheme_ids(["schemeY", "schemeZ"]);
183+
let expected = ["schemeY", "schemeZ", "schemeA", "schemeX", "schemeB"];
184+
let actual = merge_auth_scheme_options(&modeled_auth_scheme_ids, endpoint_auth_scheme_ids);
185+
assert_eq!(
186+
expected.to_vec(),
187+
actual
188+
.iter()
189+
.map(|opt| opt.scheme_id().inner())
190+
.collect::<Vec<_>>()
191+
);
192+
}
193+
}

aws/rust-runtime/aws-inlineable/src/endpoint_auth_plugin.rs

Lines changed: 0 additions & 170 deletions
This file was deleted.

0 commit comments

Comments
 (0)