Unverified Commit 40cab688 authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

Aws config feature simplification (#1017)



* Massively simplify features in aws-config

* Update example

* Update changelog

Co-authored-by: default avatarZelda Hessler <zhessler@amazon.com>
parent 6e31166c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -92,3 +92,9 @@ message = "Example for Config builder region function added"
references = ["smithy-rs#670"]
meta = { "breaking" = false, "tada" = false, "bug" = false }
author = "Jacco"

[[aws-sdk-rust]]
message = "Simplify features in aws-config. All features have been removed from `aws-config` with the exception of: `rt-tokio`, `rustls` and `native-tls`. All other features are now included by default. If you depended on those features specifically, remove them from your features listing."
references = ["smithy-rs#1017", "smithy-rs#930"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "rcoh"
+6 −18
Original line number Diff line number Diff line
@@ -9,21 +9,14 @@ license = "Apache-2.0"
repository = "https://github.com/awslabs/smithy-rs"

[features]
default-provider = ["profile", "imds", "sts", "http-provider", "web-identity-token"]
profile = ["sts", "web-identity-token", "imds", "http-provider"]
imds = ["profile", "aws-smithy-http-tower", "aws-smithy-http", "aws-smithy-json", "aws-http"]
sts = ["aws-sdk-sts", "aws-smithy-http"]
web-identity-token = ["sts", "profile"]
http-provider = ["aws-smithy-json", "aws-smithy-http"]

rustls = ["aws-smithy-client/rustls"]
native-tls = ["aws-smithy-client/native-tls"]
rt-tokio = ["aws-smithy-async/rt-tokio"]

default = ["default-provider", "rustls", "rt-tokio"]
default = ["rustls", "rt-tokio"]

[dependencies]
aws-sdk-sts = { path = "../../sdk/build/aws-sdk/sdk/sts", default-features = false, optional = true }
aws-sdk-sts = { path = "../../sdk/build/aws-sdk/sdk/sts", default-features = false }
aws-smithy-async = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-async" }
aws-smithy-client = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-client" }
aws-smithy-types = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-types" }
@@ -32,11 +25,10 @@ tokio = { version = "1", features = ["sync"] }
tracing = { version = "0.1" }
hyper = { version = "0.14.16", default-features = false }

# imds
aws-http = { path = "../../sdk/build/aws-sdk/sdk/aws-http", optional = true }
aws-smithy-http = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-http", optional = true }
aws-smithy-http-tower = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-http-tower", optional = true }
aws-smithy-json = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-json", optional = true }
aws-http = { path = "../../sdk/build/aws-sdk/sdk/aws-http" }
aws-smithy-http = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-http" }
aws-smithy-http-tower = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-http-tower" }
aws-smithy-json = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-json" }
bytes = "1.1.0"
http = "0.2.4"
tower = { version = "0.4.8" }
@@ -67,7 +59,3 @@ all-features = true
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--cfg", "docsrs"]
# End of docs.rs metadata

[[example]]
name = "imds"
required-features = ["imds"]
+1 −1
Original line number Diff line number Diff line
@@ -15,4 +15,4 @@ echo "### Testing with all features enabled"
cargo test --all-features

echo "### Testing each feature in isolation"
cargo hack test --each-feature --skip default
cargo hack test --feature-powerset
+0 −1
Original line number Diff line number Diff line
@@ -697,7 +697,6 @@ pub mod credentials {

        #[tokio::test]
        #[traced_test]
        #[cfg(feature = "tcp-connector")]
        async fn no_providers_configured_err() {
            use aws_smithy_async::rt::sleep::TokioSleep;
            use aws_smithy_client::erase::boxclone::BoxCloneService;
+40 −25
Original line number Diff line number Diff line
@@ -144,10 +144,8 @@ impl Provider {
        if let Some(relative_uri) = relative_uri {
            Self::build_full_uri(relative_uri)
        } else if let Some(full_uri) = full_uri {
            let mut dns = dns
                .or_else(tokio_dns)
                .expect("a dns service must be provided");
            validate_full_uri(&full_uri, &mut dns)
            let mut dns = dns.or_else(tokio_dns);
            validate_full_uri(&full_uri, dns.as_mut())
                .await
                .map_err(|err| EcsConfigurationErr::InvalidFullUri { err, uri: full_uri })
        } else {
@@ -305,6 +303,10 @@ pub enum InvalidFullUriError {
    #[non_exhaustive]
    InvalidUri(InvalidUri),

    /// No Dns service was provided
    #[non_exhaustive]
    NoDnsService,

    /// The URI did not specify a host
    #[non_exhaustive]
    MissingHost,
@@ -332,6 +334,7 @@ impl Display for InvalidFullUriError {
                    err
                )
            }
            InvalidFullUriError::NoDnsService => write!(f, "No DNS service was provided. Enable `rt-tokio` or provide a `dns` service to the builder.")
        }
    }
}
@@ -355,7 +358,10 @@ pub type DnsService = BoxCloneService<String, Vec<IpAddr>, io::Error>;
/// 2. The URL refers to a loopback device. If a URL contains a domain name instead of an IP address,
/// a DNS lookup will be performed. ALL resolved IP addresses MUST refer to a loopback interface, or
/// the credentials provider will return `CredentialsError::InvalidConfiguration`
async fn validate_full_uri(uri: &str, dns: &mut DnsService) -> Result<Uri, InvalidFullUriError> {
async fn validate_full_uri(
    uri: &str,
    dns: Option<&mut DnsService>,
) -> Result<Uri, InvalidFullUriError> {
    let uri = uri
        .parse::<Uri>()
        .map_err(InvalidFullUriError::InvalidUri)?;
@@ -367,6 +373,7 @@ async fn validate_full_uri(uri: &str, dns: &mut DnsService) -> Result<Uri, Inval
    let is_loopback = match host.parse::<IpAddr>() {
        Ok(addr) => addr.is_loopback(),
        Err(_domain_name) => {
            let dns = dns.ok_or(InvalidFullUriError::NoDnsService)?;
            dns.ready().await.map_err(InvalidFullUriError::DnsLookupFailed)?
                    .call(host.to_owned())
                    .await
@@ -381,7 +388,7 @@ async fn validate_full_uri(uri: &str, dns: &mut DnsService) -> Result<Uri, Inval
                        };
                        addr.is_loopback()
                    })
            },
        }
    };
    match is_loopback {
        true => Ok(uri),
@@ -431,7 +438,7 @@ fn tokio_dns() -> Option<DnsService> {
    Some(BoxCloneService::new(TokioDns))
}

#[cfg(all(test, feature = "default-provider"))]
#[cfg(test)]
mod test {
    use aws_smithy_client::erase::boxclone::BoxCloneService;
    use aws_smithy_client::never::NeverService;
@@ -509,9 +516,9 @@ mod test {
    fn validate_uri_https() {
        // over HTTPs, any URI is fine
        let never = NeverService::new();
        let mut dns = BoxCloneService::new(never);
        let mut dns = Some(BoxCloneService::new(never));
        assert_eq!(
            validate_full_uri("https://amazon.com", &mut dns)
            validate_full_uri("https://amazon.com", None)
                .now_or_never()
                .unwrap()
                .expect("valid"),
@@ -519,26 +526,34 @@ mod test {
        );
        // over HTTP, it will try to lookup
        assert!(
            validate_full_uri("http://amazon.com", &mut dns)
            validate_full_uri("http://amazon.com", dns.as_mut())
                .now_or_never()
                .is_none(),
            "DNS lookup should occur, but it will never return"
        );

        let no_dns_error = validate_full_uri("http://amazon.com", None)
            .now_or_never()
            .unwrap()
            .expect_err("DNS service is required");
        assert!(
            matches!(no_dns_error, InvalidFullUriError::NoDnsService),
            "expected no dns service, got: {}",
            no_dns_error
        );
    }

    #[test]
    fn valid_uri_loopback() {
        let never = NeverService::new();
        let mut dns = BoxCloneService::new(never);
        assert_eq!(
            validate_full_uri("http://127.0.0.1:8080/get-credentials", &mut dns)
            validate_full_uri("http://127.0.0.1:8080/get-credentials", None)
                .now_or_never()
                .unwrap()
                .expect("valid uri"),
            Uri::from_static("http://127.0.0.1:8080/get-credentials")
        );

        let err = validate_full_uri("http://192.168.10.120/creds", &mut dns)
        let err = validate_full_uri("http://192.168.10.120/creds", None)
            .now_or_never()
            .unwrap()
            .expect_err("not a loopback");
@@ -551,8 +566,8 @@ mod test {
            "127.0.0.1".parse().unwrap(),
            "127.0.0.2".parse().unwrap(),
        ]);
        let mut svc = BoxCloneService::new(svc);
        let resp = validate_full_uri("http://localhost:8888", &mut svc)
        let mut svc = Some(BoxCloneService::new(svc));
        let resp = validate_full_uri("http://localhost:8888", svc.as_mut())
            .now_or_never()
            .unwrap();
        assert!(resp.is_ok(), "Should be valid: {:?}", resp);
@@ -564,8 +579,8 @@ mod test {
            "127.0.0.1".parse().unwrap(),
            "192.168.0.1".parse().unwrap(),
        ]);
        let mut svc = BoxCloneService::new(svc);
        let resp = validate_full_uri("http://localhost:8888", &mut svc)
        let mut svc = Some(BoxCloneService::new(svc));
        let resp = validate_full_uri("http://localhost:8888", svc.as_mut())
            .now_or_never()
            .unwrap();
        assert!(
@@ -674,15 +689,15 @@ mod test {
    #[traced_test]
    #[ignore]
    async fn real_dns_lookup() {
        let mut dns = tokio_dns().expect("feature must be enabled");
        let err = validate_full_uri("http://www.amazon.com/creds", &mut dns)
        let mut dns = Some(tokio_dns().expect("feature must be enabled"));
        let err = validate_full_uri("http://www.amazon.com/creds", dns.as_mut())
            .await
            .expect_err("not a loopback");
        assert!(matches!(err, InvalidFullUriError::NotLoopback), "{:?}", err);
        assert!(logs_contain(
            "Address does not resolve to the loopback interface"
        ));
        validate_full_uri("http://localhost:8888/creds", &mut dns)
        validate_full_uri("http://localhost:8888/creds", dns.as_mut())
            .await
            .expect("localhost is the loopback interface");
    }
Loading