1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
use aws_smithy_types::error::display::DisplayErrorContext;
use std::borrow::Cow;
use tracing::Instrument;
#[derive(Debug)]
pub struct CredentialsProviderChain {
providers: Vec<(Cow<'static, str>, Box<dyn ProvideCredentials>)>,
}
impl CredentialsProviderChain {
pub fn first_try(
name: impl Into<Cow<'static, str>>,
provider: impl ProvideCredentials + 'static,
) -> Self {
CredentialsProviderChain {
providers: vec![(name.into(), Box::new(provider))],
}
}
pub fn or_else(
mut self,
name: impl Into<Cow<'static, str>>,
provider: impl ProvideCredentials + 'static,
) -> Self {
self.providers.push((name.into(), Box::new(provider)));
self
}
#[cfg(any(feature = "rustls", feature = "native-tls"))]
pub async fn or_default_provider(self) -> Self {
self.or_else(
"DefaultProviderChain",
crate::default_provider::credentials::default_provider().await,
)
}
#[cfg(any(feature = "rustls", feature = "native-tls"))]
pub async fn default_provider() -> Self {
Self::first_try(
"DefaultProviderChain",
crate::default_provider::credentials::default_provider().await,
)
}
async fn credentials(&self) -> provider::Result {
for (name, provider) in &self.providers {
let span = tracing::debug_span!("load_credentials", provider = %name);
match provider.provide_credentials().instrument(span).await {
Ok(credentials) => {
tracing::debug!(provider = %name, "loaded credentials");
return Ok(credentials);
}
Err(err @ CredentialsError::CredentialsNotLoaded(_)) => {
tracing::debug!(provider = %name, context = %DisplayErrorContext(&err), "provider in chain did not provide credentials");
}
Err(err) => {
tracing::warn!(provider = %name, error = %DisplayErrorContext(&err), "provider failed to provide credentials");
return Err(err);
}
}
}
Err(CredentialsError::not_loaded(
"no providers in chain provided credentials",
))
}
}
impl ProvideCredentials for CredentialsProviderChain {
fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'_>
where
Self: 'a,
{
future::ProvideCredentials::new(self.credentials())
}
}