#![cfg_attr(
feature = "hardcoded-credentials",
doc = r##"
See [`Credentials::from_keys`] for an example on how to use static credentials.
"##
)]
#![cfg_attr(
not(feature = "hardcoded-credentials"),
doc = r##"
Enable the `hardcoded-credentials` feature to be able to use `Credentials::from_keys` to
construct credentials from hardcoded values.
"##
)]
use crate::Credentials;
use aws_smithy_runtime_api::client::identity::{Identity, IdentityFuture, ResolveIdentity};
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace};
use std::sync::Arc;
pub mod error {
use std::error::Error;
use std::fmt;
use std::time::Duration;
#[derive(Debug)]
pub struct CredentialsNotLoaded {
source: Box<dyn Error + Send + Sync + 'static>,
}
#[derive(Debug)]
pub struct ProviderTimedOut {
timeout_duration: Duration,
}
impl ProviderTimedOut {
pub fn timeout_duration(&self) -> Duration {
self.timeout_duration
}
}
#[derive(Debug)]
pub struct InvalidConfiguration {
source: Box<dyn Error + Send + Sync + 'static>,
}
#[derive(Debug)]
pub struct ProviderError {
source: Box<dyn Error + Send + Sync + 'static>,
}
#[derive(Debug)]
pub struct Unhandled {
source: Box<dyn Error + Send + Sync + 'static>,
}
#[derive(Debug)]
#[non_exhaustive]
pub enum CredentialsError {
CredentialsNotLoaded(CredentialsNotLoaded),
ProviderTimedOut(ProviderTimedOut),
InvalidConfiguration(InvalidConfiguration),
ProviderError(ProviderError),
Unhandled(Unhandled),
}
impl CredentialsError {
pub fn not_loaded(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
CredentialsError::CredentialsNotLoaded(CredentialsNotLoaded {
source: source.into(),
})
}
pub fn unhandled(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
Self::Unhandled(Unhandled {
source: source.into(),
})
}
pub fn provider_error(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
Self::ProviderError(ProviderError {
source: source.into(),
})
}
pub fn invalid_configuration(
source: impl Into<Box<dyn Error + Send + Sync + 'static>>,
) -> Self {
Self::InvalidConfiguration(InvalidConfiguration {
source: source.into(),
})
}
pub fn provider_timed_out(timeout_duration: Duration) -> Self {
Self::ProviderTimedOut(ProviderTimedOut { timeout_duration })
}
}
impl fmt::Display for CredentialsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CredentialsError::CredentialsNotLoaded(_) => {
write!(f, "the credential provider was not enabled")
}
CredentialsError::ProviderTimedOut(details) => write!(
f,
"credentials provider timed out after {} seconds",
details.timeout_duration.as_secs()
),
CredentialsError::InvalidConfiguration(_) => {
write!(f, "the credentials provider was not properly configured")
}
CredentialsError::ProviderError(_) => {
write!(f, "an error occurred while loading credentials")
}
CredentialsError::Unhandled(_) => {
write!(f, "unexpected credentials error")
}
}
}
}
impl Error for CredentialsError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
CredentialsError::CredentialsNotLoaded(details) => {
Some(details.source.as_ref() as _)
}
CredentialsError::ProviderTimedOut(_) => None,
CredentialsError::InvalidConfiguration(details) => {
Some(details.source.as_ref() as _)
}
CredentialsError::ProviderError(details) => Some(details.source.as_ref() as _),
CredentialsError::Unhandled(details) => Some(details.source.as_ref() as _),
}
}
}
}
pub type Result = std::result::Result<Credentials, error::CredentialsError>;
pub mod future {
use aws_smithy_async::future::now_or_later::NowOrLater;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
#[derive(Debug)]
pub struct ProvideCredentials<'a>(NowOrLater<super::Result, BoxFuture<'a, super::Result>>);
impl<'a> ProvideCredentials<'a> {
pub fn new(future: impl Future<Output = super::Result> + Send + 'a) -> Self {
ProvideCredentials(NowOrLater::new(Box::pin(future)))
}
pub fn ready(credentials: super::Result) -> Self {
ProvideCredentials(NowOrLater::ready(credentials))
}
}
impl Future for ProvideCredentials<'_> {
type Output = super::Result;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.0).poll(cx)
}
}
}
pub trait ProvideCredentials: Send + Sync + std::fmt::Debug {
fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
where
Self: 'a;
fn fallback_on_interrupt(&self) -> Option<Credentials> {
None
}
}
impl ProvideCredentials for Credentials {
fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
where
Self: 'a,
{
future::ProvideCredentials::ready(Ok(self.clone()))
}
}
impl ProvideCredentials for Arc<dyn ProvideCredentials> {
fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
where
Self: 'a,
{
self.as_ref().provide_credentials()
}
}
#[derive(Clone, Debug)]
pub struct SharedCredentialsProvider(Arc<dyn ProvideCredentials>);
impl SharedCredentialsProvider {
pub fn new(provider: impl ProvideCredentials + 'static) -> Self {
Self(Arc::new(provider))
}
}
impl AsRef<dyn ProvideCredentials> for SharedCredentialsProvider {
fn as_ref(&self) -> &(dyn ProvideCredentials + 'static) {
self.0.as_ref()
}
}
impl From<Arc<dyn ProvideCredentials>> for SharedCredentialsProvider {
fn from(provider: Arc<dyn ProvideCredentials>) -> Self {
SharedCredentialsProvider(provider)
}
}
impl ProvideCredentials for SharedCredentialsProvider {
fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
where
Self: 'a,
{
self.0.provide_credentials()
}
}
impl Storable for SharedCredentialsProvider {
type Storer = StoreReplace<SharedCredentialsProvider>;
}
impl ResolveIdentity for SharedCredentialsProvider {
fn resolve_identity<'a>(
&'a self,
_runtime_components: &'a RuntimeComponents,
_config_bag: &'a ConfigBag,
) -> IdentityFuture<'a> {
IdentityFuture::new(async move { Ok(self.provide_credentials().await?.into()) })
}
fn fallback_on_interrupt(&self) -> Option<Identity> {
ProvideCredentials::fallback_on_interrupt(self).map(|creds| creds.into())
}
}