Unverified Commit 3c68521c authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Remove middleware code when generating the orchestrator exclusively (#2723)

## Motivation and Context
This PR removes all the middleware code from generated clients when the
`smithy.runtime.mode` flag is set to `orchestrator`. It also changes the
`aws-config` crate to use the fluent client instead of the Smithy client
for STS and SSO based credential providers.

The `polly` test no longer compiles in orchestrator mode with these
changes since presigning directly references middleware code. This will
get fixed in a later PR.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
parent 7ccac060
Loading
Loading
Loading
Loading
+5 −8
Original line number Diff line number Diff line
@@ -23,12 +23,13 @@
//! through a series of providers.

use crate::profile::credentials::exec::named::NamedProviderFactory;
use crate::profile::credentials::exec::{ClientConfiguration, ProviderChain};
use crate::profile::credentials::exec::ProviderChain;
use crate::profile::parser::ProfileFileLoadError;
use crate::profile::profile_file::ProfileFiles;
use crate::profile::Profile;
use crate::provider_config::ProviderConfig;
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
use aws_sdk_sts::config::Builder as StsConfigBuilder;
use aws_smithy_types::error::display::DisplayErrorContext;
use std::borrow::Cow;
use std::collections::HashMap;
@@ -141,7 +142,7 @@ impl ProvideCredentials for ProfileFileCredentialsProvider {
#[derive(Debug)]
pub struct ProfileFileCredentialsProvider {
    factory: NamedProviderFactory,
    client_config: ClientConfiguration,
    sts_config: StsConfigBuilder,
    provider_config: ProviderConfig,
}

@@ -181,7 +182,7 @@ impl ProfileFileCredentialsProvider {
        };
        for provider in inner_provider.chain().iter() {
            let next_creds = provider
                .credentials(creds, &self.client_config)
                .credentials(creds, &self.sts_config)
                .instrument(tracing::debug_span!("load_assume_role", provider = ?provider))
                .await;
            match next_creds {
@@ -440,14 +441,10 @@ impl Builder {
                )
            });
        let factory = exec::named::NamedProviderFactory::new(named_providers);
        let core_client = conf.sts_client();

        ProfileFileCredentialsProvider {
            factory,
            client_config: ClientConfiguration {
                sts_client: core_client,
                region: conf.region(),
            },
            sts_config: conf.sts_client_config(),
            provider_config: conf,
        }
    }
+12 −25
Original line number Diff line number Diff line
@@ -8,15 +8,12 @@ use crate::credential_process::CredentialProcessProvider;
use crate::profile::credentials::ProfileFileError;
use crate::provider_config::ProviderConfig;
#[cfg(feature = "credentials-sso")]
use crate::sso::{SsoConfig, SsoCredentialsProvider};
use crate::sso::{SsoCredentialsProvider, SsoProviderConfig};
use crate::sts;
use crate::web_identity_token::{StaticConfiguration, WebIdentityTokenCredentialsProvider};
use aws_credential_types::provider::{self, error::CredentialsError, ProvideCredentials};
use aws_sdk_sts::middleware::DefaultMiddleware;
use aws_sdk_sts::operation::assume_role::AssumeRoleInput;
use aws_sdk_sts::{config::Credentials, Config};
use aws_smithy_client::erase::DynConnector;
use aws_types::region::Region;
use aws_sdk_sts::config::{Builder as StsConfigBuilder, Credentials};
use aws_sdk_sts::Client as StsClient;
use std::fmt::Debug;
use std::sync::Arc;

@@ -27,39 +24,28 @@ pub(super) struct AssumeRoleProvider {
    session_name: Option<String>,
}

#[derive(Debug)]
pub(super) struct ClientConfiguration {
    pub(super) sts_client: aws_smithy_client::Client<DynConnector, DefaultMiddleware>,
    pub(super) region: Option<Region>,
}

impl AssumeRoleProvider {
    pub(super) async fn credentials(
        &self,
        input_credentials: Credentials,
        client_config: &ClientConfiguration,
        sts_config: &StsConfigBuilder,
    ) -> provider::Result {
        let config = Config::builder()
        let config = sts_config
            .clone()
            .credentials_provider(input_credentials)
            .region(client_config.region.clone())
            .build();
        let client = StsClient::from_conf(config);
        let session_name = &self
            .session_name
            .as_ref()
            .cloned()
            .unwrap_or_else(|| sts::util::default_session_name("assume-role-from-profile"));
        let operation = AssumeRoleInput::builder()
        let assume_role_creds = client
            .assume_role()
            .role_arn(&self.role_arn)
            .set_external_id(self.external_id.clone())
            .role_session_name(session_name)
            .build()
            .expect("operation is valid")
            .make_operation(&config)
            .await
            .expect("valid operation");
        let assume_role_creds = client_config
            .sts_client
            .call(operation)
            .send()
            .await
            .map_err(CredentialsError::provider_error)?
            .credentials;
@@ -127,7 +113,8 @@ impl ProviderChain {
            } => {
                #[cfg(feature = "credentials-sso")]
                {
                    let sso_config = SsoConfig {
                    use aws_types::region::Region;
                    let sso_config = SsoProviderConfig {
                        account_id: sso_account_id.to_string(),
                        role_name: sso_role_name.to_string(),
                        start_url: sso_start_url.to_string(),
+39 −41
Original line number Diff line number Diff line
@@ -17,10 +17,8 @@ use crate::provider_config::ProviderConfig;
use aws_credential_types::cache::CredentialsCache;
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
use aws_credential_types::Credentials;
use aws_sdk_sso::middleware::DefaultMiddleware as SsoMiddleware;
use aws_sdk_sso::operation::get_role_credentials::GetRoleCredentialsInput;
use aws_sdk_sso::types::RoleCredentials;
use aws_smithy_client::erase::DynConnector;
use aws_sdk_sso::{config::Builder as SsoConfigBuilder, Client as SsoClient, Config as SsoConfig};
use aws_smithy_json::deserialize::Token;
use aws_smithy_types::date_time::Format;
use aws_smithy_types::DateTime;
@@ -33,23 +31,11 @@ use std::fmt::{Display, Formatter};
use std::io;
use std::path::PathBuf;

use crate::connector::expect_connector;
use aws_smithy_types::retry::RetryConfig;
use ring::digest;
use zeroize::Zeroizing;

impl crate::provider_config::ProviderConfig {
    pub(crate) fn sso_client(
        &self,
    ) -> aws_smithy_client::Client<aws_smithy_client::erase::DynConnector, SsoMiddleware> {
        use crate::connector::expect_connector;

        let mut client_builder = aws_smithy_client::Client::builder()
            .connector(expect_connector(self.connector(&Default::default())))
            .middleware(SsoMiddleware::default());
        client_builder.set_sleep_impl(self.sleep());
        client_builder.build()
    }
}

/// SSO Credentials Provider
///
/// _Note: This provider is part of the default credentials chain and is integrated with the profile-file provider._
@@ -60,8 +46,8 @@ impl crate::provider_config::ProviderConfig {
pub struct SsoCredentialsProvider {
    fs: Fs,
    env: Env,
    sso_config: SsoConfig,
    client: aws_smithy_client::Client<DynConnector, SsoMiddleware>,
    sso_provider_config: SsoProviderConfig,
    sso_config: SsoConfigBuilder,
}

impl SsoCredentialsProvider {
@@ -70,20 +56,36 @@ impl SsoCredentialsProvider {
        Builder::new()
    }

    pub(crate) fn new(provider_config: &ProviderConfig, sso_config: SsoConfig) -> Self {
    pub(crate) fn new(
        provider_config: &ProviderConfig,
        sso_provider_config: SsoProviderConfig,
    ) -> Self {
        let fs = provider_config.fs();
        let env = provider_config.env();

        let mut sso_config = SsoConfig::builder()
            .http_connector(expect_connector(
                provider_config.connector(&Default::default()),
            ))
            .retry_config(RetryConfig::standard());
        sso_config.set_sleep_impl(provider_config.sleep());

        SsoCredentialsProvider {
            fs,
            env,
            client: provider_config.sso_client(),
            sso_provider_config,
            sso_config,
        }
    }

    async fn credentials(&self) -> provider::Result {
        load_sso_credentials(&self.sso_config, &self.client, &self.env, &self.fs).await
        load_sso_credentials(
            &self.sso_provider_config,
            &self.sso_config,
            &self.env,
            &self.fs,
        )
        .await
    }
}

@@ -152,7 +154,7 @@ impl Builder {
    /// - [`region`](Self::region)
    pub fn build(self) -> SsoCredentialsProvider {
        let provider_config = self.provider_config.unwrap_or_default();
        let sso_config = SsoConfig {
        let sso_config = SsoProviderConfig {
            account_id: self.account_id.expect("account_id must be set"),
            role_name: self.role_name.expect("role_name must be set"),
            start_url: self.start_url.expect("start_url must be set"),
@@ -194,7 +196,7 @@ impl Error for LoadTokenError {
}

#[derive(Debug)]
pub(crate) struct SsoConfig {
pub(crate) struct SsoProviderConfig {
    pub(crate) account_id: String,
    pub(crate) role_name: String,
    pub(crate) start_url: String,
@@ -202,31 +204,27 @@ pub(crate) struct SsoConfig {
}

async fn load_sso_credentials(
    sso_config: &SsoConfig,
    sso: &aws_smithy_client::Client<DynConnector, SsoMiddleware>,
    sso_provider_config: &SsoProviderConfig,
    sso_config: &SsoConfigBuilder,
    env: &Env,
    fs: &Fs,
) -> provider::Result {
    let token = load_token(&sso_config.start_url, env, fs)
    let token = load_token(&sso_provider_config.start_url, env, fs)
        .await
        .map_err(CredentialsError::provider_error)?;
    let config = aws_sdk_sso::Config::builder()
        .region(sso_config.region.clone())
    let config = sso_config
        .clone()
        .region(sso_provider_config.region.clone())
        .credentials_cache(CredentialsCache::no_caching())
        .build();
    let operation = GetRoleCredentialsInput::builder()
        .role_name(&sso_config.role_name)
    // TODO(enableNewSmithyRuntime): Use `customize().config_override()` to set the region instead of creating a new client once middleware is removed
    let client = SsoClient::from_conf(config);
    let resp = client
        .get_role_credentials()
        .role_name(&sso_provider_config.role_name)
        .access_token(&*token.access_token)
        .account_id(&sso_config.account_id)
        .build()
        .map_err(|err| {
            CredentialsError::unhandled(format!("could not construct SSO token input: {}", err))
        })?
        .make_operation(&config)
        .await
        .map_err(CredentialsError::unhandled)?;
    let resp = sso
        .call(operation)
        .account_id(&sso_provider_config.account_id)
        .send()
        .await
        .map_err(CredentialsError::provider_error)?;
    let credentials: RoleCredentials = resp
+12 −10
Original line number Diff line number Diff line
@@ -5,23 +5,25 @@

//! Credential provider augmentation through the AWS Security Token Service (STS).

use crate::connector::expect_connector;
use aws_sdk_sts::middleware::DefaultMiddleware;
use aws_smithy_client::erase::DynConnector;
use aws_smithy_client::Client;

pub(crate) mod util;

pub use assume_role::{AssumeRoleProvider, AssumeRoleProviderBuilder};

mod assume_role;

use crate::connector::expect_connector;
use aws_credential_types::cache::CredentialsCache;
use aws_sdk_sts::config::Builder as StsConfigBuilder;
use aws_smithy_types::retry::RetryConfig;

impl crate::provider_config::ProviderConfig {
    pub(crate) fn sts_client(&self) -> Client<DynConnector, DefaultMiddleware> {
        let mut builder = Client::builder()
            .connector(expect_connector(self.connector(&Default::default())))
            .middleware(DefaultMiddleware::default());
    pub(crate) fn sts_client_config(&self) -> StsConfigBuilder {
        let mut builder = aws_sdk_sts::Config::builder()
            .http_connector(expect_connector(self.connector(&Default::default())))
            .retry_config(RetryConfig::standard())
            .region(self.region())
            .credentials_cache(CredentialsCache::no_caching());
        builder.set_sleep_impl(self.sleep());
        builder.build()
        builder
    }
}
+14 −32
Original line number Diff line number Diff line
@@ -5,12 +5,14 @@

//! Assume credentials for a role through the AWS Security Token Service (STS).

use crate::connector::expect_connector;
use crate::provider_config::ProviderConfig;
use aws_credential_types::cache::CredentialsCache;
use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials};
use aws_sdk_sts::middleware::DefaultMiddleware;
use aws_sdk_sts::operation::assume_role::{AssumeRoleError, AssumeRoleInput};
use aws_sdk_sts::operation::assume_role::builders::AssumeRoleFluentBuilder;
use aws_sdk_sts::operation::assume_role::AssumeRoleError;
use aws_sdk_sts::types::PolicyDescriptorType;
use aws_sdk_sts::Client as StsClient;
use aws_smithy_client::erase::DynConnector;
use aws_smithy_http::result::SdkError;
use aws_smithy_types::error::display::DisplayErrorContext;
@@ -46,9 +48,7 @@ pub struct AssumeRoleProvider {

#[derive(Debug)]
struct Inner {
    sts: aws_smithy_client::Client<DynConnector, DefaultMiddleware>,
    conf: aws_sdk_sts::Config,
    op: AssumeRoleInput,
    fluent_builder: AssumeRoleFluentBuilder,
}

impl AssumeRoleProvider {
@@ -208,41 +208,29 @@ impl AssumeRoleProviderBuilder {
            .credentials_cache
            .unwrap_or_else(CredentialsCache::no_caching);

        let config = aws_sdk_sts::Config::builder()
        let mut config = aws_sdk_sts::Config::builder()
            .credentials_cache(credentials_cache)
            .credentials_provider(provider)
            .region(self.region.clone())
            .build();

        let conn = conf
            .connector(&Default::default())
            .expect("A connector must be provided");
        let mut client_builder = aws_smithy_client::Client::builder()
            .connector(conn)
            .middleware(DefaultMiddleware::new());
        client_builder.set_sleep_impl(conf.sleep());
        let client = client_builder.build();
            .http_connector(expect_connector(conf.connector(&Default::default())));
        config.set_sleep_impl(conf.sleep());

        let session_name = self
            .session_name
            .unwrap_or_else(|| super::util::default_session_name("assume-role-provider"));

        let operation = AssumeRoleInput::builder()
        let sts_client = StsClient::from_conf(config.build());
        let fluent_builder = sts_client
            .assume_role()
            .set_role_arn(Some(self.role_arn))
            .set_external_id(self.external_id)
            .set_role_session_name(Some(session_name))
            .set_policy(self.policy)
            .set_policy_arns(self.policy_arns)
            .set_duration_seconds(self.session_length.map(|dur| dur.as_secs() as i32))
            .build()
            .expect("operation is valid");
            .set_duration_seconds(self.session_length.map(|dur| dur.as_secs() as i32));

        AssumeRoleProvider {
            inner: Inner {
                sts: client,
                conf: config,
                op: operation,
            },
            inner: Inner { fluent_builder },
        }
    }
}
@@ -250,14 +238,8 @@ impl AssumeRoleProviderBuilder {
impl Inner {
    async fn credentials(&self) -> provider::Result {
        tracing::debug!("retrieving assumed credentials");
        let op = self
            .op
            .clone()
            .make_operation(&self.conf)
            .await
            .expect("valid operation");

        let assumed = self.sts.call(op).in_current_span().await;
        let assumed = self.fluent_builder.clone().send().in_current_span().await;
        match assumed {
            Ok(assumed) => {
                tracing::debug!(
Loading