AWS SDK

AWS SDK

rev. ba98f30b52e51c6e715b0ae469e7a2e988c27d9a

Files changed:

tmp-codegen-diff/aws-sdk/README.md

@@ -1,1 +57,57 @@
   17     17   
   18     18   
> For a step-by-step guide including several advanced use cases, check out the [Developer Guide](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/welcome.html).
   19     19   
   20     20   
The SDK provides one crate per AWS service. You must add [Tokio](https://crates.io/crates/tokio) as a dependency within your Rust project to execute asynchronous code.
   21     21   
   22     22   
1. Create a new Rust project: `cargo new sdk-example`
   23     23   
2. Add dependencies to DynamoDB and Tokio to your **Cargo.toml** file:
   24     24   
   25     25   
    ```toml
   26     26   
    [dependencies]
   27         -
    aws-config = { version= "1.8.4", features = ["behavior-version-latest"] }
          27  +
    aws-config = { version= "1.8.3", features = ["behavior-version-latest"] }
   28     28   
    aws-sdk-dynamodb = "0.0.0-local"
   29     29   
    tokio = { version = "1", features = ["full"] }
   30     30   
    ```
   31     31   
   32     32   
3. Provide your AWS credentials with the default credential provider chain, which currently looks in:
   33     33   
   - Environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_REGION`
   34     34   
   - The default credentials files located in `~/.aws/config` and `~/.aws/credentials` (location can vary per platform)
   35     35   
   - Web Identity Token credentials from the environment or container (including EKS)
   36     36   
   - ECS Container Credentials (IAM roles for tasks)
   37     37   
   - EC2 Instance Metadata Service (IAM Roles attached to instance)

tmp-codegen-diff/aws-sdk/sdk/aws-config/Cargo.toml

@@ -1,1 +157,157 @@
    1      1   
# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
    2      2   
[package]
    3      3   
name = "aws-config"
    4         -
version = "1.8.4"
           4  +
version = "1.8.3"
    5      5   
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>", "Russell Cohen <rcoh@amazon.com>"]
    6      6   
description = "AWS SDK config and credential provider implementations."
    7      7   
edition = "2021"
    8      8   
exclude = ["test-data/*", "integration-tests/*"]
    9      9   
license = "Apache-2.0"
   10     10   
repository = "https://github.com/smithy-lang/smithy-rs"
   11     11   
[package.metadata.docs.rs]
   12     12   
all-features = true
   13     13   
targets = ["x86_64-unknown-linux-gnu"]
   14     14   
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
   15     15   
rustdoc-args = ["--cfg", "docsrs"]
   16     16   
   17     17   
[package.metadata.smithy-rs-release-tooling]
   18     18   
stable = true
   19     19   
[package.metadata.cargo-udeps.ignore]
   20     20   
normal = ["proc-macro2"]
   21     21   
   22     22   
[features]
   23     23   
behavior-version-latest = []
   24     24   
credentials-process = ["tokio/process"]
   25     25   
default = ["default-https-client", "rt-tokio", "credentials-process", "sso"]
   26     26   
rt-tokio = ["aws-smithy-async/rt-tokio", "aws-smithy-runtime/rt-tokio", "tokio/rt"]
   27     27   
client-hyper = ["aws-smithy-runtime/default-https-client"]
   28     28   
rustls = ["client-hyper"]
   29     29   
default-https-client = ["aws-smithy-runtime/default-https-client"]
   30     30   
sso = ["dep:aws-sdk-sso", "dep:aws-sdk-ssooidc", "dep:ring", "dep:hex", "dep:zeroize", "aws-smithy-runtime-api/http-auth"]
   31     31   
test-util = ["aws-runtime/test-util"]
   32     32   
allow-compilation = []
   33     33   
   34     34   
[dependencies]
   35     35   
bytes = "1.1.0"
   36     36   
http = "1"
   37     37   
url = "2.5.4"
   38     38   
fastrand = "2.3.0"
   39     39   
   40     40   
[dependencies.aws-credential-types]
   41     41   
path = "../aws-credential-types"
   42     42   
features = ["test-util"]
   43         -
version = "1.2.5"
          43  +
version = "1.2.4"
   44     44   
   45     45   
[dependencies.aws-runtime]
   46     46   
path = "../aws-runtime"
   47         -
version = "1.5.10"
          47  +
version = "1.5.9"
   48     48   
   49     49   
[dependencies.aws-sdk-sts]
   50     50   
path = "../sts"
   51     51   
default-features = false
   52     52   
version = "0.0.0-local"
   53     53   
   54     54   
[dependencies.aws-smithy-async]
   55     55   
path = "../aws-smithy-async"
   56     56   
version = "1.2.5"
   57     57   
   58     58   
[dependencies.aws-smithy-http]
   59     59   
path = "../aws-smithy-http"
   60     60   
version = "0.62.3"
   61     61   
   62     62   
[dependencies.aws-smithy-json]
   63     63   
path = "../aws-smithy-json"
   64     64   
version = "0.61.4"
   65     65   
   66     66   
[dependencies.aws-smithy-runtime]
   67     67   
path = "../aws-smithy-runtime"
   68     68   
features = ["client"]
   69         -
version = "1.8.6"
          69  +
version = "1.8.5"
   70     70   
   71     71   
[dependencies.aws-smithy-runtime-api]
   72     72   
path = "../aws-smithy-runtime-api"
   73     73   
features = ["client"]
   74         -
version = "1.8.7"
          74  +
version = "1.8.5"
   75     75   
   76     76   
[dependencies.aws-smithy-types]
   77     77   
path = "../aws-smithy-types"
   78     78   
version = "1.3.2"
   79     79   
   80     80   
[dependencies.aws-types]
   81     81   
path = "../aws-types"
   82     82   
version = "1.3.8"
   83     83   
   84     84   
[dependencies.time]
   85     85   
version = "0.3.4"
   86     86   
features = ["parsing"]
   87     87   
   88     88   
[dependencies.tokio]
   89     89   
version = "1.13.1"
   90     90   
features = ["sync"]
   91     91   
   92     92   
[dependencies.tracing]
   93     93   
version = "0.1"
   94     94   
   95     95   
[dependencies.aws-sdk-sso]
   96     96   
path = "../sso"
   97     97   
default-features = false
   98     98   
optional = true
   99     99   
version = "0.0.0-local"
  100    100   
  101    101   
[dependencies.ring]
  102    102   
version = "0.17.5"
  103    103   
optional = true
  104    104   
  105    105   
[dependencies.hex]
  106    106   
version = "0.4.3"
  107    107   
optional = true
  108    108   
  109    109   
[dependencies.zeroize]
  110    110   
version = "1"
  111    111   
optional = true
  112    112   
  113    113   
[dependencies.aws-sdk-ssooidc]
  114    114   
path = "../ssooidc"
  115    115   
default-features = false
  116    116   
optional = true
  117    117   
version = "0.0.0-local"
  118    118   
  119    119   
[dev-dependencies]
  120    120   
tracing-test = "0.2.4"
  121    121   
serde_json = "1"
  122    122   
  123    123   
[dev-dependencies.aws-smithy-async]
  124    124   
path = "../aws-smithy-async"
  125    125   
features = ["rt-tokio", "test-util"]
  126    126   
version = "1.2.5"
  127    127   
         128  +
[dev-dependencies.aws-smithy-runtime]
         129  +
path = "../aws-smithy-runtime"
         130  +
features = ["client", "test-util"]
         131  +
version = "1.8.5"
         132  +
  128    133   
[dev-dependencies.aws-smithy-http-client]
  129    134   
path = "../aws-smithy-http-client"
  130    135   
features = ["default-client", "test-util"]
  131    136   
version = "1.0.6"
  132    137   
  133         -
[dev-dependencies.aws-smithy-runtime]
  134         -
path = "../aws-smithy-runtime"
  135         -
features = ["client", "test-util"]
  136         -
version = "1.8.6"
  137         -
  138    138   
[dev-dependencies.aws-smithy-runtime-api]
  139    139   
path = "../aws-smithy-runtime-api"
  140    140   
features = ["test-util"]
  141         -
version = "1.8.7"
         141  +
version = "1.8.5"
  142    142   
  143    143   
[dev-dependencies.futures-util]
  144    144   
version = "0.3.29"
  145    145   
default-features = false
  146    146   
  147    147   
[dev-dependencies.tracing-subscriber]
  148    148   
version = "0.3.16"
  149    149   
features = ["fmt", "json"]
  150    150   
  151    151   
[dev-dependencies.tokio]

tmp-codegen-diff/aws-sdk/sdk/aws-config/fuzz/Cargo.toml

@@ -1,1 +30,30 @@
   13     13   
edition = "2021"
   14     14   
   15     15   
[package.metadata]
   16     16   
cargo-fuzz = true
   17     17   
   18     18   
[dependencies]
   19     19   
libfuzzer-sys = "=0.4.7"
   20     20   
   21     21   
[dependencies.aws-config]
   22     22   
path = ".."
   23         -
version = "1.8.4"
          23  +
version = "1.8.3"
   24     24   
   25     25   
[dependencies.aws-types]
   26     26   
path = "../../../sdk/build/aws-sdk/sdk/aws-types"
   27     27   
version = "1.3.8"
   28     28   
   29     29   
[workspace]
   30     30   
members = ["."]

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/credential_process.rs

@@ -1,1 +43,42 @@
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
#![cfg(feature = "credentials-process")]
    7      7   
    8      8   
//! Credentials Provider for external process
    9      9   
   10     10   
use crate::json_credentials::{json_parse_loop, InvalidJsonCredentials};
   11     11   
use crate::sensitive_command::CommandWithSensitiveArgs;
   12     12   
use aws_credential_types::attributes::AccountId;
   13         -
use aws_credential_types::credential_feature::AwsCredentialFeature;
   14     13   
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
   15     14   
use aws_credential_types::Credentials;
   16     15   
use aws_smithy_json::deserialize::Token;
   17     16   
use std::borrow::Cow;
   18     17   
use std::process::Command;
   19     18   
use std::time::SystemTime;
   20     19   
use time::format_description::well_known::Rfc3339;
   21     20   
use time::OffsetDateTime;
   22     21   
   23     22   
/// External process credentials provider
@@ -96,95 +168,162 @@
  116    115   
            )));
  117    116   
        }
  118    117   
  119    118   
        let output = std::str::from_utf8(&output.stdout).map_err(|e| {
  120    119   
            CredentialsError::provider_error(format!(
  121    120   
                "Error retrieving credentials from external process: could not decode output as UTF-8: {}",
  122    121   
                e
  123    122   
            ))
  124    123   
        })?;
  125    124   
  126         -
        parse_credential_process_json_credentials(output, self.profile_account_id.as_ref())
  127         -
            .map(|mut creds| {
  128         -
                creds
  129         -
                    .get_property_mut_or_default::<Vec<AwsCredentialFeature>>()
  130         -
                    .push(AwsCredentialFeature::CredentialsProcess);
  131         -
                creds
  132         -
            })
  133         -
            .map_err(|invalid| {
         125  +
        parse_credential_process_json_credentials(output, self.profile_account_id.as_ref()).map_err(
         126  +
            |invalid| {
  134    127   
                CredentialsError::provider_error(format!(
  135    128   
                "Error retrieving credentials from external process, could not parse response: {}",
  136    129   
                invalid
  137    130   
            ))
  138         -
            })
         131  +
            },
         132  +
        )
  139    133   
    }
  140    134   
}
  141    135   
  142    136   
#[derive(Debug, Default)]
  143    137   
pub(crate) struct Builder {
  144    138   
    command: Option<CommandWithSensitiveArgs<String>>,
  145    139   
    profile_account_id: Option<AccountId>,
  146    140   
}
  147    141   
  148    142   
impl Builder {
@@ -243,237 +303,296 @@
  263    257   
        .map_err(|err| InvalidJsonCredentials::InvalidField {
  264    258   
            field: "Expiration",
  265    259   
            err: err.into(),
  266    260   
        })
  267    261   
}
  268    262   
  269    263   
#[cfg(test)]
  270    264   
mod test {
  271    265   
    use crate::credential_process::CredentialProcessProvider;
  272    266   
    use crate::sensitive_command::CommandWithSensitiveArgs;
  273         -
    use aws_credential_types::credential_feature::AwsCredentialFeature;
  274    267   
    use aws_credential_types::provider::ProvideCredentials;
  275    268   
    use std::time::{Duration, SystemTime};
  276    269   
    use time::format_description::well_known::Rfc3339;
  277    270   
    use time::OffsetDateTime;
  278    271   
    use tokio::time::timeout;
  279    272   
  280    273   
    // TODO(https://github.com/awslabs/aws-sdk-rust/issues/1117) This test is ignored on Windows because it uses Unix-style paths
  281    274   
    #[tokio::test]
  282    275   
    #[cfg_attr(windows, ignore)]
  283    276   
    async fn test_credential_process() {
@@ -319,312 +364,342 @@
  339    332   
    async fn fallback_account_id_shadowed_by_account_id_in_process_output() {
  340    333   
        let provider = CredentialProcessProvider::builder()
  341    334   
            .command(CommandWithSensitiveArgs::new(String::from(
  342    335   
                r#"echo '{ "Version": 1, "AccessKeyId": "ASIARTESTID", "SecretAccessKey": "TESTSECRETKEY", "AccountId": "111122223333" }'"#,
  343    336   
            )))
  344    337   
            .account_id("012345678901")
  345    338   
            .build();
  346    339   
        let creds = provider.provide_credentials().await.unwrap();
  347    340   
        assert_eq!("111122223333", creds.account_id().unwrap().as_str());
  348    341   
    }
  349         -
  350         -
    #[tokio::test]
  351         -
    async fn credential_feature() {
  352         -
        let provider = CredentialProcessProvider::builder()
  353         -
            .command(CommandWithSensitiveArgs::new(String::from(
  354         -
                r#"echo '{ "Version": 1, "AccessKeyId": "ASIARTESTID", "SecretAccessKey": "TESTSECRETKEY", "AccountId": "111122223333" }'"#,
  355         -
            )))
  356         -
            .account_id("012345678901")
  357         -
            .build();
  358         -
        let creds = provider.provide_credentials().await.unwrap();
  359         -
        assert_eq!(
  360         -
            &vec![AwsCredentialFeature::CredentialsProcess],
  361         -
            creds.get_property::<Vec<AwsCredentialFeature>>().unwrap()
  362         -
        );
  363         -
    }
  364    342   
}

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/environment/credentials.rs

@@ -1,1 +148,142 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
use std::env::VarError;
    7      7   
    8      8   
use aws_credential_types::attributes::AccountId;
    9         -
use aws_credential_types::credential_feature::AwsCredentialFeature;
   10      9   
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
   11     10   
use aws_credential_types::Credentials;
   12     11   
use aws_types::os_shim_internal::Env;
   13     12   
   14     13   
/// Load Credentials from Environment Variables
   15     14   
///
   16     15   
/// `EnvironmentVariableCredentialsProvider` uses the following variables:
   17     16   
/// - `AWS_ACCESS_KEY_ID`
   18     17   
/// - `AWS_SECRET_ACCESS_KEY` with fallback to `SECRET_ACCESS_KEY`
   19     18   
/// - `AWS_SESSION_TOKEN` (optional)
   20     19   
/// - `AWS_ACCOUNT_ID` (optional)
   21     20   
#[derive(Debug, Clone)]
   22     21   
pub struct EnvironmentVariableCredentialsProvider {
   23     22   
    env: Env,
   24     23   
}
   25     24   
   26     25   
impl EnvironmentVariableCredentialsProvider {
   27     26   
    fn credentials(&self) -> provider::Result {
   28     27   
        let access_key = self
   29     28   
            .env
   30     29   
            .get("AWS_ACCESS_KEY_ID")
   31     30   
            .and_then(err_if_blank)
   32     31   
            .map_err(to_cred_error)?;
   33     32   
        let secret_key = self
   34     33   
            .env
   35     34   
            .get("AWS_SECRET_ACCESS_KEY")
   36     35   
            .and_then(err_if_blank)
   37     36   
            .or_else(|_| self.env.get("SECRET_ACCESS_KEY"))
   38     37   
            .and_then(err_if_blank)
   39     38   
            .map_err(to_cred_error)?;
   40     39   
        let session_token =
   41     40   
            self.env
   42     41   
                .get("AWS_SESSION_TOKEN")
   43     42   
                .ok()
   44     43   
                .and_then(|token| match token.trim() {
   45     44   
                    "" => None,
   46     45   
                    s => Some(s.to_string()),
   47     46   
                });
   48     47   
        let account_id =
   49     48   
            self.env
   50     49   
                .get("AWS_ACCOUNT_ID")
   51     50   
                .ok()
   52     51   
                .and_then(|account_id| match account_id.trim() {
   53     52   
                    "" => None,
   54     53   
                    s => Some(AccountId::from(s)),
   55     54   
                });
   56     55   
        let mut builder = Credentials::builder()
   57     56   
            .access_key_id(access_key)
   58     57   
            .secret_access_key(secret_key)
   59     58   
            .provider_name(ENV_PROVIDER);
   60     59   
        builder.set_session_token(session_token);
   61     60   
        builder.set_account_id(account_id);
   62         -
        let mut creds = builder.build();
   63         -
        creds
   64         -
            .get_property_mut_or_default::<Vec<AwsCredentialFeature>>()
   65         -
            .push(AwsCredentialFeature::CredentialsEnvVars);
   66         -
        Ok(creds)
          61  +
        Ok(builder.build())
   67     62   
    }
   68     63   
}
   69     64   
   70     65   
impl EnvironmentVariableCredentialsProvider {
   71     66   
    /// Create a `EnvironmentVariableCredentialsProvider`
   72     67   
    pub fn new() -> Self {
   73     68   
        Self::new_with_env(Env::real())
   74     69   
    }
   75     70   
   76     71   
    /// Create a new `EnvironmentVariableCredentialsProvider` with `Env` overridden
   77     72   
    ///
   78     73   
    /// This function is intended for tests that mock out the process environment.
   79     74   
    pub(crate) fn new_with_env(env: Env) -> Self {
   80     75   
        Self { env }
   81     76   
    }
   82     77   
}
   83     78   
   84     79   
impl Default for EnvironmentVariableCredentialsProvider {
   85     80   
    fn default() -> Self {
   86     81   
        Self::new()
   87     82   
    }
   88     83   
}
   89     84   
   90     85   
const ENV_PROVIDER: &str = "EnvironmentVariable";
   91     86   
   92     87   
impl ProvideCredentials for EnvironmentVariableCredentialsProvider {
   93     88   
    fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
   94     89   
    where
   95     90   
        Self: 'a,
   96     91   
    {
   97     92   
        future::ProvideCredentials::ready(self.credentials())
   98     93   
    }
   99     94   
}
  100     95   
  101     96   
fn to_cred_error(err: VarError) -> CredentialsError {
  102     97   
    match err {
  103     98   
        VarError::NotPresent => CredentialsError::not_loaded("environment variable not set"),
  104     99   
        e @ VarError::NotUnicode(_) => CredentialsError::unhandled(e),
  105    100   
    }
  106    101   
}
  107    102   
  108    103   
fn err_if_blank(value: String) -> Result<String, VarError> {
  109    104   
    if value.trim().is_empty() {
  110    105   
        Err(VarError::NotPresent)
  111    106   
    } else {
  112    107   
        Ok(value)
  113    108   
    }
  114    109   
}
  115    110   
  116    111   
#[cfg(test)]
  117    112   
mod test {
  118         -
    use aws_credential_types::credential_feature::AwsCredentialFeature;
  119    113   
    use aws_credential_types::provider::{error::CredentialsError, ProvideCredentials};
  120    114   
    use aws_types::os_shim_internal::Env;
  121    115   
    use futures_util::FutureExt;
  122    116   
  123    117   
    use super::EnvironmentVariableCredentialsProvider;
  124    118   
  125    119   
    fn make_provider(vars: &[(&str, &str)]) -> EnvironmentVariableCredentialsProvider {
  126    120   
        EnvironmentVariableCredentialsProvider {
  127    121   
            env: Env::from_slice(vars),
  128    122   
        }
@@ -229,223 +285,259 @@
  249    243   
  250    244   
            let err = provider
  251    245   
                .provide_credentials()
  252    246   
                .now_or_never()
  253    247   
                .unwrap()
  254    248   
                .expect_err("no credentials defined");
  255    249   
            assert!(matches!(err, CredentialsError::CredentialsNotLoaded { .. }));
  256    250   
        }
  257    251   
    }
  258    252   
  259         -
    #[test]
  260         -
    fn credentials_feature() {
  261         -
        let provider = make_provider(&[
  262         -
            ("AWS_ACCESS_KEY_ID", "access"),
  263         -
            ("AWS_SECRET_ACCESS_KEY", "secret"),
  264         -
            ("SECRET_ACCESS_KEY", "secret"),
  265         -
            ("AWS_SESSION_TOKEN", "token"),
  266         -
        ]);
  267         -
  268         -
        let creds = provider
  269         -
            .provide_credentials()
  270         -
            .now_or_never()
  271         -
            .unwrap()
  272         -
            .expect("valid credentials");
  273         -
        assert_eq!(
  274         -
            &vec![AwsCredentialFeature::CredentialsEnvVars],
  275         -
            creds.get_property::<Vec<AwsCredentialFeature>>().unwrap()
  276         -
        );
  277         -
    }
  278         -
  279    253   
    #[test]
  280    254   
    fn real_environment() {
  281    255   
        let provider = EnvironmentVariableCredentialsProvider::new();
  282    256   
        // we don't know what's in the env, just make sure it doesn't crash.
  283    257   
        let _fut = provider.provide_credentials();
  284    258   
    }
  285    259   
}

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/http_credential_provider.rs

@@ -1,1 +97,87 @@
    4      4   
 */
    5      5   
    6      6   
//! Generalized HTTP credential provider. Currently, this cannot be used directly and can only
    7      7   
//! be used via the ECS credential provider.
    8      8   
//!
    9      9   
//! Future work will stabilize this interface and enable it to be used directly.
   10     10   
   11     11   
use crate::json_credentials::{parse_json_credentials, JsonCredentials, RefreshableCredentials};
   12     12   
use crate::provider_config::ProviderConfig;
   13     13   
use aws_credential_types::attributes::AccountId;
   14         -
use aws_credential_types::credential_feature::AwsCredentialFeature;
   15     14   
use aws_credential_types::provider::{self, error::CredentialsError};
   16     15   
use aws_credential_types::Credentials;
   17     16   
use aws_smithy_runtime::client::metrics::MetricsRuntimePlugin;
   18     17   
use aws_smithy_runtime::client::orchestrator::operation::Operation;
   19     18   
use aws_smithy_runtime::client::retries::classifiers::{
   20     19   
    HttpStatusCodeClassifier, TransientErrorClassifier,
   21     20   
};
   22     21   
use aws_smithy_runtime_api::client::http::HttpConnectorSettings;
   23     22   
use aws_smithy_runtime_api::client::interceptors::context::{Error, InterceptorContext};
   24     23   
use aws_smithy_runtime_api::client::orchestrator::{
   25     24   
    HttpResponse, Metadata, OrchestratorError, SensitiveOutput,
   26     25   
};
   27     26   
use aws_smithy_runtime_api::client::result::SdkError;
   28     27   
use aws_smithy_runtime_api::client::retries::classifiers::ClassifyRetry;
   29     28   
use aws_smithy_runtime_api::client::retries::classifiers::RetryAction;
   30     29   
use aws_smithy_runtime_api::client::runtime_plugin::StaticRuntimePlugin;
   31     30   
use aws_smithy_types::body::SdkBody;
   32     31   
use aws_smithy_types::config_bag::Layer;
   33     32   
use aws_smithy_types::retry::RetryConfig;
   34     33   
use aws_smithy_types::timeout::TimeoutConfig;
   35     34   
use http::header::{ACCEPT, AUTHORIZATION};
   36     35   
use http::HeaderValue;
   37     36   
use std::time::Duration;
   38     37   
   39     38   
const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(5);
   40     39   
const DEFAULT_CONNECT_TIMEOUT: Duration = Duration::from_secs(2);
   41     40   
   42     41   
#[derive(Debug)]
   43     42   
struct HttpProviderAuth {
   44     43   
    auth: Option<HeaderValue>,
   45     44   
}
   46     45   
   47     46   
#[derive(Debug)]
   48     47   
pub(crate) struct HttpCredentialProvider {
   49     48   
    operation: Operation<HttpProviderAuth, Credentials, CredentialsError>,
   50     49   
}
   51     50   
   52     51   
impl HttpCredentialProvider {
   53     52   
    pub(crate) fn builder() -> Builder {
   54     53   
        Builder::default()
   55     54   
    }
   56     55   
   57     56   
    pub(crate) async fn credentials(&self, auth: Option<HeaderValue>) -> provider::Result {
   58         -
        let credentials =
   59         -
            self.operation
   60         -
                .invoke(HttpProviderAuth { auth })
   61         -
                .await
   62         -
                .map(|mut creds| {
   63         -
                    creds
   64         -
                        .get_property_mut_or_default::<Vec<AwsCredentialFeature>>()
   65         -
                        .push(AwsCredentialFeature::CredentialsHttp);
   66         -
                    creds
   67         -
                });
          57  +
        let credentials = self.operation.invoke(HttpProviderAuth { auth }).await;
   68     58   
        match credentials {
   69     59   
            Ok(creds) => Ok(creds),
   70     60   
            Err(SdkError::ServiceError(context)) => Err(context.into_err()),
   71     61   
            Err(other) => Err(CredentialsError::unhandled(other)),
   72     62   
        }
   73     63   
    }
   74     64   
}
   75     65   
   76     66   
#[derive(Default)]
   77     67   
pub(crate) struct Builder {
@@ -216,206 +276,265 @@
  236    226   
            }
  237    227   
        }
  238    228   
  239    229   
        RetryAction::NoActionIndicated
  240    230   
    }
  241    231   
}
  242    232   
  243    233   
#[cfg(test)]
  244    234   
mod test {
  245    235   
    use super::*;
  246         -
    use aws_credential_types::credential_feature::AwsCredentialFeature;
  247    236   
    use aws_credential_types::provider::error::CredentialsError;
  248    237   
    use aws_smithy_http_client::test_util::{ReplayEvent, StaticReplayClient};
  249    238   
    use aws_smithy_types::body::SdkBody;
  250    239   
    use http::{Request, Response, Uri};
  251    240   
    use std::time::SystemTime;
  252    241   
  253    242   
    async fn provide_creds(
  254    243   
        http_client: StaticReplayClient,
  255    244   
    ) -> Result<Credentials, CredentialsError> {
  256    245   
        let provider_config = ProviderConfig::default().with_http_client(http_client.clone());
@@ -330,319 +370,349 @@
  350    339   
        )]);
  351    340   
        let err = provide_creds(http_client.clone())
  352    341   
            .await
  353    342   
            .expect_err("it should fail");
  354    343   
        assert!(
  355    344   
            matches!(err, CredentialsError::ProviderError { .. }),
  356    345   
            "should be CredentialsError::ProviderError: {err}",
  357    346   
        );
  358    347   
        http_client.assert_requests_match(&[]);
  359    348   
    }
  360         -
  361         -
    #[tokio::test]
  362         -
    async fn credentials_feature() {
  363         -
        let http_client = StaticReplayClient::new(vec![successful_req_resp()]);
  364         -
        let creds = provide_creds(http_client.clone()).await.expect("success");
  365         -
        assert_eq!(
  366         -
            &vec![AwsCredentialFeature::CredentialsHttp],
  367         -
            creds.get_property::<Vec<AwsCredentialFeature>>().unwrap()
  368         -
        );
  369         -
    }
  370    349   
}

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/imds/client.rs

@@ -625,625 +769,765 @@
  645    645   
pub(crate) mod test {
  646    646   
    use crate::imds::client::{Client, EndpointMode, ImdsResponseRetryClassifier};
  647    647   
    use crate::provider_config::ProviderConfig;
  648    648   
    use aws_smithy_async::rt::sleep::TokioSleep;
  649    649   
    use aws_smithy_async::test_util::{instant_time_and_sleep, InstantSleep};
  650    650   
    use aws_smithy_http_client::test_util::{capture_request, ReplayEvent, StaticReplayClient};
  651    651   
    use aws_smithy_runtime::test_util::capture_test_logs::capture_test_logs;
  652    652   
    use aws_smithy_runtime_api::client::interceptors::context::{
  653    653   
        Input, InterceptorContext, Output,
  654    654   
    };
  655         -
    use aws_smithy_runtime_api::client::orchestrator::OrchestratorError;
  656         -
    use aws_smithy_runtime_api::client::orchestrator::{HttpRequest, HttpResponse};
         655  +
    use aws_smithy_runtime_api::client::orchestrator::{
         656  +
        HttpRequest, HttpResponse, OrchestratorError,
         657  +
    };
  657    658   
    use aws_smithy_runtime_api::client::result::ConnectorError;
  658    659   
    use aws_smithy_runtime_api::client::retries::classifiers::{
  659    660   
        ClassifyRetry, RetryAction, SharedRetryClassifier,
  660    661   
    };
  661    662   
    use aws_smithy_types::body::SdkBody;
  662    663   
    use aws_smithy_types::error::display::DisplayErrorContext;
  663    664   
    use aws_types::os_shim_internal::{Env, Fs};
  664    665   
    use http::header::USER_AGENT;
  665    666   
    use http::Uri;
  666    667   
    use serde::Deserialize;
  667    668   
    use std::collections::HashMap;
  668    669   
    use std::error::Error;
  669    670   
    use std::io;
  670    671   
    use std::time::SystemTime;
  671    672   
    use std::time::{Duration, UNIX_EPOCH};
  672    673   
    use tracing_test::traced_test;
  673    674   
  674    675   
    macro_rules! assert_full_error_contains {
  675    676   
        ($err:expr, $contains:expr) => {
  676    677   
            let err = $err;
  677    678   
            let message = format!(
  678    679   
                "{}",
  679    680   
                aws_smithy_types::error::display::DisplayErrorContext(&err)
  680    681   
            );
  681    682   
            assert!(
  682    683   
                message.contains($contains),
  683    684   
                "Error message '{message}' didn't contain text '{}'",
  684    685   
                $contains
  685    686   
            );
  686    687   
        };
  687    688   
    }
  688    689   
  689    690   
    const TOKEN_A: &str = "AQAEAFTNrA4eEGx0AQgJ1arIq_Cc-t4tWt3fB0Hd8RKhXlKc5ccvhg==";
  690    691   
    const TOKEN_B: &str = "alternatetoken==";
  691    692   
  692         -
    /// Create a simple token request
  693    693   
    pub(crate) fn token_request(base: &str, ttl: u32) -> HttpRequest {
  694    694   
        http::Request::builder()
  695    695   
            .uri(format!("{}/latest/api/token", base))
  696    696   
            .header("x-aws-ec2-metadata-token-ttl-seconds", ttl)
  697    697   
            .method("PUT")
  698    698   
            .body(SdkBody::empty())
  699    699   
            .unwrap()
  700    700   
            .try_into()
  701    701   
            .unwrap()
  702    702   
    }
  703    703   
  704         -
    /// Create a simple token response
  705    704   
    pub(crate) fn token_response(ttl: u32, token: &'static str) -> HttpResponse {
  706    705   
        HttpResponse::try_from(
  707    706   
            http::Response::builder()
  708    707   
                .status(200)
  709    708   
                .header("X-aws-ec2-metadata-token-ttl-seconds", ttl)
  710    709   
                .body(SdkBody::from(token))
  711    710   
                .unwrap(),
  712    711   
        )
  713    712   
        .unwrap()
  714    713   
    }
  715    714   
  716         -
    /// Create a simple IMDS request
  717    715   
    pub(crate) fn imds_request(path: &'static str, token: &str) -> HttpRequest {
  718    716   
        http::Request::builder()
  719    717   
            .uri(Uri::from_static(path))
  720    718   
            .method("GET")
  721    719   
            .header("x-aws-ec2-metadata-token", token)
  722    720   
            .body(SdkBody::empty())
  723    721   
            .unwrap()
  724    722   
            .try_into()
  725    723   
            .unwrap()
  726    724   
    }
  727    725   
  728         -
    /// Create a simple IMDS response
  729    726   
    pub(crate) fn imds_response(body: &'static str) -> HttpResponse {
  730    727   
        HttpResponse::try_from(
  731    728   
            http::Response::builder()
  732    729   
                .status(200)
  733    730   
                .body(SdkBody::from(body))
  734    731   
                .unwrap(),
  735    732   
        )
  736    733   
        .unwrap()
  737    734   
    }
  738    735   
  739         -
    /// Create an IMDS client with an underlying [StaticReplayClient]
  740    736   
    pub(crate) fn make_imds_client(http_client: &StaticReplayClient) -> super::Client {
  741    737   
        tokio::time::pause();
  742    738   
        super::Client::builder()
  743    739   
            .configure(
  744    740   
                &ProviderConfig::no_configuration()
  745    741   
                    .with_sleep_impl(InstantSleep::unlogged())
  746    742   
                    .with_http_client(http_client.clone()),
  747    743   
            )
  748    744   
            .build()
  749    745   
    }

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/imds/credentials.rs

@@ -1,1 +45,44 @@
    5      5   
    6      6   
//! IMDSv2 Credentials Provider
    7      7   
//!
    8      8   
//! # Important
    9      9   
//! This credential provider will NOT fallback to IMDSv1. Ensure that IMDSv2 is enabled on your instances.
   10     10   
   11     11   
use super::client::error::ImdsError;
   12     12   
use crate::imds::{self, Client};
   13     13   
use crate::json_credentials::{parse_json_credentials, JsonCredentials, RefreshableCredentials};
   14     14   
use crate::provider_config::ProviderConfig;
   15         -
use aws_credential_types::credential_feature::AwsCredentialFeature;
   16     15   
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
   17     16   
use aws_credential_types::Credentials;
   18     17   
use aws_smithy_async::time::SharedTimeSource;
   19     18   
use aws_types::os_shim_internal::Env;
   20     19   
use std::borrow::Cow;
   21     20   
use std::error::Error as StdError;
   22     21   
use std::fmt;
   23     22   
use std::sync::{Arc, RwLock};
   24     23   
use std::time::{Duration, SystemTime};
   25     24   
@@ -243,242 +330,322 @@
  263    262   
            }
  264    263   
            Ok(JsonCredentials::Error { code, message }) => {
  265    264   
                Err(CredentialsError::provider_error(format!(
  266    265   
                    "Error retrieving credentials from IMDS: {} {}",
  267    266   
                    code, message
  268    267   
                )))
  269    268   
            }
  270    269   
            // got bad data from IMDS, should not occur during normal operation:
  271    270   
            Err(invalid) => Err(CredentialsError::unhandled(invalid)),
  272    271   
        }
  273         -
        .map(|mut creds| {
  274         -
            creds
  275         -
                .get_property_mut_or_default::<Vec<AwsCredentialFeature>>()
  276         -
                .push(AwsCredentialFeature::CredentialsImds);
  277         -
            creds
  278         -
        })
  279    272   
    }
  280    273   
  281    274   
    async fn credentials(&self) -> provider::Result {
  282    275   
        match self.retrieve_credentials().await {
  283    276   
            creds @ Ok(_) => creds,
  284    277   
            // Any failure while retrieving credentials MUST NOT impede use of existing credentials.
  285    278   
            err => match &*self.last_retrieved_credentials.read().unwrap() {
  286    279   
                Some(creds) => Ok(creds.clone()),
  287    280   
                _ => err,
  288    281   
            },
  289    282   
        }
  290    283   
    }
  291    284   
}
  292    285   
  293    286   
#[cfg(test)]
  294    287   
mod test {
  295    288   
    use super::*;
  296    289   
    use crate::imds::client::test::{
  297    290   
        imds_request, imds_response, make_imds_client, token_request, token_response,
  298    291   
    };
  299    292   
    use crate::provider_config::ProviderConfig;
  300         -
    use aws_credential_types::credential_feature::AwsCredentialFeature;
  301    293   
    use aws_credential_types::provider::ProvideCredentials;
  302    294   
    use aws_smithy_async::test_util::instant_time_and_sleep;
  303    295   
    use aws_smithy_http_client::test_util::{ReplayEvent, StaticReplayClient};
  304    296   
    use aws_smithy_types::body::SdkBody;
  305    297   
    use std::time::{Duration, UNIX_EPOCH};
  306    298   
    use tracing_test::traced_test;
  307    299   
  308    300   
    const TOKEN_A: &str = "token_a";
  309    301   
  310    302   
    #[tokio::test]
@@ -510,502 +575,532 @@
  530    522   
            .imds_client(make_imds_client(&http_client))
  531    523   
            .configure(&ProviderConfig::no_configuration())
  532    524   
            .build();
  533    525   
        let creds1 = provider.provide_credentials().await.expect("valid creds");
  534    526   
        assert_eq!(creds1.access_key_id(), "ASIARTEST");
  535    527   
        // `creds1` should be returned as fallback credentials and assigned to `creds2`
  536    528   
        let creds2 = provider.provide_credentials().await.expect("valid creds");
  537    529   
        assert_eq!(creds1, creds2);
  538    530   
        http_client.assert_requests_match(&[]);
  539    531   
    }
  540         -
  541         -
    #[tokio::test]
  542         -
    async fn credentials_feature() {
  543         -
        let http_client = StaticReplayClient::new(vec![
  544         -
            ReplayEvent::new(
  545         -
                token_request("http://169.254.169.254", 21600),
  546         -
                token_response(21600, TOKEN_A),
  547         -
            ),
  548         -
            ReplayEvent::new(
  549         -
                imds_request("http://169.254.169.254/latest/meta-data/iam/security-credentials/", TOKEN_A),
  550         -
                imds_response(r#"profile-name"#),
  551         -
            ),
  552         -
            ReplayEvent::new(
  553         -
                imds_request("http://169.254.169.254/latest/meta-data/iam/security-credentials/profile-name", TOKEN_A),
  554         -
                imds_response("{\n  \"Code\" : \"Success\",\n  \"LastUpdated\" : \"2021-09-20T21:42:26Z\",\n  \"Type\" : \"AWS-HMAC\",\n  \"AccessKeyId\" : \"ASIARTEST\",\n  \"SecretAccessKey\" : \"testsecret\",\n  \"Token\" : \"testtoken\",\n  \"Expiration\" : \"2021-09-21T04:16:53Z\"\n}"),
  555         -
            ),
  556         -
            ReplayEvent::new(
  557         -
                imds_request("http://169.254.169.254/latest/meta-data/iam/security-credentials/", TOKEN_A),
  558         -
                imds_response(r#"different-profile"#),
  559         -
            ),
  560         -
            ReplayEvent::new(
  561         -
                imds_request("http://169.254.169.254/latest/meta-data/iam/security-credentials/different-profile", TOKEN_A),
  562         -
                imds_response("{\n  \"Code\" : \"Success\",\n  \"LastUpdated\" : \"2021-09-20T21:42:26Z\",\n  \"Type\" : \"AWS-HMAC\",\n  \"AccessKeyId\" : \"ASIARTEST2\",\n  \"SecretAccessKey\" : \"testsecret\",\n  \"Token\" : \"testtoken\",\n  \"Expiration\" : \"2021-09-21T04:16:53Z\"\n}"),
  563         -
            ),
  564         -
        ]);
  565         -
        let client = ImdsCredentialsProvider::builder()
  566         -
            .imds_client(make_imds_client(&http_client))
  567         -
            .configure(&ProviderConfig::no_configuration())
  568         -
            .build();
  569         -
        let creds = client.provide_credentials().await.expect("valid creds");
  570         -
        assert_eq!(
  571         -
            &vec![AwsCredentialFeature::CredentialsImds],
  572         -
            creds.get_property::<Vec<AwsCredentialFeature>>().unwrap()
  573         -
        );
  574         -
    }
  575    532   
}

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/lib.rs

@@ -867,867 +1033,1024 @@
  887    887   
                TriStateOption::Set(provider) => Some(provider),
  888    888   
                TriStateOption::NotSet => {
  889    889   
                    let mut builder =
  890    890   
                        credentials::DefaultCredentialsChain::builder().configure(conf.clone());
  891    891   
                    builder.set_region(region.clone());
  892    892   
                    Some(SharedCredentialsProvider::new(builder.build().await))
  893    893   
                }
  894    894   
                TriStateOption::ExplicitlyUnset => None,
  895    895   
            };
  896    896   
         897  +
            let token_provider = match self.token_provider {
         898  +
                Some(provider) => Some(provider),
         899  +
                None => {
         900  +
                    #[cfg(feature = "sso")]
         901  +
                    {
         902  +
                        let mut builder =
         903  +
                            crate::default_provider::token::DefaultTokenChain::builder()
         904  +
                                .configure(conf.clone());
         905  +
                        builder.set_region(region.clone());
         906  +
                        Some(SharedTokenProvider::new(builder.build().await))
         907  +
                    }
         908  +
                    #[cfg(not(feature = "sso"))]
         909  +
                    {
         910  +
                        None
         911  +
                    }
         912  +
                }
         913  +
            };
         914  +
  897    915   
            let profiles = conf.profile().await;
  898    916   
            let service_config = EnvServiceConfig {
  899    917   
                env: conf.env(),
  900    918   
                env_config_sections: profiles.cloned().unwrap_or_default(),
  901    919   
            };
  902    920   
            let mut builder = SdkConfig::builder()
  903         -
                .region(region.clone())
         921  +
                .region(region)
  904    922   
                .retry_config(retry_config)
  905    923   
                .timeout_config(timeout_config)
  906    924   
                .time_source(time_source)
  907    925   
                .service_config(service_config);
  908    926   
  909    927   
            // If an endpoint URL is set programmatically, then our work is done.
  910    928   
            let endpoint_url = if self.endpoint_url.is_some() {
  911    929   
                builder.insert_origin("endpoint_url", Origin::shared_config());
  912    930   
                self.endpoint_url
  913    931   
            } else {
  914    932   
                // Otherwise, check to see if we should ignore EP URLs set in the environment.
  915    933   
                let ignore_configured_endpoint_urls =
  916    934   
                    ignore_ep::ignore_configured_endpoint_urls_provider(&conf)
  917    935   
                        .await
  918    936   
                        .unwrap_or_default();
  919    937   
  920    938   
                if ignore_configured_endpoint_urls {
  921    939   
                    // If yes, log a trace and return `None`.
  922    940   
                    tracing::trace!(
  923    941   
                        "`ignore_configured_endpoint_urls` is set, any endpoint URLs configured in the environment will be ignored. \
  924    942   
                        NOTE: Endpoint URLs set programmatically WILL still be respected"
  925    943   
                    );
  926    944   
                    None
  927    945   
                } else {
  928    946   
                    // Otherwise, attempt to resolve one.
  929    947   
                    let (v, origin) = endpoint_url::endpoint_url_provider_with_origin(&conf).await;
  930    948   
                    builder.insert_origin("endpoint_url", origin);
  931    949   
                    v
  932    950   
                }
  933    951   
            };
  934    952   
  935         -
            let token_provider = match self.token_provider {
  936         -
                Some(provider) => {
  937         -
                    builder.insert_origin("token_provider", Origin::shared_config());
  938         -
                    Some(provider)
  939         -
                }
  940         -
                None => {
  941         -
                    #[cfg(feature = "sso")]
  942         -
                    {
  943         -
                        let mut builder =
  944         -
                            crate::default_provider::token::DefaultTokenChain::builder()
  945         -
                                .configure(conf.clone());
  946         -
                        builder.set_region(region);
  947         -
                        Some(SharedTokenProvider::new(builder.build().await))
  948         -
                    }
  949         -
                    #[cfg(not(feature = "sso"))]
  950         -
                    {
  951         -
                        None
  952         -
                    }
  953         -
                    // Not setting `Origin` in this arm, and that's good for now as long as we know
  954         -
                    // it's not programmatically set in the shared config.
  955         -
                    // We can consider adding `Origin::Default` if needed.
  956         -
                }
  957         -
            };
  958         -
  959    953   
            builder.set_endpoint_url(endpoint_url);
  960    954   
            builder.set_behavior_version(self.behavior_version);
  961    955   
            builder.set_http_client(self.http_client);
  962    956   
            builder.set_app_name(app_name);
  963    957   
  964    958   
            let identity_cache = match self.identity_cache {
  965    959   
                None => match self.behavior_version {
  966    960   
                    #[allow(deprecated)]
  967    961   
                    Some(bv) if bv.is_at_least(BehaviorVersion::v2024_03_28()) => {
  968    962   
                        Some(IdentityCache::lazy().build())
  969    963   
                    }
  970    964   
                    _ => None,
  971    965   
                },
  972    966   
                Some(user_cache) => Some(user_cache),
  973    967   
            };
  974    968   
  975    969   
            let request_checksum_calculation =
  976    970   
                if let Some(request_checksum_calculation) = self.request_checksum_calculation {
  977    971   
                    Some(request_checksum_calculation)
  978    972   
                } else {
  979    973   
                    checksums::request_checksum_calculation_provider(&conf).await
  980    974   
                };
  981    975   
  982    976   
            let response_checksum_validation =
  983    977   
                if let Some(response_checksum_validation) = self.response_checksum_validation {
  984    978   
                    Some(response_checksum_validation)
  985    979   
                } else {
  986    980   
                    checksums::response_checksum_validation_provider(&conf).await
  987    981   
                };
  988    982   
  989    983   
            let account_id_endpoint_mode =
  990    984   
                if let Some(acccount_id_endpoint_mode) = self.account_id_endpoint_mode {
  991    985   
                    Some(acccount_id_endpoint_mode)
  992    986   
                } else {
  993    987   
                    account_id_endpoint_mode::account_id_endpoint_mode_provider(&conf).await
  994    988   
                };
  995    989   
  996    990   
            let auth_scheme_preference =
  997    991   
                if let Some(auth_scheme_preference) = self.auth_scheme_preference {
  998         -
                    builder.insert_origin("auth_scheme_preference", Origin::shared_config());
  999    992   
                    Some(auth_scheme_preference)
 1000    993   
                } else {
 1001    994   
                    auth_scheme_preference::auth_scheme_preference_provider(&conf).await
 1002         -
                    // Not setting `Origin` in this arm, and that's good for now as long as we know
 1003         -
                    // it's not programmatically set in the shared config.
 1004    995   
                };
 1005    996   
 1006    997   
            builder.set_request_checksum_calculation(request_checksum_calculation);
 1007    998   
            builder.set_response_checksum_validation(response_checksum_validation);
 1008    999   
            builder.set_identity_cache(identity_cache);
 1009   1000   
            builder.set_credentials_provider(credentials_provider);
 1010   1001   
            builder.set_token_provider(token_provider);
 1011   1002   
            builder.set_sleep_impl(sleep_impl);
 1012   1003   
            builder.set_use_fips(use_fips);
 1013   1004   
            builder.set_use_dual_stack(use_dual_stack);

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/profile/credentials.rs

@@ -1,1 +61,60 @@
   21     21   
//!   build it from `~/.aws/credentials` and `~/.aws/config`.
   22     22   
//! - `exec` which contains a chain representation of providers to implement passing bootstrapped credentials
   23     23   
//!   through a series of providers.
   24     24   
   25     25   
use crate::profile::cell::ErrorTakingOnceCell;
   26     26   
#[allow(deprecated)]
   27     27   
use crate::profile::profile_file::ProfileFiles;
   28     28   
use crate::profile::Profile;
   29     29   
use crate::profile::ProfileFileLoadError;
   30     30   
use crate::provider_config::ProviderConfig;
   31         -
use aws_credential_types::credential_feature::AwsCredentialFeature;
   32     31   
use aws_credential_types::{
   33     32   
    provider::{self, error::CredentialsError, future, ProvideCredentials},
   34     33   
    Credentials,
   35     34   
};
   36     35   
use aws_smithy_types::error::display::DisplayErrorContext;
   37     36   
use std::borrow::Cow;
   38     37   
use std::collections::HashMap;
   39     38   
use std::error::Error;
   40     39   
use std::fmt::{Display, Formatter};
   41     40   
use std::sync::Arc;
@@ -160,159 +225,219 @@
  180    179   
                                ))),
  181    180   
                            },
  182    181   
                        }
  183    182   
                    }
  184    183   
                },
  185    184   
                CredentialsError::unhandled(
  186    185   
                    "profile file credentials provider initialization error already taken",
  187    186   
                ),
  188    187   
            )
  189    188   
            .await?;
  190         -
        inner_provider.provide_credentials().await.map(|mut creds| {
  191         -
            creds
  192         -
                .get_property_mut_or_default::<Vec<AwsCredentialFeature>>()
  193         -
                .push(AwsCredentialFeature::CredentialsProfile);
  194         -
            creds
  195         -
        })
         189  +
        inner_provider.provide_credentials().await
  196    190   
    }
  197    191   
}
  198    192   
  199    193   
impl ProvideCredentials for ProfileFileCredentialsProvider {
  200    194   
    fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
  201    195   
    where
  202    196   
        Self: 'a,
  203    197   
    {
  204    198   
        future::ProvideCredentials::new(self.load_credentials())
  205    199   
    }
@@ -605,599 +801,767 @@
  625    619   
  626    620   
    make_test!(assume_role_override_global_env_url);
  627    621   
    make_test!(assume_role_override_service_env_url);
  628    622   
    make_test!(assume_role_override_global_profile_url);
  629    623   
    make_test!(assume_role_override_service_profile_url);
  630    624   
}
  631    625   
  632    626   
#[cfg(all(test, feature = "sso"))]
  633    627   
mod sso_tests {
  634    628   
    use crate::{profile::credentials::Builder, provider_config::ProviderConfig};
  635         -
    use aws_credential_types::credential_feature::AwsCredentialFeature;
  636    629   
    use aws_credential_types::provider::ProvideCredentials;
  637    630   
    use aws_sdk_sso::config::RuntimeComponents;
  638    631   
    use aws_smithy_runtime_api::client::{
  639    632   
        http::{
  640    633   
            HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings,
  641    634   
            SharedHttpConnector,
  642    635   
        },
  643    636   
        orchestrator::{HttpRequest, HttpResponse},
  644    637   
    };
  645    638   
    use aws_smithy_types::body::SdkBody;
  646    639   
    use aws_types::os_shim_internal::{Env, Fs};
  647    640   
    use std::collections::HashMap;
  648    641   
  649         -
    #[derive(Debug)]
  650         -
    struct ClientInner {
  651         -
        expected_token: &'static str,
  652         -
    }
  653         -
    impl HttpConnector for ClientInner {
  654         -
        fn call(&self, request: HttpRequest) -> HttpConnectorFuture {
  655         -
            assert_eq!(
  656         -
                self.expected_token,
  657         -
                request.headers().get("x-amz-sso_bearer_token").unwrap()
  658         -
            );
  659         -
            HttpConnectorFuture::ready(Ok(HttpResponse::new(
         642  +
    // TODO(https://github.com/awslabs/aws-sdk-rust/issues/1117) This test is ignored on Windows because it uses Unix-style paths
         643  +
    #[cfg_attr(windows, ignore)]
         644  +
    // In order to preserve the SSO token cache, the inner provider must only
         645  +
    // be created once, rather than once per credential resolution.
         646  +
    #[tokio::test]
         647  +
    async fn create_inner_provider_exactly_once() {
         648  +
        #[derive(Debug)]
         649  +
        struct ClientInner {
         650  +
            expected_token: &'static str,
         651  +
        }
         652  +
        impl HttpConnector for ClientInner {
         653  +
            fn call(&self, request: HttpRequest) -> HttpConnectorFuture {
         654  +
                assert_eq!(
         655  +
                    self.expected_token,
         656  +
                    request.headers().get("x-amz-sso_bearer_token").unwrap()
         657  +
                );
         658  +
                HttpConnectorFuture::ready(Ok(HttpResponse::new(
  660    659   
                    200.try_into().unwrap(),
  661    660   
                    SdkBody::from("{\"roleCredentials\":{\"accessKeyId\":\"ASIARTESTID\",\"secretAccessKey\":\"TESTSECRETKEY\",\"sessionToken\":\"TESTSESSIONTOKEN\",\"expiration\": 1651516560000}}"),
  662    661   
                )))
         662  +
            }
  663    663   
        }
  664         -
    }
  665         -
    #[derive(Debug)]
  666         -
    struct Client {
  667         -
        inner: SharedHttpConnector,
  668         -
    }
  669         -
    impl Client {
  670         -
        fn new(expected_token: &'static str) -> Self {
  671         -
            Self {
  672         -
                inner: SharedHttpConnector::new(ClientInner { expected_token }),
         664  +
        #[derive(Debug)]
         665  +
        struct Client {
         666  +
            inner: SharedHttpConnector,
         667  +
        }
         668  +
        impl Client {
         669  +
            fn new(expected_token: &'static str) -> Self {
         670  +
                Self {
         671  +
                    inner: SharedHttpConnector::new(ClientInner { expected_token }),
         672  +
                }
  673    673   
            }
  674    674   
        }
  675         -
    }
  676         -
    impl HttpClient for Client {
  677         -
        fn http_connector(
  678         -
            &self,
  679         -
            _settings: &HttpConnectorSettings,
  680         -
            _components: &RuntimeComponents,
  681         -
        ) -> SharedHttpConnector {
  682         -
            self.inner.clone()
         675  +
        impl HttpClient for Client {
         676  +
            fn http_connector(
         677  +
                &self,
         678  +
                _settings: &HttpConnectorSettings,
         679  +
                _components: &RuntimeComponents,
         680  +
            ) -> SharedHttpConnector {
         681  +
                self.inner.clone()
         682  +
            }
  683    683   
        }
  684         -
    }
  685    684   
  686         -
    fn create_test_fs() -> Fs {
  687         -
        Fs::from_map({
         685  +
        let fs = Fs::from_map({
  688    686   
            let mut map = HashMap::new();
  689    687   
            map.insert(
  690    688   
                "/home/.aws/config".to_string(),
  691    689   
                br#"
  692    690   
[profile default]
  693    691   
sso_session = dev
  694    692   
sso_account_id = 012345678901
  695    693   
sso_role_name = SampleRole
  696    694   
region = us-east-1
  697    695   
  698    696   
[sso-session dev]
  699    697   
sso_region = us-east-1
  700    698   
sso_start_url = https://d-abc123.awsapps.com/start
  701    699   
                "#
  702    700   
                .to_vec(),
  703    701   
            );
  704    702   
            map.insert(
  705    703   
                "/home/.aws/sso/cache/34c6fceca75e456f25e7e99531e2425c6c1de443.json".to_string(),
  706    704   
                br#"
  707    705   
                {
  708    706   
                    "accessToken": "secret-access-token",
  709    707   
                    "expiresAt": "2199-11-14T04:05:45Z",
  710    708   
                    "refreshToken": "secret-refresh-token",
  711    709   
                    "clientId": "ABCDEFG323242423121312312312312312",
  712    710   
                    "clientSecret": "ABCDE123",
  713    711   
                    "registrationExpiresAt": "2199-03-06T19:53:17Z",
  714    712   
                    "region": "us-east-1",
  715    713   
                    "startUrl": "https://d-abc123.awsapps.com/start"
  716    714   
                }
  717    715   
                "#
  718    716   
                .to_vec(),
  719    717   
            );
  720    718   
            map
  721         -
        })
  722         -
    }
  723         -
  724         -
    // TODO(https://github.com/awslabs/aws-sdk-rust/issues/1117) This test is ignored on Windows because it uses Unix-style paths
  725         -
    #[cfg_attr(windows, ignore)]
  726         -
    // In order to preserve the SSO token cache, the inner provider must only
  727         -
    // be created once, rather than once per credential resolution.
  728         -
    #[tokio::test]
  729         -
    async fn create_inner_provider_exactly_once() {
  730         -
        let fs = create_test_fs();
  731         -
         719  +
        });
  732    720   
        let provider_config = ProviderConfig::empty()
  733    721   
            .with_fs(fs.clone())
  734    722   
            .with_env(Env::from_slice(&[("HOME", "/home")]))
  735    723   
            .with_http_client(Client::new("secret-access-token"));
  736    724   
        let provider = Builder::default().configure(&provider_config).build();
  737    725   
  738    726   
        let first_creds = provider.provide_credentials().await.unwrap();
  739    727   
  740    728   
        // Write to the token cache with an access token that won't match the fake client's
  741    729   
        // expected access token, and thus, won't return SSO credentials.
  742    730   
        fs.write(
  743    731   
            "/home/.aws/sso/cache/34c6fceca75e456f25e7e99531e2425c6c1de443.json",
  744    732   
            r#"
  745    733   
            {
  746    734   
                "accessToken": "NEW!!secret-access-token",
  747    735   
                "expiresAt": "2199-11-14T04:05:45Z",
  748    736   
                "refreshToken": "secret-refresh-token",
  749    737   
                "clientId": "ABCDEFG323242423121312312312312312",
  750    738   
                "clientSecret": "ABCDE123",
  751    739   
                "registrationExpiresAt": "2199-03-06T19:53:17Z",
  752    740   
                "region": "us-east-1",
  753    741   
                "startUrl": "https://d-abc123.awsapps.com/start"
  754    742   
            }
  755    743   
            "#,
  756    744   
        )
  757    745   
        .await
  758    746   
        .unwrap();
  759    747   
  760    748   
        // Loading credentials will still work since the SSOTokenProvider should have only
  761    749   
        // been created once, and thus, the correct token is still in an in-memory cache.
  762    750   
        let second_creds = provider
  763    751   
            .provide_credentials()
  764    752   
            .await
  765    753   
            .expect("used cached token instead of loading from the file system");
  766    754   
        assert_eq!(first_creds, second_creds);
  767    755   
  768    756   
        // Now create a new provider, which should use the new cached token value from the file system
  769    757   
        // since it won't have the in-memory cache. We do this just to verify that the FS mutation above
  770    758   
        // actually worked correctly.
  771    759   
        let provider_config = ProviderConfig::empty()
  772    760   
            .with_fs(fs.clone())
  773    761   
            .with_env(Env::from_slice(&[("HOME", "/home")]))
  774    762   
            .with_http_client(Client::new("NEW!!secret-access-token"));
  775    763   
        let provider = Builder::default().configure(&provider_config).build();
  776    764   
        let third_creds = provider.provide_credentials().await.unwrap();
  777    765   
        assert_eq!(second_creds, third_creds);
  778    766   
    }
  779         -
  780         -
    #[cfg_attr(windows, ignore)]
  781         -
    #[tokio::test]
  782         -
    async fn credential_feature() {
  783         -
        let fs = create_test_fs();
  784         -
  785         -
        let provider_config = ProviderConfig::empty()
  786         -
            .with_fs(fs.clone())
  787         -
            .with_env(Env::from_slice(&[("HOME", "/home")]))
  788         -
            .with_http_client(Client::new("secret-access-token"));
  789         -
        let provider = Builder::default().configure(&provider_config).build();
  790         -
  791         -
        let creds = provider.provide_credentials().await.unwrap();
  792         -
  793         -
        assert_eq!(
  794         -
            &vec![
  795         -
                AwsCredentialFeature::CredentialsSso,
  796         -
                AwsCredentialFeature::CredentialsProfile
  797         -
            ],
  798         -
            creds.get_property::<Vec<AwsCredentialFeature>>().unwrap()
  799         -
        )
  800         -
    }
  801    767   
}

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/sso/credentials.rs

@@ -1,1 +47,46 @@
    7      7   
//!
    8      8   
//! This credentials provider enables loading credentials from `~/.aws/sso/cache`. For more information,
    9      9   
//! see [Using AWS SSO Credentials](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/sso-credentials.html)
   10     10   
//!
   11     11   
//! This provider is included automatically when profiles are loaded.
   12     12   
   13     13   
use super::cache::load_cached_token;
   14     14   
use crate::identity::IdentityCache;
   15     15   
use crate::provider_config::ProviderConfig;
   16     16   
use crate::sso::SsoTokenProvider;
   17         -
use aws_credential_types::credential_feature::AwsCredentialFeature;
   18     17   
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
   19     18   
use aws_credential_types::Credentials;
   20     19   
use aws_sdk_sso::types::RoleCredentials;
   21     20   
use aws_sdk_sso::Client as SsoClient;
   22     21   
use aws_smithy_async::time::SharedTimeSource;
   23     22   
use aws_smithy_types::DateTime;
   24     23   
use aws_types::os_shim_internal::{Env, Fs};
   25     24   
use aws_types::region::Region;
   26     25   
use aws_types::SdkConfig;
   27     26   
@@ -62,61 +127,120 @@
   82     81   
    async fn credentials(&self) -> provider::Result {
   83     82   
        load_sso_credentials(
   84     83   
            &self.sso_provider_config,
   85     84   
            &self.sdk_config,
   86     85   
            self.token_provider.as_ref(),
   87     86   
            &self.env,
   88     87   
            &self.fs,
   89     88   
            self.time_source.clone(),
   90     89   
        )
   91     90   
        .await
   92         -
        .map(|mut creds| {
   93         -
            creds
   94         -
                .get_property_mut_or_default::<Vec<AwsCredentialFeature>>()
   95         -
                .push(AwsCredentialFeature::CredentialsSso);
   96         -
            creds
   97         -
        })
   98     91   
    }
   99     92   
}
  100     93   
  101     94   
impl ProvideCredentials for SsoCredentialsProvider {
  102     95   
    fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
  103     96   
    where
  104     97   
        Self: 'a,
  105     98   
    {
  106     99   
        future::ProvideCredentials::new(self.credentials())
  107    100   
    }

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/sts/assume_role.rs

@@ -1,1 +38,37 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
//! Assume credentials for a role through the AWS Security Token Service (STS).
    7      7   
    8         -
use aws_credential_types::credential_feature::AwsCredentialFeature;
    9      8   
use aws_credential_types::provider::{
   10      9   
    self, error::CredentialsError, future, ProvideCredentials, SharedCredentialsProvider,
   11     10   
};
   12     11   
use aws_sdk_sts::operation::assume_role::builders::AssumeRoleFluentBuilder;
   13     12   
use aws_sdk_sts::operation::assume_role::AssumeRoleError;
   14     13   
use aws_sdk_sts::types::PolicyDescriptorType;
   15     14   
use aws_sdk_sts::Client as StsClient;
   16     15   
use aws_smithy_runtime::client::identity::IdentityCache;
   17     16   
use aws_smithy_runtime_api::client::result::SdkError;
   18     17   
use aws_smithy_types::error::display::DisplayErrorContext;
@@ -259,258 +374,365 @@
  279    278   
        self.sdk_config = Some(conf);
  280    279   
        self.build().await
  281    280   
    }
  282    281   
}
  283    282   
  284    283   
impl Inner {
  285    284   
    async fn credentials(&self) -> provider::Result {
  286    285   
        tracing::debug!("retrieving assumed credentials");
  287    286   
  288    287   
        let assumed = self.fluent_builder.clone().send().in_current_span().await;
  289         -
        let assumed = match assumed {
         288  +
        match assumed {
  290    289   
            Ok(assumed) => {
  291    290   
                tracing::debug!(
  292    291   
                    access_key_id = ?assumed.credentials.as_ref().map(|c| &c.access_key_id),
  293    292   
                    "obtained assumed credentials"
  294    293   
                );
  295    294   
                super::util::into_credentials(
  296    295   
                    assumed.credentials,
  297    296   
                    assumed.assumed_role_user,
  298    297   
                    "AssumeRoleProvider",
  299    298   
                )
  300    299   
            }
  301    300   
            Err(SdkError::ServiceError(ref context))
  302    301   
                if matches!(
  303    302   
                    context.err(),
  304    303   
                    AssumeRoleError::RegionDisabledException(_)
  305    304   
                        | AssumeRoleError::MalformedPolicyDocumentException(_)
  306    305   
                ) =>
  307    306   
            {
  308    307   
                Err(CredentialsError::invalid_configuration(
  309    308   
                    assumed.err().unwrap(),
  310    309   
                ))
  311    310   
            }
  312    311   
            Err(SdkError::ServiceError(ref context)) => {
  313    312   
                tracing::warn!(error = %DisplayErrorContext(context.err()), "STS refused to grant assume role");
  314    313   
                Err(CredentialsError::provider_error(assumed.err().unwrap()))
  315    314   
            }
  316    315   
            Err(err) => Err(CredentialsError::provider_error(err)),
  317         -
        };
  318         -
  319         -
        assumed.map(|mut creds| {
  320         -
            creds
  321         -
                .get_property_mut_or_default::<Vec<AwsCredentialFeature>>()
  322         -
                .push(AwsCredentialFeature::CredentialsStsAssumeRole);
  323         -
            creds
  324         -
        })
         316  +
        }
  325    317   
    }
  326    318   
}
  327    319   
  328    320   
impl ProvideCredentials for AssumeRoleProvider {
  329    321   
    fn provide_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
  330    322   
    where
  331    323   
        Self: 'a,
  332    324   
    {
  333    325   
        future::ProvideCredentials::new(
  334    326   
            self.inner
  335    327   
                .credentials()
  336    328   
                .instrument(tracing::debug_span!("assume_role")),
  337    329   
        )
  338    330   
    }
  339    331   
}
  340    332   
  341    333   
#[cfg(test)]
  342    334   
mod test {
  343    335   
    use crate::sts::AssumeRoleProvider;
  344         -
    use aws_credential_types::credential_feature::AwsCredentialFeature;
  345    336   
    use aws_credential_types::credential_fn::provide_credentials_fn;
  346    337   
    use aws_credential_types::provider::{ProvideCredentials, SharedCredentialsProvider};
  347    338   
    use aws_credential_types::Credentials;
  348    339   
    use aws_smithy_async::rt::sleep::{SharedAsyncSleep, TokioSleep};
  349    340   
    use aws_smithy_async::test_util::instant_time_and_sleep;
  350    341   
    use aws_smithy_async::time::StaticTimeSource;
  351    342   
    use aws_smithy_http_client::test_util::{capture_request, ReplayEvent, StaticReplayClient};
  352    343   
    use aws_smithy_runtime::test_util::capture_test_logs::capture_test_logs;
  353    344   
    use aws_smithy_runtime_api::client::behavior_version::BehaviorVersion;
  354    345   
    use aws_smithy_types::body::SdkBody;
@@ -425,416 +566,515 @@
  445    436   
        let auth_header = req.headers().get(AUTHORIZATION).unwrap().to_string();
  446    437   
        let expect = "Credential=123-key/20090213/us-west-17/sts/aws4_request";
  447    438   
        assert!(
  448    439   
            auth_header.contains(expect),
  449    440   
            "Expected header to contain {expect} but it was {auth_header}"
  450    441   
        );
  451    442   
        // ensure that FIPS & DualStack are also respected
  452    443   
        assert_eq!("https://sts-fips.us-west-17.api.aws/", req.uri())
  453    444   
    }
  454    445   
  455         -
    fn create_test_http_client() -> StaticReplayClient {
  456         -
        StaticReplayClient::new(vec![
         446  +
    #[tokio::test]
         447  +
    async fn provider_does_not_cache_credentials_by_default() {
         448  +
        let http_client = StaticReplayClient::new(vec![
  457    449   
            ReplayEvent::new(http::Request::new(SdkBody::from("request body")),
  458    450   
            http::Response::builder().status(200).body(SdkBody::from(
  459    451   
                "<AssumeRoleResponse xmlns=\"https://sts.amazonaws.com/doc/2011-06-15/\">\n  <AssumeRoleResult>\n    <AssumedRoleUser>\n      <AssumedRoleId>AROAR42TAWARILN3MNKUT:assume-role-from-profile-1632246085998</AssumedRoleId>\n      <Arn>arn:aws:sts::130633740322:assumed-role/assume-provider-test/assume-role-from-profile-1632246085998</Arn>\n    </AssumedRoleUser>\n    <Credentials>\n      <AccessKeyId>ASIARCORRECT</AccessKeyId>\n      <SecretAccessKey>secretkeycorrect</SecretAccessKey>\n      <SessionToken>tokencorrect</SessionToken>\n      <Expiration>2009-02-13T23:31:30Z</Expiration>\n    </Credentials>\n  </AssumeRoleResult>\n  <ResponseMetadata>\n    <RequestId>d9d47248-fd55-4686-ad7c-0fb7cd1cddd7</RequestId>\n  </ResponseMetadata>\n</AssumeRoleResponse>\n"
  460    452   
            )).unwrap()),
  461    453   
            ReplayEvent::new(http::Request::new(SdkBody::from("request body")),
  462    454   
            http::Response::builder().status(200).body(SdkBody::from(
  463    455   
                "<AssumeRoleResponse xmlns=\"https://sts.amazonaws.com/doc/2011-06-15/\">\n  <AssumeRoleResult>\n    <AssumedRoleUser>\n      <AssumedRoleId>AROAR42TAWARILN3MNKUT:assume-role-from-profile-1632246085998</AssumedRoleId>\n      <Arn>arn:aws:sts::130633740322:assumed-role/assume-provider-test/assume-role-from-profile-1632246085998</Arn>\n    </AssumedRoleUser>\n    <Credentials>\n      <AccessKeyId>ASIARCORRECT</AccessKeyId>\n      <SecretAccessKey>TESTSECRET</SecretAccessKey>\n      <SessionToken>tokencorrect</SessionToken>\n      <Expiration>2009-02-13T23:33:30Z</Expiration>\n    </Credentials>\n  </AssumeRoleResult>\n  <ResponseMetadata>\n    <RequestId>c2e971c2-702d-4124-9b1f-1670febbea18</RequestId>\n  </ResponseMetadata>\n</AssumeRoleResponse>\n"
  464    456   
            )).unwrap()),
  465         -
        ])
  466         -
    }
  467         -
  468         -
    #[tokio::test]
  469         -
    async fn provider_does_not_cache_credentials_by_default() {
  470         -
        let http_client = create_test_http_client();
         457  +
        ]);
  471    458   
  472    459   
        let (testing_time_source, sleep) = instant_time_and_sleep(
  473    460   
            UNIX_EPOCH + Duration::from_secs(1234567890 - 120), // 1234567890 since UNIX_EPOCH is 2009-02-13T23:31:30Z
  474    461   
        );
  475    462   
  476    463   
        let sdk_config = SdkConfig::builder()
  477    464   
            .sleep_impl(SharedAsyncSleep::new(sleep))
  478    465   
            .time_source(testing_time_source.clone())
  479    466   
            .http_client(http_client)
  480    467   
            .behavior_version(crate::BehaviorVersion::latest())
  481    468   
            .build();
  482    469   
        let credentials_list = std::sync::Arc::new(std::sync::Mutex::new(vec![
  483    470   
            Credentials::new(
  484    471   
                "test",
  485    472   
                "test",
  486    473   
                None,
  487    474   
                Some(UNIX_EPOCH + Duration::from_secs(1234567890 + 1)),
  488    475   
                "test",
  489    476   
            ),
  490    477   
            Credentials::new(
  491    478   
                "test",
  492    479   
                "test",
  493    480   
                None,
  494    481   
                Some(UNIX_EPOCH + Duration::from_secs(1234567890 + 120)),
  495    482   
                "test",
  496    483   
            ),
  497    484   
        ]));
  498    485   
        let credentials_list_cloned = credentials_list.clone();
  499    486   
        let provider = AssumeRoleProvider::builder("myrole")
  500    487   
            .configure(&sdk_config)
  501    488   
            .region(Region::new("us-east-1"))
  502    489   
            .build_from_provider(provide_credentials_fn(move || {
  503    490   
                let list = credentials_list.clone();
  504    491   
                async move {
  505    492   
                    let next = list.lock().unwrap().remove(0);
  506    493   
                    Ok(next)
  507    494   
                }
  508    495   
            }))
  509    496   
            .await;
  510    497   
  511    498   
        let creds_first = provider
  512    499   
            .provide_credentials()
  513    500   
            .await
  514    501   
            .expect("should return valid credentials");
  515    502   
  516    503   
        // After time has been advanced by 120 seconds, the first credentials _could_ still be valid
  517    504   
        // if `LazyCredentialsCache` were used, but the provider uses `NoCredentialsCache` by default
  518    505   
        // so the first credentials will not be used.
  519    506   
        testing_time_source.advance(Duration::from_secs(120));
  520    507   
  521    508   
        let creds_second = provider
  522    509   
            .provide_credentials()
  523    510   
            .await
  524    511   
            .expect("should return the second credentials");
  525    512   
        assert_ne!(creds_first, creds_second);
  526    513   
        assert!(credentials_list_cloned.lock().unwrap().is_empty());
  527    514   
    }
  528         -
  529         -
    #[tokio::test]
  530         -
    async fn credentials_feature() {
  531         -
        let http_client = create_test_http_client();
  532         -
  533         -
        let (testing_time_source, sleep) = instant_time_and_sleep(
  534         -
            UNIX_EPOCH + Duration::from_secs(1234567890), // 1234567890 since UNIX_EPOCH is 2009-02-13T23:31:30Z
  535         -
        );
  536         -
  537         -
        let sdk_config = SdkConfig::builder()
  538         -
            .sleep_impl(SharedAsyncSleep::new(sleep))
  539         -
            .time_source(testing_time_source.clone())
  540         -
            .http_client(http_client)
  541         -
            .behavior_version(crate::BehaviorVersion::latest())
  542         -
            .build();
  543         -
        let credentials = Credentials::new(
  544         -
            "test",
  545         -
            "test",
  546         -
            None,
  547         -
            Some(UNIX_EPOCH + Duration::from_secs(1234567890 + 1)),
  548         -
            "test",
  549         -
        );
  550         -
        let provider = AssumeRoleProvider::builder("myrole")
  551         -
            .configure(&sdk_config)
  552         -
            .region(Region::new("us-east-1"))
  553         -
            .build_from_provider(credentials)
  554         -
            .await;
  555         -
  556         -
        let creds = provider
  557         -
            .provide_credentials()
  558         -
            .await
  559         -
            .expect("should return valid credentials");
  560         -
  561         -
        assert_eq!(
  562         -
            &vec![AwsCredentialFeature::CredentialsStsAssumeRole],
  563         -
            creds.get_property::<Vec<AwsCredentialFeature>>().unwrap()
  564         -
        )
  565         -
    }
  566    515   
}

tmp-codegen-diff/aws-sdk/sdk/aws-config/src/web_identity_token.rs

@@ -36,36 +96,95 @@
   56     56   
//! use aws_config::web_identity_token::WebIdentityTokenCredentialsProvider;
   57     57   
//! use aws_config::provider_config::ProviderConfig;
   58     58   
//! let provider = WebIdentityTokenCredentialsProvider::builder()
   59     59   
//!     .configure(&ProviderConfig::with_default_region().await)
   60     60   
//!     .build();
   61     61   
//! # }
   62     62   
//! ```
   63     63   
   64     64   
use crate::provider_config::ProviderConfig;
   65     65   
use crate::sts;
   66         -
use aws_credential_types::credential_feature::AwsCredentialFeature;
   67     66   
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
   68     67   
use aws_sdk_sts::{types::PolicyDescriptorType, Client as StsClient};
   69     68   
use aws_smithy_async::time::SharedTimeSource;
   70     69   
use aws_smithy_types::error::display::DisplayErrorContext;
   71     70   
use aws_types::os_shim_internal::{Env, Fs};
   72     71   
   73     72   
use std::borrow::Cow;
   74     73   
use std::path::{Path, PathBuf};
   75     74   
   76     75   
const ENV_VAR_TOKEN_FILE: &str = "AWS_WEB_IDENTITY_TOKEN_FILE";
@@ -134,133 +199,192 @@
  154    153   
        load_credentials(
  155    154   
            &self.fs,
  156    155   
            &self.sts_client,
  157    156   
            self.policy.clone(),
  158    157   
            self.policy_arns.clone(),
  159    158   
            &conf.web_identity_token_file,
  160    159   
            &conf.role_arn,
  161    160   
            &conf.session_name,
  162    161   
        )
  163    162   
        .await
  164         -
        .map(|mut creds| {
  165         -
            creds
  166         -
                .get_property_mut_or_default::<Vec<AwsCredentialFeature>>()
  167         -
                .push(AwsCredentialFeature::CredentialsProfileStsWebIdToken);
  168         -
            creds
  169         -
        })
  170    163   
    }
  171    164   
}
  172    165   
  173    166   
/// Builder for [`WebIdentityTokenCredentialsProvider`].
  174    167   
#[derive(Debug, Default)]
  175    168   
pub struct Builder {
  176    169   
    source: Option<Source>,
  177    170   
    config: Option<ProviderConfig>,
  178    171   
    policy: Option<String>,
  179    172   
    policy_arns: Option<Vec<PolicyDescriptorType>>,

tmp-codegen-diff/aws-sdk/sdk/aws-credential-types/Cargo.toml

@@ -1,1 +49,49 @@
    1      1   
# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
    2      2   
[package]
    3      3   
name = "aws-credential-types"
    4         -
version = "1.2.5"
           4  +
version = "1.2.4"
    5      5   
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>"]
    6      6   
description = "Types for AWS SDK credentials."
    7      7   
edition = "2021"
    8      8   
license = "Apache-2.0"
    9      9   
repository = "https://github.com/smithy-lang/smithy-rs"
   10     10   
[package.metadata.docs.rs]
   11     11   
all-features = true
   12     12   
targets = ["x86_64-unknown-linux-gnu"]
   13     13   
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
   14     14   
rustdoc-args = ["--cfg", "docsrs"]
   15     15   
   16     16   
[package.metadata.smithy-rs-release-tooling]
   17     17   
stable = true
   18     18   
   19     19   
[features]
   20     20   
hardcoded-credentials = []
   21     21   
test-util = ["aws-smithy-runtime-api/test-util"]
   22     22   
   23     23   
[dependencies]
   24     24   
zeroize = "1.7.0"
   25     25   
   26     26   
[dependencies.aws-smithy-async]
   27     27   
path = "../aws-smithy-async"
   28     28   
version = "1.2.5"
   29     29   
   30     30   
[dependencies.aws-smithy-types]
   31     31   
path = "../aws-smithy-types"
   32     32   
version = "1.3.2"
   33     33   
   34     34   
[dependencies.aws-smithy-runtime-api]
   35     35   
path = "../aws-smithy-runtime-api"
   36     36   
features = ["client", "http-auth"]
   37         -
version = "1.8.7"
          37  +
version = "1.8.5"
   38     38   
   39     39   
[dev-dependencies]
   40     40   
async-trait = "0.1.74"
   41     41   
   42     42   
[dev-dependencies.aws-smithy-runtime-api]
   43     43   
path = "../aws-smithy-runtime-api"
   44     44   
features = ["test-util"]
   45         -
version = "1.8.7"
          45  +
version = "1.8.5"
   46     46   
   47     47   
[dev-dependencies.tokio]
   48     48   
version = "1.23.1"
   49     49   
features = ["full", "test-util", "rt"]

tmp-codegen-diff/aws-sdk/sdk/aws-credential-types/src/credential_feature.rs

@@ -1,0 +54,0 @@
    1         -
/*
    2         -
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3         -
 * SPDX-License-Identifier: Apache-2.0
    4         -
 */
    5         -
    6         -
use aws_smithy_types::config_bag::{Storable, StoreAppend};
    7         -
    8         -
/// IDs for the credential related features that may be used in the AWS SDK
    9         -
#[non_exhaustive]
   10         -
#[derive(Clone, Debug, Eq, PartialEq)]
   11         -
pub enum AwsCredentialFeature {
   12         -
    /// An operation called using credentials resolved from code, cli parameters, session object, or client instance
   13         -
    CredentialsCode,
   14         -
    /// An operation called using credentials resolved from environment variables
   15         -
    CredentialsEnvVars,
   16         -
    /// An operation called using credentials resolved from environment variables for assuming a role with STS using a web identity token
   17         -
    CredentialsEnvVarsStsWebIdToken,
   18         -
    /// An operation called using credentials resolved from STS using assume role
   19         -
    CredentialsStsAssumeRole,
   20         -
    /// An operation called using credentials resolved from STS using assume role with SAML
   21         -
    CredentialsStsAssumeRoleSaml,
   22         -
    /// An operation called using credentials resolved from STS using assume role with web identity
   23         -
    CredentialsStsAssumeRoleWebId,
   24         -
    /// An operation called using credentials resolved from STS using a federation token
   25         -
    CredentialsStsFederationToken,
   26         -
    /// An operation called using credentials resolved from STS using a session token
   27         -
    CredentialsStsSessionToken,
   28         -
    /// An operation called using credentials resolved from a config file(s) profile with static credentials
   29         -
    CredentialsProfile,
   30         -
    /// An operation called using credentials resolved from a source profile in a config file(s) profile
   31         -
    CredentialsProfileSourceProfile,
   32         -
    /// An operation called using credentials resolved from a named provider in a config file(s) profile
   33         -
    CredentialsProfileNamedProvider,
   34         -
    /// An operation called using credentials resolved from configuration for assuming a role with STS using web identity token in a config file(s) profile
   35         -
    CredentialsProfileStsWebIdToken,
   36         -
    /// An operation called using credentials resolved from an SSO session in a config file(s) profile
   37         -
    CredentialsProfileSso,
   38         -
    /// An operation called using credentials resolved from an SSO session
   39         -
    CredentialsSso,
   40         -
    /// An operation called using credentials resolved from a process in a config file(s) profile
   41         -
    CredentialsProfileProcess,
   42         -
    /// An operation called using credentials resolved from a process
   43         -
    CredentialsProcess,
   44         -
    /// An operation called using credentials resolved from an HTTP endpoint
   45         -
    CredentialsHttp,
   46         -
    /// An operation called using credentials resolved from the instance metadata service (IMDS)
   47         -
    CredentialsImds,
   48         -
    /// An operation called using a Bearer token resolved from service-specific environment variables
   49         -
    BearerServiceEnvVars,
   50         -
}
   51         -
   52         -
impl Storable for AwsCredentialFeature {
   53         -
    type Storer = StoreAppend<Self>;
   54         -
}