1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
56//! Credentials provider errors
78use std::error::Error;
9use std::fmt;
10use std::time::Duration;
1112/// Details for [`CredentialsError::CredentialsNotLoaded`]
13#[derive(Debug)]
14pub struct CredentialsNotLoaded {
15 source: Option<Box<dyn Error + Send + Sync + 'static>>,
16}
1718/// Details for [`CredentialsError::ProviderTimedOut`] or [`TokenError::ProviderTimedOut`]
19#[derive(Debug)]
20pub struct ProviderTimedOut {
21 timeout_duration: Duration,
22}
2324impl ProviderTimedOut {
25/// Returns the maximum allowed timeout duration that was exceeded
26pub fn timeout_duration(&self) -> Duration {
27self.timeout_duration
28 }
29}
3031/// Details for [`CredentialsError::InvalidConfiguration`] or [`TokenError::InvalidConfiguration`]
32#[derive(Debug)]
33pub struct InvalidConfiguration {
34 source: Box<dyn Error + Send + Sync + 'static>,
35}
3637/// Details for [`CredentialsError::ProviderError`] or [`TokenError::ProviderError`]
38#[derive(Debug)]
39pub struct ProviderError {
40 source: Box<dyn Error + Send + Sync + 'static>,
41}
4243/// Details for [`CredentialsError::Unhandled`] or [`TokenError::Unhandled`]
44#[derive(Debug)]
45pub struct Unhandled {
46 source: Box<dyn Error + Send + Sync + 'static>,
47}
4849/// Error returned when credentials failed to load.
50#[derive(Debug)]
51#[non_exhaustive]
52pub enum CredentialsError {
53/// No credentials were available for this provider
54CredentialsNotLoaded(CredentialsNotLoaded),
5556/// Loading credentials from this provider exceeded the maximum allowed duration
57ProviderTimedOut(ProviderTimedOut),
5859/// The provider was given an invalid configuration
60 ///
61 /// For example:
62 /// - syntax error in ~/.aws/config
63 /// - assume role profile that forms an infinite loop
64InvalidConfiguration(InvalidConfiguration),
6566/// The provider experienced an error during credential resolution
67 ///
68 /// This may include errors like a 503 from STS or a file system error when attempting to
69 /// read a configuration file.
70ProviderError(ProviderError),
7172/// An unexpected error occurred during credential resolution
73 ///
74 /// If the error is something that can occur during expected usage of a provider, `ProviderError`
75 /// should be returned instead. Unhandled is reserved for exceptional cases, for example:
76 /// - Returned data not UTF-8
77 /// - A provider returns data that is missing required fields
78Unhandled(Unhandled),
79}
8081impl CredentialsError {
82/// The credentials provider did not provide credentials
83 ///
84 /// This error indicates the credentials provider was not enable or no configuration was set.
85 /// This contrasts with [`invalid_configuration`](CredentialsError::InvalidConfiguration), indicating
86 /// that the provider was configured in some way, but certain settings were invalid.
87pub fn not_loaded(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
88 CredentialsError::CredentialsNotLoaded(CredentialsNotLoaded {
89 source: Some(source.into()),
90 })
91 }
9293/// The credentials provider did not provide credentials
94 ///
95 /// This error indicates the credentials provider was not enable or no configuration was set.
96 /// This contrasts with [`invalid_configuration`](CredentialsError::InvalidConfiguration), indicating
97 /// that the provider was configured in some way, but certain settings were invalid.
98pub fn not_loaded_no_source() -> Self {
99 CredentialsError::CredentialsNotLoaded(CredentialsNotLoaded { source: None })
100 }
101102/// An unexpected error occurred loading credentials from this provider
103 ///
104 /// Unhandled errors should not occur during normal operation and should be reserved for exceptional
105 /// cases, such as a JSON API returning an output that was not parseable as JSON.
106pub fn unhandled(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
107Self::Unhandled(Unhandled {
108 source: source.into(),
109 })
110 }
111112/// The credentials provider returned an error
113 ///
114 /// Provider errors may occur during normal use of a credentials provider, e.g. a 503 when
115 /// retrieving credentials from IMDS.
116pub fn provider_error(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
117Self::ProviderError(ProviderError {
118 source: source.into(),
119 })
120 }
121122/// The provided configuration for a provider was invalid
123pub fn invalid_configuration(
124 source: impl Into<Box<dyn Error + Send + Sync + 'static>>,
125 ) -> Self {
126Self::InvalidConfiguration(InvalidConfiguration {
127 source: source.into(),
128 })
129 }
130131/// The credentials provider did not provide credentials within an allotted duration
132pub fn provider_timed_out(timeout_duration: Duration) -> Self {
133Self::ProviderTimedOut(ProviderTimedOut { timeout_duration })
134 }
135}
136137impl fmt::Display for CredentialsError {
138fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139match self {
140 CredentialsError::CredentialsNotLoaded(_) => {
141write!(f, "the credential provider was not enabled")
142 }
143 CredentialsError::ProviderTimedOut(details) => write!(
144 f,
145"credentials provider timed out after {} seconds",
146 details.timeout_duration.as_secs()
147 ),
148 CredentialsError::InvalidConfiguration(_) => {
149write!(f, "the credentials provider was not properly configured")
150 }
151 CredentialsError::ProviderError(_) => {
152write!(f, "an error occurred while loading credentials")
153 }
154 CredentialsError::Unhandled(_) => {
155write!(f, "unexpected credentials error")
156 }
157 }
158 }
159}
160161impl Error for CredentialsError {
162fn source(&self) -> Option<&(dyn Error + 'static)> {
163match self {
164 CredentialsError::CredentialsNotLoaded(details) => {
165 details.source.as_ref().map(|s| s.as_ref() as _)
166 }
167 CredentialsError::ProviderTimedOut(_) => None,
168 CredentialsError::InvalidConfiguration(details) => Some(details.source.as_ref() as _),
169 CredentialsError::ProviderError(details) => Some(details.source.as_ref() as _),
170 CredentialsError::Unhandled(details) => Some(details.source.as_ref() as _),
171 }
172 }
173}
174175/// Details for [`TokenError::TokenNotLoaded`]
176#[derive(Debug)]
177pub struct TokenNotLoaded {
178 source: Box<dyn Error + Send + Sync + 'static>,
179}
180181/// Error returned when an access token provider fails to provide an access token.
182#[derive(Debug)]
183pub enum TokenError {
184/// This provider couldn't provide a token.
185TokenNotLoaded(TokenNotLoaded),
186187/// Loading a token from this provider exceeded the maximum allowed time.
188ProviderTimedOut(ProviderTimedOut),
189190/// The provider was given invalid configuration.
191 ///
192 /// For example, a syntax error in `~/.aws/config`.
193InvalidConfiguration(InvalidConfiguration),
194195/// The provider experienced an error during credential resolution.
196ProviderError(ProviderError),
197198/// An unexpected error occurred during token resolution.
199 ///
200 /// If the error is something that can occur during expected usage of a provider, `ProviderError`
201 /// should be returned instead. Unhandled is reserved for exceptional cases, for example:
202 /// - Returned data not UTF-8
203 /// - A provider returns data that is missing required fields
204Unhandled(Unhandled),
205}
206207impl TokenError {
208/// The access token provider couldn't provide a token.
209 ///
210 /// This error indicates the token provider was not enable or no configuration was set.
211 /// This contrasts with [`invalid_configuration`](TokenError::InvalidConfiguration), indicating
212 /// that the provider was configured in some way, but certain settings were invalid.
213pub fn not_loaded(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
214 TokenError::TokenNotLoaded(TokenNotLoaded {
215 source: source.into(),
216 })
217 }
218219/// An unexpected error occurred loading an access token from this provider.
220 ///
221 /// Unhandled errors should not occur during normal operation and should be reserved for exceptional
222 /// cases, such as a JSON API returning an output that was not parseable as JSON.
223pub fn unhandled(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
224Self::Unhandled(Unhandled {
225 source: source.into(),
226 })
227 }
228229/// The access token provider returned an error.
230pub fn provider_error(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
231Self::ProviderError(ProviderError {
232 source: source.into(),
233 })
234 }
235236/// The provided configuration for a provider was invalid.
237pub fn invalid_configuration(
238 source: impl Into<Box<dyn Error + Send + Sync + 'static>>,
239 ) -> Self {
240Self::InvalidConfiguration(InvalidConfiguration {
241 source: source.into(),
242 })
243 }
244245/// The access token provider did not provide a token within an allotted amount of time.
246pub fn provider_timed_out(timeout_duration: Duration) -> Self {
247Self::ProviderTimedOut(ProviderTimedOut { timeout_duration })
248 }
249}
250251impl fmt::Display for TokenError {
252fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253match self {
254 TokenError::TokenNotLoaded(_) => {
255write!(f, "the access token provider was not enabled")
256 }
257 TokenError::ProviderTimedOut(details) => write!(
258 f,
259"access token provider timed out after {} seconds",
260 details.timeout_duration.as_secs()
261 ),
262 TokenError::InvalidConfiguration(_) => {
263write!(f, "the access token provider was not properly configured")
264 }
265 TokenError::ProviderError(_) => {
266write!(f, "an error occurred while loading an access token")
267 }
268 TokenError::Unhandled(_) => {
269write!(f, "unexpected access token providererror")
270 }
271 }
272 }
273}
274275impl Error for TokenError {
276fn source(&self) -> Option<&(dyn Error + 'static)> {
277match self {
278 TokenError::TokenNotLoaded(details) => Some(details.source.as_ref() as _),
279 TokenError::ProviderTimedOut(_) => None,
280 TokenError::InvalidConfiguration(details) => Some(details.source.as_ref() as _),
281 TokenError::ProviderError(details) => Some(details.source.as_ref() as _),
282 TokenError::Unhandled(details) => Some(details.source.as_ref() as _),
283 }
284 }
285}