aws_credential_types/provider/
credentials.rs1#![cfg_attr(
20 feature = "hardcoded-credentials",
21 doc = r##"
22See [`Credentials::from_keys`] for an example on how to use static credentials.
23 "##
24)]
25#![cfg_attr(
26 not(feature = "hardcoded-credentials"),
27 doc = r##"
28Enable the `hardcoded-credentials` feature to be able to use `Credentials::from_keys` to
29construct credentials from hardcoded values.
30 "##
31)]
32
33use crate::Credentials;
75use aws_smithy_runtime_api::client::identity::{
76 Identity, IdentityCachePartition, IdentityFuture, ResolveIdentity,
77};
78use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
79use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace};
80use std::sync::Arc;
81
82pub type Result = std::result::Result<Credentials, super::error::CredentialsError>;
84
85pub trait ProvideCredentials: Send + Sync + std::fmt::Debug {
87 fn provide_credentials<'a>(&'a self) -> super::future::ProvideCredentials<'a>
89 where
90 Self: 'a;
91
92 fn fallback_on_interrupt(&self) -> Option<Credentials> {
102 None
103 }
104}
105
106impl ProvideCredentials for Credentials {
107 fn provide_credentials<'a>(&'a self) -> super::future::ProvideCredentials<'a>
108 where
109 Self: 'a,
110 {
111 super::future::ProvideCredentials::ready(Ok(self.clone()))
112 }
113}
114
115impl ProvideCredentials for Arc<dyn ProvideCredentials> {
116 fn provide_credentials<'a>(&'a self) -> super::future::ProvideCredentials<'a>
117 where
118 Self: 'a,
119 {
120 self.as_ref().provide_credentials()
121 }
122}
123
124#[derive(Clone, Debug)]
129pub struct SharedCredentialsProvider(Arc<dyn ProvideCredentials>, IdentityCachePartition);
130
131impl SharedCredentialsProvider {
132 pub fn new(provider: impl ProvideCredentials + 'static) -> Self {
137 Self(Arc::new(provider), IdentityCachePartition::new())
138 }
139}
140
141impl AsRef<dyn ProvideCredentials> for SharedCredentialsProvider {
142 fn as_ref(&self) -> &(dyn ProvideCredentials + 'static) {
143 self.0.as_ref()
144 }
145}
146
147impl From<Arc<dyn ProvideCredentials>> for SharedCredentialsProvider {
148 fn from(provider: Arc<dyn ProvideCredentials>) -> Self {
149 SharedCredentialsProvider(provider, IdentityCachePartition::new())
150 }
151}
152
153impl ProvideCredentials for SharedCredentialsProvider {
154 fn provide_credentials<'a>(&'a self) -> super::future::ProvideCredentials<'a>
155 where
156 Self: 'a,
157 {
158 self.0.provide_credentials()
159 }
160}
161
162impl Storable for SharedCredentialsProvider {
163 type Storer = StoreReplace<SharedCredentialsProvider>;
164}
165
166impl ResolveIdentity for SharedCredentialsProvider {
167 fn resolve_identity<'a>(
168 &'a self,
169 _runtime_components: &'a RuntimeComponents,
170 _config_bag: &'a ConfigBag,
171 ) -> IdentityFuture<'a> {
172 IdentityFuture::new(async move { Ok(self.provide_credentials().await?.into()) })
173 }
174
175 fn fallback_on_interrupt(&self) -> Option<Identity> {
176 ProvideCredentials::fallback_on_interrupt(self).map(|creds| creds.into())
177 }
178
179 fn cache_partition(&self) -> Option<IdentityCachePartition> {
180 Some(self.1)
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use aws_smithy_runtime_api::client::{
187 identity::SharedIdentityResolver, runtime_components::RuntimeComponentsBuilder,
188 };
189
190 use crate::attributes::AccountId;
191
192 use super::*;
193
194 #[test]
195 fn reuses_cache_partition() {
196 let creds = Credentials::new("AKID", "SECRET", None, None, "test");
197 let provider = SharedCredentialsProvider::new(creds);
198 let partition = provider.cache_partition();
199 assert!(partition.is_some());
200
201 let identity_resolver = SharedIdentityResolver::new(provider);
202 let identity_partition = identity_resolver.cache_partition();
203
204 assert!(partition.unwrap() == identity_partition);
205 }
206
207 #[tokio::test]
208 async fn account_id_can_be_retrieved_from_identity() {
209 let expected_account_id = "012345678901";
210 let creds = Credentials::builder()
211 .access_key_id("AKID")
212 .secret_access_key("SECRET")
213 .account_id(expected_account_id)
214 .provider_name("test")
215 .build();
216 let provider = SharedCredentialsProvider::new(creds);
217 let identity = provider
218 .resolve_identity(
219 &RuntimeComponentsBuilder::for_tests().build().unwrap(),
220 &ConfigBag::base(),
221 )
222 .await
223 .unwrap();
224 let actual = identity.property::<AccountId>().unwrap();
225 assert_eq!(expected_account_id, actual.as_str());
226 }
227}