aws_smithy_runtime/client/auth/
no_auth.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! The [`NoAuthRuntimePlugin`] and supporting code.
7
8use crate::client::identity::no_auth::NoAuthIdentityResolver;
9use aws_smithy_runtime_api::box_error::BoxError;
10use aws_smithy_runtime_api::client::auth::static_resolver::StaticAuthSchemeOptionResolver;
11use aws_smithy_runtime_api::client::auth::{
12    AuthScheme, AuthSchemeEndpointConfig, AuthSchemeId, AuthSchemeOption,
13    AuthSchemeOptionResolverParams, AuthSchemeOptionsFuture, ResolveAuthSchemeOptions,
14    SharedAuthScheme, SharedAuthSchemeOptionResolver, Sign,
15};
16use aws_smithy_runtime_api::client::identity::{Identity, SharedIdentityResolver};
17use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
18use aws_smithy_runtime_api::client::runtime_components::{
19    GetIdentityResolver, RuntimeComponents, RuntimeComponentsBuilder,
20};
21use aws_smithy_runtime_api::client::runtime_plugin::{Order, RuntimePlugin};
22use aws_smithy_runtime_api::shared::IntoShared;
23use aws_smithy_types::config_bag::ConfigBag;
24use std::borrow::Cow;
25
26/// Auth scheme ID for "no auth".
27pub const NO_AUTH_SCHEME_ID: AuthSchemeId = AuthSchemeId::new("noAuth");
28
29/// A [`RuntimePlugin`] that registers a "no auth" identity resolver and auth scheme.
30///
31/// This plugin can be used to disable authentication in certain cases, such as when there is
32/// a Smithy `@optionalAuth` trait.
33///
34/// Note: This plugin does not work out of the box because it does not configure an auth scheme option resolver
35/// that recognizes the `noAuth` scheme.
36#[doc(hidden)]
37#[non_exhaustive]
38#[derive(Debug)]
39#[deprecated(since = "1.9.8", note = "Use `NoAuthRuntimePluginV2` instead")]
40pub struct NoAuthRuntimePlugin(RuntimeComponentsBuilder);
41
42#[allow(deprecated)]
43impl Default for NoAuthRuntimePlugin {
44    fn default() -> Self {
45        Self::new()
46    }
47}
48
49#[allow(deprecated)]
50impl NoAuthRuntimePlugin {
51    /// Creates a new `NoAuthRuntimePlugin`.
52    pub fn new() -> Self {
53        Self(
54            RuntimeComponentsBuilder::new("NoAuthRuntimePlugin")
55                .with_identity_resolver(
56                    NO_AUTH_SCHEME_ID,
57                    SharedIdentityResolver::new(NoAuthIdentityResolver::new()),
58                )
59                .with_auth_scheme(SharedAuthScheme::new(NoAuthScheme::new())),
60        )
61    }
62}
63
64#[allow(deprecated)]
65impl RuntimePlugin for NoAuthRuntimePlugin {
66    fn runtime_components(
67        &self,
68        _: &RuntimeComponentsBuilder,
69    ) -> Cow<'_, RuntimeComponentsBuilder> {
70        Cow::Borrowed(&self.0)
71    }
72}
73
74/// A [`RuntimePlugin`] that registers a "no auth" identity resolver, auth scheme, and auth scheme option resolver.
75///
76/// Ideally, a Smithy model should use `@optionalAuth` or `@auth([])` on operations so that:
77/// - The Smithy runtime supports the no-auth scheme
78/// - The code-generated default auth scheme option resolver includes the no-auth scheme for those operations
79///
80/// When that is not possible, this plugin can be used to achieve the same effect.
81#[derive(Debug)]
82pub struct NoAuthRuntimePluginV2(RuntimeComponentsBuilder);
83
84impl Default for NoAuthRuntimePluginV2 {
85    fn default() -> Self {
86        Self::new()
87    }
88}
89
90impl NoAuthRuntimePluginV2 {
91    /// Creates a new `NoAuthRuntimePluginV2`.
92    pub fn new() -> Self {
93        Self(
94            RuntimeComponentsBuilder::new("NoAuthRuntimePluginV2")
95                .with_identity_resolver(
96                    NO_AUTH_SCHEME_ID,
97                    SharedIdentityResolver::new(NoAuthIdentityResolver::new()),
98                )
99                .with_auth_scheme(SharedAuthScheme::new(NoAuthScheme::new())),
100        )
101    }
102}
103
104impl RuntimePlugin for NoAuthRuntimePluginV2 {
105    fn order(&self) -> Order {
106        // This plugin should be applied as an escape hatch to append the no-auth scheme, hence `NestedComponents`.
107        Order::NestedComponents
108    }
109
110    fn runtime_components(
111        &self,
112        current_components: &RuntimeComponentsBuilder,
113    ) -> Cow<'_, RuntimeComponentsBuilder> {
114        // No auth scheme option resolver is configured here because it needs to access
115        // the existing resolver (likely the code-generated default) stored in the
116        // current runtime components builder.
117        let auth_scheme_option_resolver: SharedAuthSchemeOptionResolver =
118            match current_components.auth_scheme_option_resolver() {
119                Some(current_resolver) => {
120                    NoAuthSchemeOptionResolver::new(current_resolver.clone()).into_shared()
121                }
122                None => StaticAuthSchemeOptionResolver::new(vec![NO_AUTH_SCHEME_ID]).into_shared(),
123            };
124        Cow::Owned(
125            self.0
126                .clone()
127                .with_auth_scheme_option_resolver(Some(auth_scheme_option_resolver)),
128        )
129    }
130}
131
132#[derive(Debug)]
133struct NoAuthSchemeOptionResolver<R> {
134    inner: R,
135}
136
137impl<R> NoAuthSchemeOptionResolver<R> {
138    fn new(inner: R) -> Self {
139        Self { inner }
140    }
141}
142
143impl<R> ResolveAuthSchemeOptions for NoAuthSchemeOptionResolver<R>
144where
145    R: ResolveAuthSchemeOptions,
146{
147    fn resolve_auth_scheme_options_v2<'a>(
148        &'a self,
149        params: &'a AuthSchemeOptionResolverParams,
150        cfg: &'a ConfigBag,
151        runtime_components: &'a RuntimeComponents,
152    ) -> AuthSchemeOptionsFuture<'a> {
153        let inner_future =
154            self.inner
155                .resolve_auth_scheme_options_v2(params, cfg, runtime_components);
156
157        AuthSchemeOptionsFuture::new(async move {
158            let mut options = inner_future.await?;
159            options.push(AuthSchemeOption::from(NO_AUTH_SCHEME_ID));
160            Ok(options)
161        })
162    }
163}
164
165/// The "no auth" auth scheme.
166///
167/// The orchestrator requires an auth scheme, so Smithy's `@optionalAuth` trait is implemented
168/// by placing a "no auth" auth scheme at the end of the auth scheme options list so that it is
169/// used if there's no identity resolver available for the other auth schemes. It's also used
170/// for models that don't have auth at all.
171#[derive(Debug, Default)]
172pub struct NoAuthScheme {
173    signer: NoAuthSigner,
174}
175
176impl NoAuthScheme {
177    /// Creates a new `NoAuthScheme`.
178    pub fn new() -> Self {
179        Self::default()
180    }
181}
182
183#[derive(Debug, Default)]
184struct NoAuthSigner;
185
186impl Sign for NoAuthSigner {
187    fn sign_http_request(
188        &self,
189        _request: &mut HttpRequest,
190        _identity: &Identity,
191        _auth_scheme_endpoint_config: AuthSchemeEndpointConfig<'_>,
192        _runtime_components: &RuntimeComponents,
193        _config_bag: &ConfigBag,
194    ) -> Result<(), BoxError> {
195        Ok(())
196    }
197}
198
199impl AuthScheme for NoAuthScheme {
200    fn scheme_id(&self) -> AuthSchemeId {
201        NO_AUTH_SCHEME_ID
202    }
203
204    fn identity_resolver(
205        &self,
206        identity_resolvers: &dyn GetIdentityResolver,
207    ) -> Option<SharedIdentityResolver> {
208        identity_resolvers.identity_resolver(NO_AUTH_SCHEME_ID)
209    }
210
211    fn signer(&self) -> &dyn Sign {
212        &self.signer
213    }
214}