Unverified Commit 08196ec8 authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Remove remaining middleware code (#3038)

This PR removes the remaining rust-runtime code to support middleware,
deprecates empty crates, and removes the remaining codegen references to
any of that code. In the interest of keeping code review easier, a
separate PR will finish addressing the remaining
`TODO(enableNewSmithyRuntime)` comments.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
parent 26a914ec
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -17,6 +17,12 @@ references = ["smithy-rs#3011"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "jdisanti"

[[smithy-rs]]
message = "The `enableNewSmithyRuntime: middleware` opt-out flag in smithy-build.json has been removed and no longer opts out of the client orchestrator implementation. Middleware is no longer supported. If you haven't already upgraded to the orchestrator, see [the guide](https://github.com/awslabs/smithy-rs/discussions/2887)."
references = ["smithy-rs#3038"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "jdisanti"

[[aws-sdk-rust]]
message = "HTTP connector configuration has changed significantly. See the [upgrade guidance](https://github.com/awslabs/smithy-rs/discussions/3022) for details."
references = ["smithy-rs#3011"]
@@ -279,3 +285,9 @@ message = "STS and SSO-based credential providers will now respect both `use_fip
references = ["aws-sdk-rust#882", "smithy-rs#3007"]
meta = { "breaking" = true, "tada" = true, "bug" = true }
author = "Velfi"

[[smithy-rs]]
message = "`SdkError` is no longer re-exported in generated server crates."
references = ["smithy-rs#3038"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "server" }
author = "jdisanti"
+1 −8
Original line number Diff line number Diff line
@@ -2,18 +2,11 @@
name = "aws-endpoint"
version = "0.0.0-smithy-rs-head"
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>", "Russell Cohen <rcoh@amazon.com>"]
description = "AWS SDK endpoint support."
description = "This crate is no longer used by the AWS SDK and is deprecated."
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/awslabs/smithy-rs"

[dependencies]
aws-smithy-http = { path = "../../../rust-runtime/aws-smithy-http" }
aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types"}
aws-types = { path = "../aws-types" }
http = "0.2.3"
tracing = "0.1"

[package.metadata.docs.rs]
all-features = true
targets = ["x86_64-unknown-linux-gnu"]
+2 −1
Original line number Diff line number Diff line
# aws-endpoint
This crate defines endpoint resolution logic specific to AWS services.

This crate is no longer used by the AWS SDK and is deprecated.

<!-- anchor_start:footer -->
This crate is part of the [AWS SDK for Rust](https://awslabs.github.io/aws-sdk-rust/) and the [smithy-rs](https://github.com/awslabs/smithy-rs) code generator. In most cases, it should not be used directly.
+1 −5
Original line number Diff line number Diff line
allowed_external_types = [
    "aws_types::*",
    "aws_smithy_http::property_bag::PropertyBag",
    "aws_smithy_http::middleware::MapRequest",
]
allowed_external_types = []
+1 −237
Original line number Diff line number Diff line
@@ -3,240 +3,4 @@
 * SPDX-License-Identifier: Apache-2.0
 */

#![allow(clippy::derive_partial_eq_without_eq)]

use std::error::Error;
use std::fmt;

use aws_smithy_http::middleware::MapRequest;
use aws_smithy_http::operation::Request;
use aws_smithy_types::endpoint::Endpoint as SmithyEndpoint;
use aws_smithy_types::Document;

use aws_types::region::{Region, SigningRegion};
use aws_types::SigningName;

/// Middleware Stage to add authentication information from a Smithy endpoint into the property bag
///
/// AwsAuthStage implements [`MapRequest`](MapRequest). It will:
/// 1. Load an endpoint from the property bag
/// 2. Set the `SigningRegion` and `SigningName` in the property bag to drive downstream
/// signing middleware.
#[derive(Clone, Debug)]
pub struct AwsAuthStage;

#[derive(Debug)]
enum AwsAuthStageErrorKind {
    NoEndpointResolver,
    EndpointResolutionError(Box<dyn Error + Send + Sync>),
}

#[derive(Debug)]
pub struct AwsAuthStageError {
    kind: AwsAuthStageErrorKind,
}

impl fmt::Display for AwsAuthStageError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use AwsAuthStageErrorKind::*;
        match &self.kind {
            NoEndpointResolver => write!(f, "endpoint resolution failed: no endpoint present"),
            EndpointResolutionError(_) => write!(f, "endpoint resolution failed"),
        }
    }
}

impl Error for AwsAuthStageError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        use AwsAuthStageErrorKind::*;
        match &self.kind {
            EndpointResolutionError(source) => Some(source.as_ref() as _),
            NoEndpointResolver => None,
        }
    }
}

impl From<AwsAuthStageErrorKind> for AwsAuthStageError {
    fn from(kind: AwsAuthStageErrorKind) -> Self {
        Self { kind }
    }
}

impl MapRequest for AwsAuthStage {
    type Error = AwsAuthStageError;

    fn name(&self) -> &'static str {
        "resolve_endpoint"
    }

    fn apply(&self, request: Request) -> Result<Request, Self::Error> {
        request.augment(|http_req, props| {
            let endpoint = props
                .get::<aws_smithy_types::endpoint::Endpoint>()
                .ok_or(AwsAuthStageErrorKind::NoEndpointResolver)?;
            let (signing_region_override, signing_name_override) = smithy_to_aws(endpoint)
                .map_err(|err| AwsAuthStageErrorKind::EndpointResolutionError(err))?;

            if let Some(signing_region) = signing_region_override {
                props.insert(signing_region);
            }
            if let Some(signing_name) = signing_name_override {
                props.insert(signing_name);
            }
            Ok(http_req)
        })
    }
}

type EndpointMetadata = (Option<SigningRegion>, Option<SigningName>);

fn smithy_to_aws(value: &SmithyEndpoint) -> Result<EndpointMetadata, Box<dyn Error + Send + Sync>> {
    // look for v4 as an auth scheme
    let auth_schemes = match value.properties().get("authSchemes") {
        Some(Document::Array(schemes)) => schemes,
        // no auth schemes:
        None => return Ok((None, None)),
        _other => return Err("expected an array for authSchemes".into()),
    };
    let auth_schemes = auth_schemes
        .iter()
        .flat_map(|doc| match doc {
            Document::Object(map) => Some(map),
            _ => None,
        })
        .map(|it| {
            let name = match it.get("name") {
                Some(Document::String(s)) => Some(s.as_str()),
                _ => None,
            };
            (name, it)
        });
    let (_, v4) = auth_schemes
        .clone()
        .find(|(name, _doc)| name.as_deref() == Some("sigv4"))
        .ok_or_else(|| {
            format!(
                "No auth schemes were supported. The Rust SDK only supports sigv4. \
                The authentication schemes supported by this endpoint were: {:?}",
                auth_schemes.flat_map(|(name, _)| name).collect::<Vec<_>>()
            )
        })?;

    let signing_scope = match v4.get("signingRegion") {
        Some(Document::String(s)) => Some(SigningRegion::from(Region::new(s.clone()))),
        None => None,
        _ => return Err("unexpected type".into()),
    };
    let signing_name = match v4.get("signingName") {
        Some(Document::String(s)) => Some(SigningName::from(s.to_string())),
        None => None,
        _ => return Err("unexpected type".into()),
    };
    Ok((signing_scope, signing_name))
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;

    use aws_smithy_http::body::SdkBody;
    use aws_smithy_http::middleware::MapRequest;
    use aws_smithy_http::operation;
    use aws_smithy_types::endpoint::Endpoint;
    use aws_smithy_types::Document;
    use http::header::HOST;

    use aws_types::region::{Region, SigningRegion};
    use aws_types::SigningName;

    use crate::AwsAuthStage;

    #[test]
    fn default_endpoint_updates_request() {
        let endpoint = Endpoint::builder()
            .url("kinesis.us-east-1.amazon.com")
            .build();
        let req = http::Request::new(SdkBody::from(""));
        let region = Region::new("us-east-1");
        let mut req = operation::Request::new(req);
        {
            let mut props = req.properties_mut();
            props.insert(SigningRegion::from(region.clone()));
            props.insert(SigningName::from_static("kinesis"));
            props.insert(endpoint);
        };
        let req = AwsAuthStage.apply(req).expect("should succeed");
        assert_eq!(req.properties().get(), Some(&SigningRegion::from(region)));
        assert_eq!(
            req.properties().get(),
            Some(&SigningName::from_static("kinesis"))
        );

        assert!(req.http().headers().get(HOST).is_none());
        assert!(
            req.properties().get::<Endpoint>().is_some(),
            "Endpoint middleware MUST leave the result in the bag"
        );
    }

    #[test]
    fn sets_service_override_when_set() {
        let endpoint = Endpoint::builder()
            .url("kinesis.us-east-override.amazon.com")
            .property(
                "authSchemes",
                vec![Document::Object({
                    let mut out = HashMap::new();
                    out.insert("name".to_string(), "sigv4".to_string().into());
                    out.insert(
                        "signingName".to_string(),
                        "qldb-override".to_string().into(),
                    );
                    out.insert(
                        "signingRegion".to_string(),
                        "us-east-override".to_string().into(),
                    );
                    out
                })],
            )
            .build();
        let req = http::Request::new(SdkBody::from(""));
        let region = Region::new("us-east-1");
        let mut req = operation::Request::new(req);
        {
            let mut props = req.properties_mut();
            props.insert(region);
            props.insert(SigningName::from_static("qldb"));
            props.insert(endpoint);
        };
        let req = AwsAuthStage.apply(req).expect("should succeed");
        assert_eq!(
            req.properties().get(),
            Some(&SigningRegion::from_static("us-east-override"))
        );
        assert_eq!(
            req.properties().get(),
            Some(&SigningName::from_static("qldb-override"))
        );
    }

    #[test]
    fn supports_fallback_when_scope_is_unset() {
        let endpoint = Endpoint::builder().url("www.service.com").build();
        let req = http::Request::new(SdkBody::from(""));
        let region = SigningRegion::from_static("us-east-1");
        let mut req = operation::Request::new(req);
        {
            let mut props = req.properties_mut();
            props.insert(region.clone());
            props.insert(SigningName::from_static("qldb"));
            props.insert(endpoint);
        };
        let req = AwsAuthStage.apply(req).expect("should succeed");
        assert_eq!(req.properties().get(), Some(&region));
        assert_eq!(
            req.properties().get(),
            Some(&SigningName::from_static("qldb"))
        );
    }
}
//! This crate is no longer used by the AWS SDK and is deprecated.
Loading