Unverified Commit d040f76f authored by ysaito1001's avatar ysaito1001 Committed by GitHub
Browse files

Ensure SDK credential cache type safety (#2122)

* Add the `aws-credential-types` crate

This commit adds a new crate `aws-credential-types` to the `rust-runtime`
workspace. This lays the groundwork for being able to create a
`LazyCachingCredentialsProvider` outside the `aws-config` crate according
to the proposed solution in https://github.com/awslabs/smithy-rs/pull/2082

.

We have moved the following into this new crate:
- Items in aws_types::credentials and and their dependencies
- Items in aws_config::meta::credentials and their dependencies

Finally, the crate comes with auxiliary files that are present in the
other crates in the `rust-runtime` workspace such as `external-types.toml`.

* Make `aws-types` depend on `aws-credential-types`

The credentials module has been moved from the `aws-types` crate to the
`aws-credential-types` crate. This leads to some of the items in the
`aws-types` crate adjusting their use statements to point to
`aws-credential-types`.

The `TimeSource` struct has also been moved to `aws-credential-types`
because it is used by `LazyCachingCredentialsProvider`. We have decided
to move it instead of duplicating it because `aws-config` was creating
a `TimeSource` from `aws-types` and then passing it to the builder for
`LazyCachingCredentialsProvider`. If we had duplicated the implementation
of `TimeSource` in `aws-credential-types`, two `TimeSource` implementations
would have been considered different types and the said use case in
`aws-config` would have been broken.

* Make `aws-config` depend on `aws-credential-types`

The `cache` module and modules in `meta::credentials` (except for `chain`)
have been moved to `aws-credential-types`. Again, the goal of restructuring
is to allow `LazyCachingCredentialsProvider` to be created outside the
`aws-config` crate. While doing so, we try not moving all the default
credential provider implementations.

* Make `aws-http` depend on `aws-credential-types`

This commit adjusts the use statements for the items that have been moved
from the `aws-types` crate to the `aws-credential-types` crate.

* Make `aws-inlineable` depend on `aws-credential-types`

This commit adjusts the use statements for the items that have been moved
from the `aws-types` crate to the `aws-credential-types` crate.

* Make `aws-sig-auth` depend on `aws-credential-types`

This commit adjusts the use statements for the items that have been moved
from the `aws-types` crate to the `aws-credential-types` crate.

* Emit `aws-credential-types` to the build directory

This commit adds `aws-credential-types` to AWS_SDK_RUNTIME so that
the build command `/gradlew :aws:sdk:assemble` can generate the crate
into sdk/build/aws-sdk.

* Make codegen aware of `aws-credential-types`

This commit allows the codegen to handle the `aws-credential-types` crate.
The items that have been moved from `aws-types` should now be prefixed with
`aws-credential-types` when generating fully qualified names.

* Make `dynamo-tests` depend on `aws-credential-types`

This commit adjusts the use statements for the items that have been moved
from the `aws-types` crate to the `aws-credential-types` crate.

* Make `s3-tests` depend on `aws-credential-types`

This commit adjusts the use statements for the items that have been moved
from the `aws-types` crate to the `aws-credential-types` crate.

* Make `s3control` depend on `aws-credential-types`

This commit adjusts the use statements for the items that have been moved
from the `aws-types` crate to the `aws-credential-types` crate.

* Update external-types.xml in rust-runtime crates

This commit fixes CI failures related to `cargo check-external-types`
in ec994be.

* Update the file permission on additional-ci

* Remove unused dependency from aws-credential-types

* Clean up features for aws-credential-types

This commit fixes a CI failure where the feature hardcoded-credentials
needed other features, aws-smithy-async/rt-tokio and tokio/rt, for the
test code to compile with --no-default-features.

* Update sdk-external-types.toml

* Update aws/rust-runtime/aws-credential-types/Cargo.toml

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>

* Update aws/rust-runtime/aws-credential-types/README.md

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>

* Update aws/rust-runtime/aws-credential-types/README.md

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>

* Update aws/rust-runtime/aws-credential-types/additional-ci

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>

* Update aws/rust-runtime/aws-credential-types/src/lib.rs

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>

* Reduce re-exports from `aws-credential-types`

This commit reduces the number of re-exports from `aws-credential-types`.
The rationale here is that if we add more items to this crate later on,
we may get some name collisions in root. Since this crate is not used by
our customers directly, it is acceptable for items to take a bit of typing
to get to.

* Fix broken intra doc link

This commit fixes a broken intra doc link that went unnoticed because the
offending link was behind the feature `hardcoded-credentials`.

* Introduce type and trait for credential caching

This commit introduces the following items in the `aws-credential-types`
crate:
* CredentialsCache
* ProvideCachedCredentials

`CredentialsCache` is a struct a user will be interacting with when creating
a credentials cache; the user no longer creates a concrete credentials cache
directly, and instead it is taken care of by `CredentialsCache` behind the
scene.
`ProvideCachedCredentials` is a trait that will be implemented by concrete
credentials caches.

Furthermore, this commit renames the following structs according to the RFC
https://github.com/awslabs/smithy-rs/pull/1842

:
* SharedCredentialsProvider -> SharedCredentialsCache
* LazyCachingCredentialsProvider -> LazyCredentialsCache

* Add `credentials_cache` to `SdkConfig` and to builder

This commit adds a new field `credentials_cache` to `SdkConfig`. It also
adds a new method `credentials_cache` to `sdk_config::Builder`. They
will help a `CredentialsCache` be threaded through from `ConfigLoader`
to a service specific client's `config::Builder`, which will be
implemented in a subsequent commit.

* Put `SharedCredentialsCache` into the property bag

This commit updates what goes into the property bag. Now that
`SharedCredentialsProvider` has been renamed to `SharedCredentialsCache`,
that's what goes into the property bag. Once a `SharedCredentialsCache`
is retrieved from the bag, credentials can be obtained by calling
`provide_cached_credentials`.

* Thread through `credentials_cache` to service client

This commit threads through `credentials_cache` to service client's
`Config` and its builder. The builder will be the single-sourced place
for creating a credentials cache.

* Update `aws-config` to use `CredentialsCache`

This commit updates `aws-config` to use `CredentialsCache`. Specifically,
* `ConfigLoader` now has `credentials_cache` to take `CredentialsCache`
* No more `LazyCachingCredentialsProvider` in `DefaultCredentialsChain`
* No more `LazyCachingCredentialsProvider` in `AssumeRoleProvider`

The second and third bullet points are a result of a credentials cache
being composed in a service client's `config::Builder` rather than
`DefaultCredentialsChain` or `AssumeRoleProvider` holding it as its field.

* Update sdk integration tests

This commit bulk updates the integration tests for SDK. Most updates
replace the previous `SharedCredentialsProvider::new` with `Arc::new`.

A more subtle but important change is to respect the `sleep_impl` field
within the build method of a Config builder, making sure to thread it
a default `LazyCredentialsCache` created within the build method. If we
missed this step, the default constructed `LazyCredentialsCache` would
later use the default Tokio sleep impl even during tests that exercise
different async runtime, causing them to fail.

* Update aws/rust-runtime/aws-credential-types/README.md

Co-authored-by: default avatarZelda Hessler <zhessler@amazon.com>

* Rename variants of `aws_credential_types::time_source::Inner`

This commit addresses https://github.com/awslabs/smithy-rs/pull/2108#discussion_r1053637722

* Split the unit test for `time_source` into two

This commit addresses https://github.com/awslabs/smithy-rs/pull/2108#discussion_r1053638381

* Update CHANGELOG.next.toml

* Fix test failures in CI coming from `aws-inlineable`

This commit fixes test failures in CI coming from the integration test in
the `aws-inlineable` crate. Commit ea47572 should have included this
change.

* Update external-types TOML files

* Clean up offending use statements left after merging main

* Remove moved module wrongly brought in after merging main

* Remove `credentials_cache` from `Builder` for `DefaultCredentialsChain`

This commit removes a field `credentials_cache` from the `Builder` for
`DefaultCredentialsChain` as it no longer stores `LazyCredentialsCache`.
Furthermore, we have also removed methods on the builder that referred
to the field `credentials_cache`.

After this commit, certain use cases will be broken, i.e. when a user
sets timeout for loading credentials via `load_timeout` on the builder,
the configured timeout will be dropped on the floor because it will not
be threaded through the field `credentials_cache`. We will later provide
instructions for how to update those use cases with our new set of APIs.

* Remove `configure` from `LazyCredentialsCache` builder

This commit removes the `configure` method from the builder for
`LazyCredentialsCache`. We tried our best to keep it when we had moved
the builder from `aws-config` but had to modify the method signature to
destructure `ProviderCondig` to obtain the two fields out of it
(`ProviderConfig` lives in `aws-config` so cannot be passed to the builder
for `LazyCredentialsCache` which lives in `aws-credential-types`).

Given `configure` is technically meant for credentials providers, which
`LazyCredentialsCache` is not anymore, we might as well remove it and
accomplish the same effect by having customers use both `time_source` and
`set_sleep` on the builder instead.

* Update CHANGELOG.next.toml

* Update CHANGELOG.next.toml

* Use unwrap_or_else to simplify two assignments

This commit addresses https://github.com/awslabs/smithy-rs/pull/2122#discussion_r1056497419

* Add doc link to `CredentialsCache` to builder method

This commit addresses https://github.com/awslabs/smithy-rs/pull/2122#discussion_r1056500448.
In addition, it moves rustdoc for `LazyCredentialsCache` to `LazyBuilder`
as `LazyCredentialsCache` has been made `pub(crate)` from `pub` and
`LazyBuilder` is now a `pub` item instead.

* Make `CredentialsCache` configurable in `AssumeRoleProviderBuilder`

This commit addresses https://github.com/awslabs/smithy-rs/pull/2122#discussion_r1066400431.
It allows users to pass their `CredentialsCache` to the builder just as
they do in `SdkConfig`.

* Update CHANGELOG.next.toml

This commit addresses https://github.com/awslabs/smithy-rs/pull/2122#discussion_r1066400431

.

Co-authored-by: default avatarYuki Saito <awsaito@amazon.com>
Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>
Co-authored-by: default avatarZelda Hessler <zhessler@amazon.com>
parent 9f905179
Loading
Loading
Loading
Loading
+354 −0
Original line number Diff line number Diff line
@@ -16,3 +16,357 @@ message = "`@sparse` list shapes and map shapes with constraint traits and with
references = ["smithy-rs#2213"]
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "server"}
author = "david-perez"

[[aws-sdk-rust]]
message = """Integrate Endpoints 2.0 into the Rust SDK. Endpoints 2.0 enables features like S3 virtual addressing & S3
object lambda. As part of this change, there are several breaking changes although efforts have been made to deprecate
where possible to smooth the upgrade path.
1. `aws_smithy_http::endpoint::Endpoint` and the `endpoint_resolver` methods have been deprecated. In general, these usages
   should be replaced with usages of `endpoint_url` instead. `endpoint_url` accepts a string so an `aws_smithy_http::Endpoint`
   does not need to be constructed. This structure and methods will be removed in a future release.
2. The `endpoint_resolver` method on `<service>::config::Builder` now accepts a service specific endpoint resolver instead
   of an implementation of `ResolveAwsEndpoint`. Most users will be able to replace these usages with a usage of `endpoint_url`.
3. `ResolveAwsEndpoint` has been deprecated and will be removed in a future version of the SDK.
4. The SDK does not support "pseudo regions" anymore. Specifically, regions like `iam-fips` will no longer resolve to a FIPS endpoint.
"""
references = ["smithy-rs#1784", "smithy-rs#2074"]
meta = { "breaking" = true, "tada" = true, "bug" = false }
author = "rcoh"

[[aws-sdk-rust]]
message = """Add additional configuration parameters to `aws_sdk_s3::Config`.

The launch of endpoints 2.0 includes more configuration options for S3. The default behavior for endpoint resolution has
been changed. Before, all requests hit the path-style endpoint. Going forward, all requests that can be routed to the
virtually hosted bucket will be routed there automatically.
- `force_path_style`: Requests will now default to the virtually-hosted endpoint `<bucketname>.s3.<region>.amazonaws.com`
- `use_arn_region`: Enables this client to use an ARN’s region when constructing an endpoint instead of the client’s configured region.
- `accelerate`: Enables this client to use S3 Transfer Acceleration endpoints.

Note: the AWS SDK for Rust does not currently support Multi Region Access Points (MRAP).
"""
references = ["smithy-rs#1784", "smithy-rs#2074"]
meta = { "breaking" = true, "tada" = true, "bug" = false }
author = "rcoh"

[[smithy-rs]]
message = "In 0.52, `@length`-constrained collection shapes whose members are not constrained made the server code generator crash. This has been fixed."
references = ["smithy-rs#2103"]
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "server" }
author = "david-perez"

[[smithy-rs]]
message = "The Rust client codegen plugin is now called `rust-client-codegen` instead of `rust-codegen`. Be sure to update your `smithy-build.json` files to refer to the correct plugin name."
references = ["smithy-rs#2099"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "jdisanti"

[[smithy-rs]]
message = "Client codegen plugins need to define a service named `software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator` (this is the new file name for the plugin definition in `resources/META-INF/services`)."
references = ["smithy-rs#2099"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "jdisanti"

[[smithy-rs]]
message = "Server codegen plugins need to define a service named `software.amazon.smithy.rust.codegen.server.smithy.customize.ServerCodegenDecorator` (this is the new file name for the plugin definition in `resources/META-INF/services`)."
references = ["smithy-rs#2099"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "server" }
author = "jdisanti"

[[aws-sdk-rust]]
message = """
Move types for AWS SDK credentials to a separate crate.
A new AWS runtime crate called `aws-credential-types` has been introduced. Types for AWS SDK credentials have been moved to that crate from `aws-config` and `aws-types`. The new crate is placed at the top of the dependency graph among AWS runtime crates with the aim of the downstream crates having access to the types defined in it.
"""
references = ["smithy-rs#2108"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "ysaito1001"

[[smithy-rs]]
message = "Servers support the `@default` trait: models can specify default values. Default values will be automatically supplied when not manually set."
references = ["smithy-rs#1879"]
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "server" }
author = "82marbag"

[[smithy-rs]]
message = "The constraint `@length` on non-streaming blob shapes is supported."
references = ["smithy-rs#2131"]
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "server" }
author = "82marbag"

[[aws-sdk-rust]]
references = ["smithy-rs#2152"]
meta = { "breaking" = false, "tada" = false, "bug" = false }
author = "rcoh"
message = """Add support for overriding profile name and profile file location across all providers. Prior to this change, each provider needed to be updated individually.

### Before
```rust
use aws_config::profile::{ProfileFileCredentialsProvider, ProfileFileRegionProvider};
use aws_config::profile::profile_file::{ProfileFiles, ProfileFileKind};

let profile_files = ProfileFiles::builder()
    .with_file(ProfileFileKind::Credentials, "some/path/to/credentials-file")
    .build();
let credentials_provider = ProfileFileCredentialsProvider::builder()
    .profile_files(profile_files.clone())
    .build();
let region_provider = ProfileFileRegionProvider::builder()
    .profile_files(profile_files)
    .build();

let sdk_config = aws_config::from_env()
    .credentials_provider(credentials_provider)
    .region(region_provider)
    .load()
    .await;
```

### After
```rust
use aws_config::profile::{ProfileFileCredentialsProvider, ProfileFileRegionProvider};
use aws_config::profile::profile_file::{ProfileFiles, ProfileFileKind};

let profile_files = ProfileFiles::builder()
    .with_file(ProfileFileKind::Credentials, "some/path/to/credentials-file")
    .build();
let sdk_config = aws_config::from_env()
    .profile_files(profile_files)
    .load()
    .await;
/// ```
"""

[[smithy-rs]]
message = "Fix bug where string default values were not supported for endpoint parameters"
references = ["smithy-rs#2150"]
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "client" }
author = "rcoh"

[[aws-sdk-rust]]
references = ["smithy-rs#2162"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
message = "`aws_config::profile::retry_config` && `aws_config::environment::retry_config` have been removed. Use `aws_config::default_provider::retry_config` instead."
author = "rcoh"

[[smithy-rs]]
references = ["smithy-rs#2170", "aws-sdk-rust#706"]
meta = { "breaking" = false, "tada" = false, "bug" = true }
message = "Remove the webpki-roots feature from `hyper-rustls`"
author = "rcoh"

[[aws-sdk-rust]]
references = ["smithy-rs#2168"]
meta = { "breaking" = false, "tada" = true, "bug" = false }
message = """Add support for resolving FIPS and dual-stack endpoints.

FIPS and dual-stack endpoints can each be configured in multiple ways:
1. Automatically from the environment and AWS profile
2. Across all clients loaded from the same `SdkConfig` via `from_env().use_dual_stack(true).load().await`
3. At a client level when constructing the configuration for an individual client.

Note: Not all services support FIPS and dual-stack.
"""
author = "rcoh"

[[aws-sdk-rust]]
message = """
Improve SDK credentials caching through type safety. `LazyCachingCredentialsProvider` has been renamed to `LazyCredentialsCache` and is no longer treated as a credentials provider. Furthermore, you do not create a `LazyCredentialsCache` directly, and instead you interact with `CredentialsCache`. This introduces the following breaking changes.

If you previously used `LazyCachingCredentialsProvider`, you can replace it with `CredentialsCache`.
<details>
<summary>Example</summary>

Before:
```rust
use aws_config::meta::credentials::lazy_caching::LazyCachingCredentialsProvider;
use aws_types::provider::ProvideCredentials;

fn make_provider() -> impl ProvideCredentials {
    // --snip--
}

let credentials_provider =
    LazyCachingCredentialsProvider::builder()
        .load(make_provider())
        .build();

let sdk_config = aws_config::from_env()
    .credentials_provider(credentials_provider)
    .load()
    .await;

let client = aws_sdk_s3::Client::new(&sdk_config);
```

After:
```rust
use aws_credential_types::cache::CredentialsCache;
use aws_types::provider::ProvideCredentials;
use std::sync::Arc;

fn make_provider() -> impl ProvideCredentials {
    // --snip--
}

// Wrapping a result of `make_provider` in `LazyCredentialsCache` is done automatically.
let sdk_config = aws_config::from_env()
    .credentials_cache(CredentialsCache::lazy()) // This line can be omitted because it is on by default.
    .credentials_provider(Arc::new(make_provider()))
    .load()
    .await;

let client = aws_sdk_s3::Client::new(&sdk_config);
```

If you previously configured a `LazyCachingCredentialsProvider`, you can use the builder for `LazyCredentialsCache` instead.

Before:
```rust
use aws_config::meta::credentials::lazy_caching::LazyCachingCredentialsProvider;
use aws_types::provider::ProvideCredentials;
use std::time::Duration;

fn make_provider() -> impl ProvideCredentials {
    // --snip--
}

let credentials_provider =
    LazyCachingCredentialsProvider::builder()
        .load(make_provider())
        .load_timeout(Duration::from_secs(60)) // Configures timeout.
        .build();

let sdk_config = aws_config::from_env()
    .credentials_provider(credentials_provider)
    .load()
    .await;

let client = aws_sdk_s3::Client::new(&sdk_config);
```

After:
```rust
use aws_credential_types::cache::CredentialsCache;
use aws_types::provider::ProvideCredentials;
use std::sync::Arc;
use std::time::Duration;

fn make_provider() -> impl ProvideCredentials {
    // --snip--
}

let sdk_config = aws_config::from_env()
    .credentials_cache(
        CredentialsCache::lazy_builder()
            .load_timeout(Duration::from_secs(60)) // Configures timeout.
            .into_credentials_cache(),
    )
    .credentials_provider(Arc::new(make_provider()))
    .load()
    .await;

let client = aws_sdk_s3::Client::new(&sdk_config);
```

The examples above only demonstrate how to use `credentials_cache` and `credentials_provider` methods on `aws_config::ConfigLoader` but the same code update can be applied when you interact with `aws_types::sdk_config::Builder` or the builder for a service-specific config, e.g. `aws_sdk_s3::config::Builder`.

</details>


If you previously configured a `DefaultCredentialsChain` by calling `load_timeout`, `buffer_time`, or `default_credential_expiration` on its builder, you need to call the same set of methods on the builder for `LazyCredentialsCache` instead.
<details>
<summary>Example</summary>

Before:
```rust
use aws_config::default_provider::credentials::DefaultCredentialsChain;
use std::time::Duration;

let credentials_provider = DefaultCredentialsChain::builder()
    .buffer_time(Duration::from_secs(30))
    .default_credential_expiration(Duration::from_secs(20 * 60))
    .build()
    .await;

let sdk_config = aws_config::from_env()
    .credentials_provider(credentials_provider)
    .load()
    .await;

let client = aws_sdk_s3::Client::new(&sdk_config);
```

After:
```rust
use aws_config::default_provider::credentials::default_provider;
use aws_credential_types::cache::CredentialsCache;
use std::sync::Arc;
use std::time::Duration;

// Previously used methods no longer exist on the builder for `DefaultCredentialsChain`.
let credentials_provider = default_provider().await;

let sdk_config = aws_config::from_env()
    .credentials_cache(
        CredentialsCache::lazy_builder()
            .buffer_time(Duration::from_secs(30))
            .default_credential_expiration(Duration::from_secs(20 * 60))
            .into_credentials_cache(),
    )
    .credentials_provider(Arc::new(credentials_provider))
    .load()
    .await;

let client = aws_sdk_s3::Client::new(&sdk_config);
```

</details>
"""
references = ["smithy-rs#2122"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "ysaito1001"

[[aws-sdk-rust]]
message = """
The introduction of `CredentialsCache` comes with an accompanying type `SharedCredentialsCache`. This replaces `SharedCredentialsProvider` and as a result, `aws_http::auth:set_provider` has been updated to `aws_http::auth::set_credentials_cache`.

Before:
```rust
use aws_credential_types::Credentials;
use aws_credential_types::provider::SharedCredentialsProvider;
use aws_http::auth::set_provider;
use aws_smithy_http::body::SdkBody;
use aws_smithy_http::operation;

let mut req = operation::Request::new(http::Request::new(SdkBody::from("some body")));
let credentials = Credentials::new("example", "example", None, None, "my_provider_name");
set_provider(
    &mut req.properties_mut(),
    SharedCredentialsProvider::new(credentials),
);
```

After:
```rust
use aws_credential_types::Credentials;
use aws_credential_types::cache::{CredentialsCache, SharedCredentialsCache};
use aws_http::auth::set_credentials_cache;
use aws_smithy_http::body::SdkBody;
use aws_smithy_http::operation;
use std::sync::Arc;

let mut req = operation::Request::new(http::Request::new(SdkBody::from("some body")));
let credentials = Credentials::new("example", "example", None, None, "my_provider_name");
let credentials_cache = CredentialsCache::lazy_builder()
    .into_credentials_cache()
    .create_cache(Arc::new(credentials));
set_credentials_cache(
    &mut req.properties_mut(),
    SharedCredentialsCache::new(credentials_cache),
);
```
"""
references = ["smithy-rs#2122"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "ysaito1001"
+1 −1
Original line number Diff line number Diff line
@@ -3,9 +3,9 @@
# require manual version bumping every time an automated version bump
# to the exposed SDK crates happens.
allowed_external_types = [
   "aws_credential_types::cache::CredentialsCache",
   "aws_credential_types::provider::ProvideCredentials",
   "aws_credential_types::provider::Result",
   "aws_credential_types::provider::SharedCredentialsProvider",
   "aws_sdk_sts::model::PolicyDescriptorType",
   "aws_smithy_async::rt::sleep::AsyncSleep",
   "aws_smithy_client::bounds::SmithyConnector",
+5 −75
Original line number Diff line number Diff line
@@ -4,9 +4,7 @@
 */

use std::borrow::Cow;
use std::time::Duration;

use aws_credential_types::lazy_caching::{self, LazyCachingCredentialsProvider};
use aws_credential_types::provider::{self, future, ProvideCredentials};
use tracing::Instrument;

@@ -60,7 +58,9 @@ pub async fn default_provider() -> impl ProvideCredentials {
///     .build();
/// ```
#[derive(Debug)]
pub struct DefaultCredentialsChain(LazyCachingCredentialsProvider);
pub struct DefaultCredentialsChain {
    provider_chain: CredentialsProviderChain,
}

impl DefaultCredentialsChain {
    /// Builder for `DefaultCredentialsChain`
@@ -69,7 +69,7 @@ impl DefaultCredentialsChain {
    }

    async fn credentials(&self) -> provider::Result {
        self.0
        self.provider_chain
            .provide_credentials()
            .instrument(tracing::debug_span!("provide_credentials", provider = %"default_chain"))
            .await
@@ -92,7 +92,6 @@ pub struct Builder {
    web_identity_builder: crate::web_identity_token::Builder,
    imds_builder: crate::imds::credentials::Builder,
    ecs_builder: crate::ecs::Builder,
    credential_cache: lazy_caching::Builder,
    region_override: Option<Box<dyn ProvideRegion>>,
    region_chain: crate::default_provider::region::Builder,
    conf: Option<ProviderConfig>,
@@ -115,71 +114,6 @@ impl Builder {
        self
    }

    /// Timeout for the entire credential loading chain.
    ///
    /// Defaults to 5 seconds.
    pub fn load_timeout(mut self, timeout: Duration) -> Self {
        self.set_load_timeout(Some(timeout));
        self
    }

    /// Timeout for the entire credential loading chain.
    ///
    /// Defaults to 5 seconds.
    pub fn set_load_timeout(&mut self, timeout: Option<Duration>) -> &mut Self {
        self.credential_cache.set_load_timeout(timeout);
        self
    }

    /// Amount of time before the actual credential expiration time
    /// where credentials are considered expired.
    ///
    /// For example, if credentials are expiring in 15 minutes, and the buffer time is 10 seconds,
    /// then any requests made after 14 minutes and 50 seconds will load new credentials.
    ///
    /// Defaults to 10 seconds.
    pub fn buffer_time(mut self, buffer_time: Duration) -> Self {
        self.set_buffer_time(Some(buffer_time));
        self
    }

    /// Amount of time before the actual credential expiration time
    /// where credentials are considered expired.
    ///
    /// For example, if credentials are expiring in 15 minutes, and the buffer time is 10 seconds,
    /// then any requests made after 14 minutes and 50 seconds will load new credentials.
    ///
    /// Defaults to 10 seconds.
    pub fn set_buffer_time(&mut self, buffer_time: Option<Duration>) -> &mut Self {
        self.credential_cache.set_buffer_time(buffer_time);
        self
    }

    /// Default expiration time to set on credentials if they don't have an expiration time.
    ///
    /// This is only used if the given [`ProvideCredentials`] returns
    /// [`Credentials`](aws_credential_types::Credentials) that don't have their `expiry` set.
    /// This must be at least 15 minutes.
    ///
    /// Defaults to 15 minutes.
    pub fn default_credential_expiration(mut self, duration: Duration) -> Self {
        self.set_default_credential_expiration(Some(duration));
        self
    }

    /// Default expiration time to set on credentials if they don't have an expiration time.
    ///
    /// This is only used if the given [`ProvideCredentials`] returns
    /// [`Credentials`](aws_credential_types::Credentials) that don't have their `expiry` set.
    /// This must be at least 15 minutes.
    ///
    /// Defaults to 15 minutes.
    pub fn set_default_credential_expiration(&mut self, duration: Option<Duration>) -> &mut Self {
        self.credential_cache
            .set_default_credential_expiration(duration);
        self
    }

    /// Add an additional credential source for the ProfileProvider
    ///
    /// Assume role profiles may specify named credential sources:
@@ -252,12 +186,8 @@ impl Builder {
            .or_else("WebIdentityToken", web_identity_token_provider)
            .or_else("EcsContainer", ecs_provider)
            .or_else("Ec2InstanceMetadata", imds_provider);
        let cached_provider = self
            .credential_cache
            .configure(conf.sleep(), conf.time_source())
            .load(provider_chain);

        DefaultCredentialsChain(cached_provider.build())
        DefaultCredentialsChain { provider_chain }
    }
}

+40 −13
Original line number Diff line number Diff line
@@ -150,7 +150,8 @@ pub async fn load_from_env() -> aws_types::SdkConfig {
mod loader {
    use std::sync::Arc;

    use aws_credential_types::provider::{ProvideCredentials, SharedCredentialsProvider};
    use aws_credential_types::cache::CredentialsCache;
    use aws_credential_types::provider::ProvideCredentials;
    use aws_smithy_async::rt::sleep::{default_async_sleep, AsyncSleep};
    use aws_smithy_client::http_connector::{ConnectorSettings, HttpConnector};
    use aws_smithy_types::retry::RetryConfig;
@@ -177,7 +178,8 @@ mod loader {
    #[derive(Default, Debug)]
    pub struct ConfigLoader {
        app_name: Option<AppName>,
        credentials_provider: Option<SharedCredentialsProvider>,
        credentials_cache: Option<CredentialsCache>,
        credentials_provider: Option<Arc<dyn ProvideCredentials>>,
        endpoint_resolver: Option<Arc<dyn ResolveAwsEndpoint>>,
        endpoint_url: Option<String>,
        region: Option<Box<dyn ProvideRegion>>,
@@ -298,6 +300,25 @@ mod loader {
            self
        }

        /// Override the credentials cache used to build [`SdkConfig`](aws_types::SdkConfig).
        ///
        /// # Examples
        ///
        /// Override the credentials cache but load the default value for region:
        /// ```no_run
        /// # use aws_credential_types::cache::CredentialsCache;
        /// # async fn create_config() {
        /// let config = aws_config::from_env()
        ///     .credentials_cache(CredentialsCache::lazy())
        ///     .load()
        ///     .await;
        /// # }
        /// ```
        pub fn credentials_cache(mut self, credentials_cache: CredentialsCache) -> Self {
            self.credentials_cache = Some(credentials_cache);
            self
        }

        /// Override the credentials provider used to build [`SdkConfig`](aws_types::SdkConfig).
        ///
        /// # Examples
@@ -305,21 +326,22 @@ mod loader {
        /// Override the credentials provider but load the default value for region:
        /// ```no_run
        /// # use aws_credential_types::Credentials;
        /// # use std::sync::Arc;
        /// # fn create_my_credential_provider() -> Credentials {
        /// #     Credentials::new("example", "example", None, None, "example")
        /// # }
        /// # async fn create_config() {
        /// let config = aws_config::from_env()
        ///     .credentials_provider(create_my_credential_provider())
        ///     .credentials_provider(Arc::new(create_my_credential_provider()))
        ///     .load()
        ///     .await;
        /// # }
        /// ```
        pub fn credentials_provider(
            mut self,
            credentials_provider: impl ProvideCredentials + 'static,
            credentials_provider: Arc<dyn ProvideCredentials>,
        ) -> Self {
            self.credentials_provider = Some(SharedCredentialsProvider::new(credentials_provider));
            self.credentials_provider = Some(credentials_provider);
            self
        }

@@ -524,7 +546,9 @@ mod loader {
                    .await
            };

            let sleep_impl = if self.sleep.is_none() {
            let sleep_impl = if self.sleep.is_some() {
                self.sleep
            } else {
                if default_async_sleep().is_none() {
                    tracing::warn!(
                        "An implementation of AsyncSleep was requested by calling default_async_sleep \
@@ -535,8 +559,6 @@ mod loader {
                    );
                }
                default_async_sleep()
            } else {
                self.sleep
            };

            let timeout_config = if let Some(timeout_config) = self.timeout_config {
@@ -548,14 +570,18 @@ mod loader {
                    .await
            };

            let http_connector = if let Some(http_connector) = self.http_connector {
                http_connector
            } else {
            let http_connector = self.http_connector.unwrap_or_else(|| {
                HttpConnector::Prebuilt(default_connector(
                    &ConnectorSettings::from_timeout_config(&timeout_config),
                    sleep_impl.clone(),
                ))
            };
            });

            let credentials_cache = self.credentials_cache.unwrap_or_else(|| {
                let mut builder = CredentialsCache::lazy_builder().time_source(conf.time_source());
                builder.set_sleep(conf.sleep());
                builder.into_credentials_cache()
            });

            let use_fips = if let Some(use_fips) = self.use_fips {
                Some(use_fips)
@@ -574,7 +600,7 @@ mod loader {
            } else {
                let mut builder = credentials::DefaultCredentialsChain::builder().configure(conf);
                builder.set_region(region.clone());
                SharedCredentialsProvider::new(builder.build().await)
                Arc::new(builder.build().await)
            };

            let endpoint_resolver = self.endpoint_resolver;
@@ -583,6 +609,7 @@ mod loader {
                .region(region)
                .retry_config(retry_config)
                .timeout_config(timeout_config)
                .credentials_cache(credentials_cache)
                .credentials_provider(credentials_provider)
                .http_connector(http_connector);

+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ impl ProvideCredentials for ProfileFileCredentialsProvider {
/// ```
///
/// _Note: Profile providers to not implement any caching. They will reload and reparse the profile
/// from the file system when called. See [lazy_caching](aws_credential_types::lazy_caching::LazyCachingCredentialsProvider) for
/// from the file system when called. See [CredentialsCache](aws_credential_types::cache::CredentialsCache) for
/// more information about caching._
///
/// This provider supports several different credentials formats:
Loading