diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml
index cfeb53879e..0faa2266e8 100644
--- a/CHANGELOG.next.toml
+++ b/CHANGELOG.next.toml
@@ -450,3 +450,21 @@ message = """
references = ["smithy-rs#3076"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" }
author = "ysaito1001"
+
+[[aws-sdk-rust]]
+message = "**This change has [detailed upgrade guidance](https://github.com/awslabs/aws-sdk-rust/discussions/923).**
The AWS credentials cache has been replaced with a more generic identity cache."
+references = ["smithy-rs#3077"]
+meta = { "breaking" = true, "tada" = false, "bug" = false }
+author = "jdisanti"
+
+[[smithy-rs]]
+message = "**Behavior Break!** Identities for auth are now cached by default. See the `Config` builder's `identity_cache()` method docs for an example of how to disable this caching."
+references = ["smithy-rs#3077"]
+meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
+author = "jdisanti"
+
+[[smithy-rs]]
+message = "Clients now have a default async sleep implementation so that one does not need to be specified if you're using Tokio."
+references = ["smithy-rs#3071"]
+meta = { "breaking" = false, "tada" = true, "bug" = false, "target" = "client" }
+author = "jdisanti"
diff --git a/aws/rust-runtime/aws-config/external-types.toml b/aws/rust-runtime/aws-config/external-types.toml
index c6328580b0..e1593172a6 100644
--- a/aws/rust-runtime/aws-config/external-types.toml
+++ b/aws/rust-runtime/aws-config/external-types.toml
@@ -12,15 +12,18 @@ allowed_external_types = [
"aws_smithy_async::rt::sleep::SharedAsyncSleep",
"aws_smithy_async::time::SharedTimeSource",
"aws_smithy_async::time::TimeSource",
- "aws_smithy_types::body::SdkBody",
"aws_smithy_http::endpoint",
"aws_smithy_http::endpoint::error::InvalidEndpointError",
"aws_smithy_http::result::SdkError",
+ "aws_smithy_runtime::client::identity::cache::IdentityCache",
+ "aws_smithy_runtime::client::identity::cache::lazy::LazyCacheBuilder",
"aws_smithy_runtime_api::client::dns::ResolveDns",
"aws_smithy_runtime_api::client::dns::SharedDnsResolver",
"aws_smithy_runtime_api::client::http::HttpClient",
"aws_smithy_runtime_api::client::http::SharedHttpClient",
+ "aws_smithy_runtime_api::client::identity::ResolveCachedIdentity",
"aws_smithy_runtime_api::client::identity::ResolveIdentity",
+ "aws_smithy_types::body::SdkBody",
"aws_smithy_types::retry",
"aws_smithy_types::retry::*",
"aws_smithy_types::timeout",
diff --git a/aws/rust-runtime/aws-config/src/imds/client.rs b/aws/rust-runtime/aws-config/src/imds/client.rs
index e956193e38..fd2315a316 100644
--- a/aws/rust-runtime/aws-config/src/imds/client.rs
+++ b/aws/rust-runtime/aws-config/src/imds/client.rs
@@ -433,7 +433,6 @@ impl Builder {
.runtime_plugin(common_plugin.clone())
.runtime_plugin(TokenRuntimePlugin::new(
common_plugin,
- config.time_source(),
self.token_ttl.unwrap_or(DEFAULT_TOKEN_TTL),
))
.with_connection_poisoning()
@@ -748,6 +747,7 @@ pub(crate) mod test {
/// Tokens are refreshed up to 120 seconds early to avoid using an expired token.
#[tokio::test]
async fn token_refresh_buffer() {
+ let _logs = capture_test_logs();
let (_, http_client) = mock_imds_client(vec![
ReplayEvent::new(
token_request("http://[fd00:ec2::254]", 600),
@@ -785,11 +785,14 @@ pub(crate) mod test {
.token_ttl(Duration::from_secs(600))
.build();
+ tracing::info!("resp1 -----------------------------------------------------------");
let resp1 = client.get("/latest/metadata").await.expect("success");
// now the cached credential has expired
time_source.advance(Duration::from_secs(400));
+ tracing::info!("resp2 -----------------------------------------------------------");
let resp2 = client.get("/latest/metadata").await.expect("success");
time_source.advance(Duration::from_secs(150));
+ tracing::info!("resp3 -----------------------------------------------------------");
let resp3 = client.get("/latest/metadata").await.expect("success");
http_client.assert_requests_match(&[]);
assert_eq!("test-imds-output1", resp1.as_ref());
diff --git a/aws/rust-runtime/aws-config/src/imds/client/token.rs b/aws/rust-runtime/aws-config/src/imds/client/token.rs
index 57c0aeddd1..d91fa3b89f 100644
--- a/aws/rust-runtime/aws-config/src/imds/client/token.rs
+++ b/aws/rust-runtime/aws-config/src/imds/client/token.rs
@@ -14,10 +14,11 @@
//! - Retry token loading when it fails
//! - Attach the token to the request in the `x-aws-ec2-metadata-token` header
+use crate::identity::IdentityCache;
use crate::imds::client::error::{ImdsError, TokenError, TokenErrorKind};
-use aws_credential_types::cache::ExpiringCache;
use aws_smithy_async::time::SharedTimeSource;
use aws_smithy_runtime::client::orchestrator::operation::Operation;
+use aws_smithy_runtime::expiring_cache::ExpiringCache;
use aws_smithy_runtime_api::box_error::BoxError;
use aws_smithy_runtime_api::client::auth::static_resolver::StaticAuthSchemeOptionResolver;
use aws_smithy_runtime_api::client::auth::{
@@ -50,6 +51,12 @@ const X_AWS_EC2_METADATA_TOKEN_TTL_SECONDS: &str = "x-aws-ec2-metadata-token-ttl
const X_AWS_EC2_METADATA_TOKEN: &str = "x-aws-ec2-metadata-token";
const IMDS_TOKEN_AUTH_SCHEME: AuthSchemeId = AuthSchemeId::new(X_AWS_EC2_METADATA_TOKEN);
+#[derive(Debug)]
+struct TtlToken {
+ value: HeaderValue,
+ ttl: Duration,
+}
+
/// IMDS Token
#[derive(Clone)]
struct Token {
@@ -76,20 +83,18 @@ pub(super) struct TokenRuntimePlugin {
}
impl TokenRuntimePlugin {
- pub(super) fn new(
- common_plugin: SharedRuntimePlugin,
- time_source: SharedTimeSource,
- token_ttl: Duration,
- ) -> Self {
+ pub(super) fn new(common_plugin: SharedRuntimePlugin, token_ttl: Duration) -> Self {
Self {
components: RuntimeComponentsBuilder::new("TokenRuntimePlugin")
.with_auth_scheme(TokenAuthScheme::new())
.with_auth_scheme_option_resolver(Some(StaticAuthSchemeOptionResolver::new(vec![
IMDS_TOKEN_AUTH_SCHEME,
])))
+ // The TokenResolver has a cache of its own, so don't use identity caching
+ .with_identity_cache(Some(IdentityCache::no_cache()))
.with_identity_resolver(
IMDS_TOKEN_AUTH_SCHEME,
- TokenResolver::new(common_plugin, time_source, token_ttl),
+ TokenResolver::new(common_plugin, token_ttl),
),
}
}
@@ -107,8 +112,7 @@ impl RuntimePlugin for TokenRuntimePlugin {
#[derive(Debug)]
struct TokenResolverInner {
cache: ExpiringCache,
- refresh: Operation<(), Token, TokenError>,
- time_source: SharedTimeSource,
+ refresh: Operation<(), TtlToken, TokenError>,
}
#[derive(Clone, Debug)]
@@ -117,11 +121,7 @@ struct TokenResolver {
}
impl TokenResolver {
- fn new(
- common_plugin: SharedRuntimePlugin,
- time_source: SharedTimeSource,
- token_ttl: Duration,
- ) -> Self {
+ fn new(common_plugin: SharedRuntimePlugin, token_ttl: Duration) -> Self {
Self {
inner: Arc::new(TokenResolverInner {
cache: ExpiringCache::new(TOKEN_REFRESH_BUFFER),
@@ -141,26 +141,26 @@ impl TokenResolver {
.try_into()
.unwrap())
})
- .deserializer({
- let time_source = time_source.clone();
- move |response| {
- let now = time_source.now();
- parse_token_response(response, now)
- .map_err(OrchestratorError::operation)
- }
+ .deserializer(move |response| {
+ parse_token_response(response).map_err(OrchestratorError::operation)
})
.build(),
- time_source,
}),
}
}
- async fn get_token(&self) -> Result<(Token, SystemTime), ImdsError> {
- self.inner
- .refresh
- .invoke(())
- .await
+ async fn get_token(
+ &self,
+ time_source: SharedTimeSource,
+ ) -> Result<(Token, SystemTime), ImdsError> {
+ let result = self.inner.refresh.invoke(()).await;
+ let now = time_source.now();
+ result
.map(|token| {
+ let token = Token {
+ value: token.value,
+ expiry: now + token.ttl,
+ };
let expiry = token.expiry;
(token, expiry)
})
@@ -168,7 +168,7 @@ impl TokenResolver {
}
}
-fn parse_token_response(response: &HttpResponse, now: SystemTime) -> Result {
+fn parse_token_response(response: &HttpResponse) -> Result {
match response.status().as_u16() {
400 => return Err(TokenErrorKind::InvalidParameters.into()),
403 => return Err(TokenErrorKind::Forbidden.into()),
@@ -187,30 +187,38 @@ fn parse_token_response(response: &HttpResponse, now: SystemTime) -> Result(
&'a self,
- _components: &'a RuntimeComponents,
+ components: &'a RuntimeComponents,
_config_bag: &'a ConfigBag,
) -> IdentityFuture<'a> {
+ let time_source = components
+ .time_source()
+ .expect("time source required for IMDS token caching");
IdentityFuture::new(async {
- let preloaded_token = self
- .inner
- .cache
- .yield_or_clear_if_expired(self.inner.time_source.now())
- .await;
+ let now = time_source.now();
+ let preloaded_token = self.inner.cache.yield_or_clear_if_expired(now).await;
let token = match preloaded_token {
- Some(token) => Ok(token),
+ Some(token) => {
+ tracing::trace!(
+ buffer_time=?TOKEN_REFRESH_BUFFER,
+ expiration=?token.expiry,
+ now=?now,
+ "loaded IMDS token from cache");
+ Ok(token)
+ }
None => {
+ tracing::debug!("IMDS token cache miss");
self.inner
.cache
- .get_or_load(|| async { self.get_token().await })
+ .get_or_load(|| async { self.get_token(time_source).await })
.await
}
}?;
diff --git a/aws/rust-runtime/aws-config/src/lib.rs b/aws/rust-runtime/aws-config/src/lib.rs
index a12dea2a3b..c0cec0cfcd 100644
--- a/aws/rust-runtime/aws-config/src/lib.rs
+++ b/aws/rust-runtime/aws-config/src/lib.rs
@@ -102,6 +102,12 @@ pub use aws_types::{
/// Load default sources for all configuration with override support
pub use loader::ConfigLoader;
+/// Types for configuring identity caching.
+pub mod identity {
+ pub use aws_smithy_runtime::client::identity::IdentityCache;
+ pub use aws_smithy_runtime::client::identity::LazyCacheBuilder;
+}
+
#[allow(dead_code)]
const PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
@@ -155,11 +161,11 @@ mod loader {
use crate::meta::region::ProvideRegion;
use crate::profile::profile_file::ProfileFiles;
use crate::provider_config::ProviderConfig;
- use aws_credential_types::cache::CredentialsCache;
use aws_credential_types::provider::{ProvideCredentials, SharedCredentialsProvider};
use aws_smithy_async::rt::sleep::{default_async_sleep, AsyncSleep, SharedAsyncSleep};
use aws_smithy_async::time::{SharedTimeSource, TimeSource};
use aws_smithy_runtime_api::client::http::HttpClient;
+ use aws_smithy_runtime_api::client::identity::{ResolveCachedIdentity, SharedIdentityCache};
use aws_smithy_runtime_api::shared::IntoShared;
use aws_smithy_types::retry::RetryConfig;
use aws_smithy_types::timeout::TimeoutConfig;
@@ -189,7 +195,7 @@ mod loader {
#[derive(Default, Debug)]
pub struct ConfigLoader {
app_name: Option,
- credentials_cache: Option,
+ identity_cache: Option,
credentials_provider: CredentialsProviderOption,
endpoint_url: Option,
region: Option>,
@@ -333,22 +339,45 @@ mod loader {
self
}
- /// Override the credentials cache used to build [`SdkConfig`](aws_types::SdkConfig).
+ /// The credentials cache has been replaced. Use the identity_cache() method instead. See its rustdoc for an example.
+ #[deprecated(
+ note = "The credentials cache has been replaced. Use the identity_cache() method instead for equivalent functionality. See its rustdoc for an example."
+ )]
+ pub fn credentials_cache(self) -> Self {
+ self
+ }
+
+ /// Override the identity cache used to build [`SdkConfig`](aws_types::SdkConfig).
+ ///
+ /// The identity cache caches AWS credentials and SSO tokens. By default, a lazy cache is used
+ /// that will load credentials upon first request, cache them, and then reload them during
+ /// another request when they are close to expiring.
///
/// # Examples
///
- /// Override the credentials cache but load the default value for region:
+ /// Change a setting on the default lazy caching implementation:
/// ```no_run
- /// # use aws_credential_types::cache::CredentialsCache;
+ /// use aws_config::identity::IdentityCache;
+ /// use std::time::Duration;
+ ///
/// # async fn create_config() {
/// let config = aws_config::from_env()
- /// .credentials_cache(CredentialsCache::lazy())
+ /// .identity_cache(
+ /// IdentityCache::lazy()
+ /// // Change the load timeout to 10 seconds.
+ /// // Note: there are other timeouts that could trigger if the load timeout is too long.
+ /// .load_timeout(Duration::from_secs(10))
+ /// .build()
+ /// )
/// .load()
/// .await;
/// # }
/// ```
- pub fn credentials_cache(mut self, credentials_cache: CredentialsCache) -> Self {
- self.credentials_cache = Some(credentials_cache);
+ pub fn identity_cache(
+ mut self,
+ identity_cache: impl ResolveCachedIdentity + 'static,
+ ) -> Self {
+ self.identity_cache = Some(identity_cache.into_shared());
self
}
@@ -656,17 +685,6 @@ mod loader {
CredentialsProviderOption::ExplicitlyUnset => None,
};
- let credentials_cache = if credentials_provider.is_some() {
- Some(self.credentials_cache.unwrap_or_else(|| {
- let mut builder =
- CredentialsCache::lazy_builder().time_source(conf.time_source());
- builder.set_sleep_impl(conf.sleep_impl());
- builder.into_credentials_cache()
- }))
- } else {
- None
- };
-
let mut builder = SdkConfig::builder()
.region(region)
.retry_config(retry_config)
@@ -675,7 +693,7 @@ mod loader {
builder.set_http_client(self.http_client);
builder.set_app_name(app_name);
- builder.set_credentials_cache(credentials_cache);
+ builder.set_identity_cache(self.identity_cache);
builder.set_credentials_provider(credentials_provider);
builder.set_sleep_impl(sleep_impl);
builder.set_endpoint_url(self.endpoint_url);
@@ -705,13 +723,11 @@ mod loader {
use crate::{from_env, ConfigLoader};
use aws_credential_types::provider::ProvideCredentials;
use aws_smithy_async::rt::sleep::TokioSleep;
- use aws_smithy_async::time::{StaticTimeSource, TimeSource};
use aws_smithy_runtime::client::http::test_util::{infallible_client_fn, NeverClient};
use aws_types::app_name::AppName;
use aws_types::os_shim_internal::{Env, Fs};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
- use std::time::{SystemTime, UNIX_EPOCH};
use tracing_test::traced_test;
#[tokio::test]
@@ -800,7 +816,7 @@ mod loader {
#[tokio::test]
async fn disable_default_credentials() {
let config = from_env().no_credentials().load().await;
- assert!(config.credentials_cache().is_none());
+ assert!(config.identity_cache().is_none());
assert!(config.credentials_provider().is_none());
}
@@ -827,35 +843,5 @@ mod loader {
let num_requests = num_requests.load(Ordering::Relaxed);
assert!(num_requests > 0, "{}", num_requests);
}
-
- #[tokio::test]
- async fn time_source_is_passed() {
- #[derive(Debug)]
- struct PanicTs;
- impl TimeSource for PanicTs {
- fn now(&self) -> SystemTime {
- panic!("timesource-was-used")
- }
- }
- let config = from_env()
- .sleep_impl(InstantSleep)
- .time_source(StaticTimeSource::new(UNIX_EPOCH))
- .http_client(no_traffic_client())
- .load()
- .await;
- // assert that the innards contain the customized fields
- for inner in ["InstantSleep", "StaticTimeSource"] {
- assert!(
- format!("{:#?}", config.credentials_cache()).contains(inner),
- "{:#?}",
- config.credentials_cache()
- );
- assert!(
- format!("{:#?}", config.credentials_provider()).contains(inner),
- "{:#?}",
- config.credentials_cache()
- );
- }
- }
}
}
diff --git a/aws/rust-runtime/aws-config/src/sso/credentials.rs b/aws/rust-runtime/aws-config/src/sso/credentials.rs
index 15e57546c5..fbf7ff4553 100644
--- a/aws/rust-runtime/aws-config/src/sso/credentials.rs
+++ b/aws/rust-runtime/aws-config/src/sso/credentials.rs
@@ -11,9 +11,9 @@
//! This provider is included automatically when profiles are loaded.
use super::cache::load_cached_token;
+use crate::identity::IdentityCache;
use crate::provider_config::ProviderConfig;
use crate::sso::SsoTokenProvider;
-use aws_credential_types::cache::CredentialsCache;
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
use aws_credential_types::Credentials;
use aws_sdk_sso::types::RoleCredentials;
@@ -253,7 +253,7 @@ async fn load_sso_credentials(
let config = sdk_config
.to_builder()
.region(sso_provider_config.region.clone())
- .credentials_cache(CredentialsCache::no_caching())
+ .identity_cache(IdentityCache::no_cache())
.build();
// TODO(enableNewSmithyRuntimeCleanup): Use `customize().config_override()` to set the region instead of creating a new client once middleware is removed
let client = SsoClient::new(&config);
diff --git a/aws/rust-runtime/aws-config/src/sso/token.rs b/aws/rust-runtime/aws-config/src/sso/token.rs
index 11870a241f..b4546cd769 100644
--- a/aws/rust-runtime/aws-config/src/sso/token.rs
+++ b/aws/rust-runtime/aws-config/src/sso/token.rs
@@ -10,14 +10,15 @@
//!
//! This provider is included automatically when profiles are loaded.
+use crate::identity::IdentityCache;
use crate::sso::cache::{
load_cached_token, save_cached_token, CachedSsoToken, CachedSsoTokenError,
};
-use aws_credential_types::cache::{CredentialsCache, ExpiringCache};
use aws_sdk_ssooidc::error::DisplayErrorContext;
use aws_sdk_ssooidc::operation::create_token::CreateTokenOutput;
use aws_sdk_ssooidc::Client as SsoOidcClient;
use aws_smithy_async::time::SharedTimeSource;
+use aws_smithy_runtime::expiring_cache::ExpiringCache;
use aws_smithy_runtime_api::client::identity::http::Token;
use aws_smithy_runtime_api::client::identity::{Identity, IdentityFuture, ResolveIdentity};
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
@@ -74,7 +75,7 @@ impl SsoTokenProvider {
.sdk_config
.to_builder()
.region(Some(inner.region.clone()))
- .credentials_cache(CredentialsCache::no_caching())
+ .identity_cache(IdentityCache::no_cache())
.build();
let client = SsoOidcClient::new(&config);
let resp = client
diff --git a/aws/rust-runtime/aws-config/src/sts/assume_role.rs b/aws/rust-runtime/aws-config/src/sts/assume_role.rs
index 112358ec90..293951b37b 100644
--- a/aws/rust-runtime/aws-config/src/sts/assume_role.rs
+++ b/aws/rust-runtime/aws-config/src/sts/assume_role.rs
@@ -5,7 +5,6 @@
//! Assume credentials for a role through the AWS Security Token Service (STS).
-use aws_credential_types::cache::CredentialsCache;
use aws_credential_types::provider::{
self, error::CredentialsError, future, ProvideCredentials, SharedCredentialsProvider,
};
@@ -14,6 +13,7 @@ use aws_sdk_sts::operation::assume_role::AssumeRoleError;
use aws_sdk_sts::types::PolicyDescriptorType;
use aws_sdk_sts::Client as StsClient;
use aws_smithy_http::result::SdkError;
+use aws_smithy_runtime::client::identity::IdentityCache;
use aws_smithy_types::error::display::DisplayErrorContext;
use aws_types::region::Region;
use aws_types::SdkConfig;
@@ -100,10 +100,7 @@ pub struct AssumeRoleProviderBuilder {
session_length: Option,
policy: Option,
policy_arns: Option>,
-
region_override: Option,
-
- credentials_cache: Option,
sdk_config: Option,
}
@@ -118,7 +115,6 @@ impl AssumeRoleProviderBuilder {
pub fn new(role: impl Into) -> Self {
Self {
role_arn: role.into(),
- credentials_cache: None,
external_id: None,
session_name: None,
session_length: None,
@@ -196,18 +192,6 @@ impl AssumeRoleProviderBuilder {
self
}
- #[deprecated(
- note = "This should not be necessary as the default, no caching, is usually what you want."
- )]
- /// Set the [`CredentialsCache`] for credentials retrieved from STS.
- ///
- /// By default, an [`AssumeRoleProvider`] internally uses `NoCredentialsCache` because the
- /// provider itself will be wrapped by `LazyCredentialsCache` when a service client is created.
- pub fn credentials_cache(mut self, cache: CredentialsCache) -> Self {
- self.credentials_cache = Some(cache);
- self
- }
-
/// Sets the configuration used for this provider
///
/// This enables overriding the connection used to communicate with STS in addition to other internal
@@ -239,13 +223,10 @@ impl AssumeRoleProviderBuilder {
Some(conf) => conf,
None => crate::load_from_env().await,
};
- // ignore a credentials cache set from SdkConfig
+ // ignore a identity cache set from SdkConfig
conf = conf
.into_builder()
- .credentials_cache(
- self.credentials_cache
- .unwrap_or(CredentialsCache::no_caching()),
- )
+ .identity_cache(IdentityCache::no_cache())
.build();
// set a region override if one exists
diff --git a/aws/rust-runtime/aws-config/src/test_case.rs b/aws/rust-runtime/aws-config/src/test_case.rs
index d567bae89e..9a8af1ad6a 100644
--- a/aws/rust-runtime/aws-config/src/test_case.rs
+++ b/aws/rust-runtime/aws-config/src/test_case.rs
@@ -11,23 +11,18 @@ use aws_smithy_async::rt::sleep::{AsyncSleep, Sleep, TokioSleep};
use aws_smithy_runtime::client::http::test_util::dvr::{
NetworkTraffic, RecordingClient, ReplayingClient,
};
+use aws_smithy_runtime::test_util::capture_test_logs::capture_test_logs;
use aws_smithy_runtime_api::shared::IntoShared;
use aws_smithy_types::error::display::DisplayErrorContext;
use aws_types::os_shim_internal::{Env, Fs};
use aws_types::sdk_config::SharedHttpClient;
use serde::Deserialize;
use std::collections::HashMap;
-use std::env;
use std::error::Error;
use std::fmt::Debug;
use std::future::Future;
-use std::io::Write;
use std::path::{Path, PathBuf};
-use std::sync::{Arc, Mutex};
use std::time::{Duration, UNIX_EPOCH};
-use tracing::dispatcher::DefaultGuard;
-use tracing::Level;
-use tracing_subscriber::fmt::TestWriter;
/// Test case credentials
///
@@ -137,81 +132,6 @@ pub(crate) struct Metadata {
name: String,
}
-// TODO(enableNewSmithyRuntimeCleanup): Replace Tee, capture_test_logs, and Rx with
-// the implementations added to aws_smithy_runtime::test_util::capture_test_logs
-struct Tee {
- buf: Arc>>,
- quiet: bool,
- inner: W,
-}
-
-/// Capture logs from this test.
-///
-/// The logs will be captured until the `DefaultGuard` is dropped.
-///
-/// *Why use this instead of traced_test?*
-/// This captures _all_ logs, not just logs produced by the current crate.
-fn capture_test_logs() -> (DefaultGuard, Rx) {
- // it may be helpful to upstream this at some point
- let (mut writer, rx) = Tee::stdout();
- if env::var("VERBOSE_TEST_LOGS").is_ok() {
- writer.loud();
- } else {
- eprintln!("To see full logs from this test set VERBOSE_TEST_LOGS=true");
- }
- let subscriber = tracing_subscriber::fmt()
- .with_max_level(Level::TRACE)
- .with_writer(Mutex::new(writer))
- .finish();
- let guard = tracing::subscriber::set_default(subscriber);
- (guard, rx)
-}
-
-struct Rx(Arc>>);
-impl Rx {
- pub(crate) fn contents(&self) -> String {
- String::from_utf8(self.0.lock().unwrap().clone()).unwrap()
- }
-}
-
-impl Tee {
- fn stdout() -> (Self, Rx) {
- let buf: Arc>> = Default::default();
- (
- Tee {
- buf: buf.clone(),
- quiet: true,
- inner: TestWriter::new(),
- },
- Rx(buf),
- )
- }
-}
-
-impl Tee {
- fn loud(&mut self) {
- self.quiet = false;
- }
-}
-
-impl Write for Tee
-where
- W: Write,
-{
- fn write(&mut self, buf: &[u8]) -> std::io::Result {
- self.buf.lock().unwrap().extend_from_slice(buf);
- if !self.quiet {
- self.inner.write(buf)
- } else {
- Ok(buf.len())
- }
- }
-
- fn flush(&mut self) -> std::io::Result<()> {
- self.inner.flush()
- }
-}
-
impl TestEnvironment {
pub(crate) async fn from_dir(dir: impl AsRef) -> Result> {
let dir = dir.as_ref();
diff --git a/aws/rust-runtime/aws-credential-types/Cargo.toml b/aws/rust-runtime/aws-credential-types/Cargo.toml
index ac5886fa73..ec4ebea555 100644
--- a/aws/rust-runtime/aws-credential-types/Cargo.toml
+++ b/aws/rust-runtime/aws-credential-types/Cargo.toml
@@ -15,20 +15,11 @@ test-util = []
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async" }
aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types" }
aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] }
-fastrand = "2.0.0"
-tokio = { version = "1.23.1", features = ["sync"] }
-tracing = "0.1"
zeroize = "1"
[dev-dependencies]
-aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async", features = ["rt-tokio", "test-util"] }
-
-# used to test compatibility
-async-trait = "0.1.51"
-env_logger = "0.10.0"
-
+async-trait = "0.1.51" # used to test compatibility
tokio = { version = "1.23.1", features = ["full", "test-util", "rt"] }
-tracing-test = "0.2.4"
[package.metadata.docs.rs]
all-features = true
diff --git a/aws/rust-runtime/aws-credential-types/external-types.toml b/aws/rust-runtime/aws-credential-types/external-types.toml
index 88a5088190..e1d82c7db4 100644
--- a/aws/rust-runtime/aws-credential-types/external-types.toml
+++ b/aws/rust-runtime/aws-credential-types/external-types.toml
@@ -1,6 +1,7 @@
allowed_external_types = [
"aws_smithy_async::rt::sleep::AsyncSleep",
"aws_smithy_async::rt::sleep::SharedAsyncSleep",
+ "aws_smithy_runtime_api::client::identity::ResolveIdentity",
"aws_smithy_types::config_bag::storable::Storable",
"aws_smithy_types::config_bag::storable::StoreReplace",
"aws_smithy_types::config_bag::storable::Storer",
diff --git a/aws/rust-runtime/aws-credential-types/src/cache.rs b/aws/rust-runtime/aws-credential-types/src/cache.rs
deleted file mode 100644
index a1351d0f9c..0000000000
--- a/aws/rust-runtime/aws-credential-types/src/cache.rs
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-//! Types and traits for enabling caching
-
-mod expiring_cache;
-mod lazy_caching;
-mod no_caching;
-
-pub use expiring_cache::ExpiringCache;
-pub use lazy_caching::Builder as LazyBuilder;
-use no_caching::NoCredentialsCache;
-
-use crate::provider::{future, SharedCredentialsProvider};
-use aws_smithy_types::config_bag::{Storable, StoreReplace};
-use std::sync::Arc;
-
-/// Asynchronous Cached Credentials Provider
-pub trait ProvideCachedCredentials: Send + Sync + std::fmt::Debug {
- /// Returns a future that provides cached credentials.
- fn provide_cached_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
- where
- Self: 'a;
-}
-
-/// Credentials cache wrapper that may be shared
-///
-/// Newtype wrapper around `ProvideCachedCredentials` that implements `Clone` using an internal
-/// `Arc`.
-#[derive(Clone, Debug)]
-pub struct SharedCredentialsCache(Arc);
-
-impl SharedCredentialsCache {
- /// Create a new `SharedCredentialsCache` from `ProvideCachedCredentials`
- ///
- /// The given `cache` will be wrapped in an internal `Arc`. If your
- /// cache is already in an `Arc`, use `SharedCredentialsCache::from(cache)` instead.
- pub fn new(provider: impl ProvideCachedCredentials + 'static) -> Self {
- Self(Arc::new(provider))
- }
-}
-
-impl AsRef for SharedCredentialsCache {
- fn as_ref(&self) -> &(dyn ProvideCachedCredentials + 'static) {
- self.0.as_ref()
- }
-}
-
-impl From> for SharedCredentialsCache {
- fn from(cache: Arc) -> Self {
- SharedCredentialsCache(cache)
- }
-}
-
-impl ProvideCachedCredentials for SharedCredentialsCache {
- fn provide_cached_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
- where
- Self: 'a,
- {
- self.0.provide_cached_credentials()
- }
-}
-
-impl Storable for SharedCredentialsCache {
- type Storer = StoreReplace;
-}
-
-#[derive(Clone, Debug)]
-pub(crate) enum Inner {
- Lazy(lazy_caching::Builder),
- NoCaching,
-}
-
-/// `CredentialsCache` allows for configuring and creating a credentials cache.
-///
-/// # Examples
-///
-/// ```no_run
-/// use aws_credential_types::Credentials;
-/// use aws_credential_types::cache::CredentialsCache;
-/// use aws_credential_types::credential_fn::provide_credentials_fn;
-/// use aws_credential_types::provider::SharedCredentialsProvider;
-///
-/// let credentials_cache = CredentialsCache::lazy_builder()
-/// .into_credentials_cache()
-/// .create_cache(SharedCredentialsProvider::new(provide_credentials_fn(|| async {
-/// // An async process to retrieve credentials would go here:
-/// Ok(Credentials::new(
-/// "example",
-/// "example",
-/// None,
-/// None,
-/// "my_provider_name"
-/// ))
-/// })));
-/// ```
-#[derive(Clone, Debug)]
-pub struct CredentialsCache {
- pub(crate) inner: Inner,
-}
-
-impl CredentialsCache {
- /// Creates a [`CredentialsCache`] from the default [`LazyBuilder`].
- pub fn lazy() -> Self {
- Self::lazy_builder().into_credentials_cache()
- }
-
- /// Returns the default [`LazyBuilder`].
- pub fn lazy_builder() -> LazyBuilder {
- lazy_caching::Builder::new()
- }
-
- /// Creates a [`CredentialsCache`] that offers no caching ability.
- pub fn no_caching() -> Self {
- Self {
- inner: Inner::NoCaching,
- }
- }
-
- /// Creates a [`SharedCredentialsCache`] wrapping a concrete caching implementation.
- pub fn create_cache(self, provider: SharedCredentialsProvider) -> SharedCredentialsCache {
- match self.inner {
- Inner::Lazy(builder) => SharedCredentialsCache::new(builder.build(provider)),
- Inner::NoCaching => SharedCredentialsCache::new(NoCredentialsCache::new(provider)),
- }
- }
-}
-
-impl Storable for CredentialsCache {
- type Storer = StoreReplace;
-}
diff --git a/aws/rust-runtime/aws-credential-types/src/cache/expiring_cache.rs b/aws/rust-runtime/aws-credential-types/src/cache/expiring_cache.rs
deleted file mode 100644
index 67556aad9b..0000000000
--- a/aws/rust-runtime/aws-credential-types/src/cache/expiring_cache.rs
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-use std::future::Future;
-use std::marker::PhantomData;
-use std::sync::Arc;
-use std::time::{Duration, SystemTime};
-use tokio::sync::{OnceCell, RwLock};
-
-/// Expiry-aware cache
-///
-/// [`ExpiringCache`] implements two important features:
-/// 1. Respect expiry of contents
-/// 2. Deduplicate load requests to prevent thundering herds when no value is present.
-#[derive(Debug)]
-pub struct ExpiringCache {
- /// Amount of time before the actual expiration time
- /// when the value is considered expired.
- buffer_time: Duration,
- value: Arc>>,
- _phantom: PhantomData,
-}
-
-impl Clone for ExpiringCache {
- fn clone(&self) -> Self {
- Self {
- buffer_time: self.buffer_time,
- value: self.value.clone(),
- _phantom: Default::default(),
- }
- }
-}
-
-impl ExpiringCache
-where
- T: Clone,
-{
- /// Creates `ExpiringCache` with the given `buffer_time`.
- pub fn new(buffer_time: Duration) -> Self {
- ExpiringCache {
- buffer_time,
- value: Arc::new(RwLock::new(OnceCell::new())),
- _phantom: Default::default(),
- }
- }
-
- #[cfg(test)]
- async fn get(&self) -> Option
- where
- T: Clone,
- {
- self.value
- .read()
- .await
- .get()
- .cloned()
- .map(|(creds, _expiry)| creds)
- }
-
- /// Attempts to refresh the cached value with the given future.
- /// If multiple threads attempt to refresh at the same time, one of them will win,
- /// and the others will await that thread's result rather than multiple refreshes occurring.
- /// The function given to acquire a value future, `f`, will not be called
- /// if another thread is chosen to load the value.
- pub async fn get_or_load(&self, f: F) -> Result
- where
- F: FnOnce() -> Fut,
- Fut: Future