RFC: Finding New Home for Credential Types
Status: Implemented in smithy-rs#2108
Applies to: clients
This RFC supplements RFC 28 and discusses for the selected design where to place the types for credentials providers, credentials caching, and everything else that comes with them.
It is assumed that the primary motivation behind the introduction of type safe credentials caching remains the same as the preceding RFC.
Assumptions
This document assumes that the following items in the changes checklist in the preceding RFC have been implemented:
-
Implement
CredentialsCache
with itsLazy
variant and builder -
Add the
credentials_cache
method toConfigLoader
-
Rename
SharedCredentialsProvider
toSharedCredentialsCache
-
Remove
ProvideCredentials
impl fromLazyCachingCredentialsProvider
-
Rename
LazyCachingCredentialsProvider
->LazyCredentialsCache
-
Refactor the SDK
Config
code generator to be consistent withConfigLoader
Problems
Here is how our attempt to implement the selected design in the preceding RFC can lead to an obstacle. Consider this code snippet we are planning to support:
let sdk_config = aws_config::from_env()
.credentials_cache(CredentialsCache::lazy())
.load()
.await;
let client = aws_sdk_s3::Client::new(&sdk_config);
A CredentialsCache
created by CredentialsCache::lazy()
above will internally go through three crates before the variable client
has been created:
aws-config
: after it has been passed toaws_config::ConfigLoader::credentials_cache
// in lib.rs
impl ConfigLoader {
// --snip--
pub fn credentials_cache(mut self, credentials_cache: CredentialsCache) -> Self {
self.credentials_cache = Some(credentials_cache);
self
}
// --snip--
}
aws-types
: afteraws_config::ConfigLoader::load
has passed it toaws_types::sdk_config::Builder::credentials_cache
// in sdk_config.rs
impl Builder {
// --snip--
pub fn credentials_cache(mut self, cache: CredentialsCache) -> Self {
self.set_credentials_cache(Some(cache));
self
}
// --snip--
}
aws-sdk-s3
: afteraws_sdk_s3::Client::new
has been called with the variablesdk_config
// in client.rs
impl Client {
// --snip--
pub fn new(sdk_config: &aws_types::sdk_config::SdkConfig) -> Self {
Self::from_conf(sdk_config.into())
}
// --snip--
}
calls
// in config.rs
impl From<&aws_types::sdk_config::SdkConfig> for Builder {
fn from(input: &aws_types::sdk_config::SdkConfig) -> Self {
let mut builder = Builder::default();
builder = builder.region(input.region().cloned());
builder.set_endpoint_resolver(input.endpoint_resolver().clone());
builder.set_retry_config(input.retry_config().cloned());
builder.set_timeout_config(input.timeout_config().cloned());
builder.set_sleep_impl(input.sleep_impl());
builder.set_credentials_cache(input.credentials_cache().cloned());
builder.set_credentials_provider(input.credentials_provider().cloned());
builder.set_app_name(input.app_name().cloned());
builder.set_http_connector(input.http_connector().cloned());
builder
}
}
impl From<&aws_types::sdk_config::SdkConfig> for Config {
fn from(sdk_config: &aws_types::sdk_config::SdkConfig) -> Self {
Builder::from(sdk_config).build()
}
}
What this all means is that CredentialsCache
needs to be accessible from aws-config
, aws-types
, and aws-sdk-s3
(SDK client crates, to be more generic). We originally assumed that CredentialsCache
would be defined in aws-config
along with LazyCredentialsCache
, but the assumption no longer holds because aws-types
and aws-sdk-s3
do not depend upon aws-config
.
Therefore, we need to find a new place in which to create credentials caches accessible from the aforementioned crates.
Proposed Solution
We propose to move the following items to a new crate called aws-credential-types
:
- All items in
aws_types::credentials
and their dependencies - All items in
aws_config::meta::credentials
and their dependencies
For the first bullet point, we move types and traits associated with credentials out of aws-types
. Crucially, the ProvideCredentials
trait now lives in aws-credential-types
.
For the second bullet point, we move the items related to credentials caching. CredentialsCache
with its Lazy
variant and builder lives in aws-credential-types
and CredentialsCache::create_cache
will be marked as pub
. One area where we make an adjustment, though, is that LazyCredentialsCache
depends on aws_types::os_shim_internal::TimeSource
so we need to move TimeSource
into aws-credentials-types
as well.
A result of the above arrangement will give us the following module dependencies (only showing what's relevant):
- :+1:
aws_types::sdk_config::Builder
and a service clientconfig::Builder
can create aSharedCredentialsCache
with a concrete type of credentials cache. - :+1: It avoids cyclic crate dependencies.
- :-1: There is one more AWS runtime crate to maintain and version.
Rejected Alternative
An alternative design is to move the following items to a separate crate (tentatively called aws-XXX
):
- All items in
aws_types::sdk_config
, i.e.SdkConfig
and its builder - All items in
aws_types::credentials
and their dependencies - All items in
aws_config::meta::credentials
and their dependencies
The reason for the first bullet point is that the builder needs to be somewhere it has access to the credentials caching factory function, CredentialsCache::create_cache
. The factory function is in aws-XXX
and if the builder stayed in aws-types
, it would cause a cyclic dependency between those two crates.
A result of the above arrangement will give us the following module dependencies:
We have dismissed this design mainly because we try moving out of the aws-types
create as little as possible. Another downside is that SdkConfig
sitting together with the items for credentials provider & caching does not give us a coherent mental model for the aws-XXX
crate, making it difficult to choose the right name for XXX
.
Changes Checklist
The following list does not repeat what is listed in the preceding RFC but does include those new mentioned in the Assumptions
section:
-
Create
aws-credential-types
-
Move all items in
aws_types::credentials
and their dependencies to theaws-credential-types
crate -
Move all items in
aws_config::meta::credentials
and their dependencies to theaws-credential-types
crate - Update use statements and fully qualified names in the affected places