From 3826d76674e2d43e6dbe490e5af783f798f03956 Mon Sep 17 00:00:00 2001 From: Harry Barber Date: Tue, 20 Sep 2022 17:22:37 +0000 Subject: [PATCH 1/3] Add InstrumentLayer and InstrumentPlugin --- .../src/logging/layer.rs | 65 +++++++++++++++++++ .../aws-smithy-http-server/src/logging/mod.rs | 4 ++ .../src/logging/plugin.rs | 47 ++++++++++++++ .../src/logging/sensitivity/mod.rs | 18 +++++ 4 files changed, 134 insertions(+) create mode 100644 rust-runtime/aws-smithy-http-server/src/logging/layer.rs create mode 100644 rust-runtime/aws-smithy-http-server/src/logging/plugin.rs diff --git a/rust-runtime/aws-smithy-http-server/src/logging/layer.rs b/rust-runtime/aws-smithy-http-server/src/logging/layer.rs new file mode 100644 index 0000000000..956fd6b24d --- /dev/null +++ b/rust-runtime/aws-smithy-http-server/src/logging/layer.rs @@ -0,0 +1,65 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use tower::Layer; + +use super::{InstrumentOperation, MakeIdentity}; + +/// A [`Layer`] used to apply [`InstrumentOperation`]. +#[derive(Debug)] +pub struct InstrumentLayer { + operation_name: &'static str, + make_request: RequestMakeFmt, + make_response: ResponseMakeFmt, +} + +impl InstrumentLayer { + /// Constructs a new [`InstrumentLayer`] with no data redacted. + pub fn new(operation_name: &'static str) -> Self { + Self { + operation_name, + make_request: MakeIdentity, + make_response: MakeIdentity, + } + } +} + +impl InstrumentLayer { + /// Configures the request format. + /// + /// The argument is typically [`RequestFmt`](super::sensitivity::RequestFmt). + pub fn request_fmt(self, make_request: R) -> InstrumentLayer { + InstrumentLayer { + operation_name: self.operation_name, + make_request, + make_response: self.make_response, + } + } + + /// Configures the response format. + /// + /// The argument is typically [`ResponseFmt`](super::sensitivity::ResponseFmt). + pub fn response_fmt(self, make_response: R) -> InstrumentLayer { + InstrumentLayer { + operation_name: self.operation_name, + make_request: self.make_request, + make_response, + } + } +} + +impl Layer for InstrumentLayer +where + RequestMakeFmt: Clone, + ResponseMakeFmt: Clone, +{ + type Service = InstrumentOperation; + + fn layer(&self, service: S) -> Self::Service { + InstrumentOperation::new(service, self.operation_name) + .request_fmt(self.make_request.clone()) + .response_fmt(self.make_response.clone()) + } +} diff --git a/rust-runtime/aws-smithy-http-server/src/logging/mod.rs b/rust-runtime/aws-smithy-http-server/src/logging/mod.rs index 646179730d..99f6f94869 100644 --- a/rust-runtime/aws-smithy-http-server/src/logging/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/logging/mod.rs @@ -57,11 +57,15 @@ //! //! [sensitive trait]: https://awslabs.github.io/smithy/1.0/spec/core/documentation-traits.html?highlight=sensitive%20trait#sensitive-trait +mod layer; +mod plugin; pub mod sensitivity; mod service; use std::fmt::{Debug, Display}; +pub use layer::*; +pub use plugin::*; pub use service::*; /// A standard interface for taking some component of the HTTP request/response and transforming it into new struct diff --git a/rust-runtime/aws-smithy-http-server/src/logging/plugin.rs b/rust-runtime/aws-smithy-http-server/src/logging/plugin.rs new file mode 100644 index 0000000000..494964ab3d --- /dev/null +++ b/rust-runtime/aws-smithy-http-server/src/logging/plugin.rs @@ -0,0 +1,47 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use tower::layer::util::Stack; + +use crate::{ + operation::{Operation, OperationShape}, + plugin::{Pluggable, Plugin}, +}; + +use super::{layer::InstrumentLayer, sensitivity::Sensitivity}; + +/// An [`Plugin`] which applies [`InstrumentLayer`] to all operations in the builder. +#[derive(Debug)] +pub struct InstrumentPlugin; + +impl Plugin for InstrumentPlugin +where + Op: OperationShape, + Op: Sensitivity, +{ + type Service = S; + type Layer = Stack>; + + fn map(&self, operation: Operation) -> Operation { + let layer = InstrumentLayer::new(Op::NAME) + .request_fmt(Op::request_fmt()) + .response_fmt(Op::response_fmt()); + operation.layer(layer) + } +} + +/// An extension trait for applying [`InstrumentLayer`] to all operations. +pub trait InstrumentExt: Pluggable { + /// Applies [`InstrumentLayer`] to all operations. See [`InstrumentOperation`](super::InstrumentOperation) for more + /// information. + fn instrument(self) -> Self::Output + where + Self: Sized, + { + self.apply(InstrumentPlugin) + } +} + +impl InstrumentExt for Builder where Builder: Pluggable {} diff --git a/rust-runtime/aws-smithy-http-server/src/logging/sensitivity/mod.rs b/rust-runtime/aws-smithy-http-server/src/logging/sensitivity/mod.rs index ca1485fbe4..fff18b3d5c 100644 --- a/rust-runtime/aws-smithy-http-server/src/logging/sensitivity/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/logging/sensitivity/mod.rs @@ -15,9 +15,27 @@ mod response; mod sensitive; pub mod uri; +use http::{HeaderMap, StatusCode, Uri}; pub use request::*; pub use response::*; pub use sensitive::*; +use super::{MakeDebug, MakeDisplay}; + /// The string placeholder for redacted data. pub const REDACTED: &str = "{redacted}"; + +/// An interface for providing [`MakeDebug`] and [`MakeDisplay`] for [`Request`](http::Request) and +/// [`Response`](http::Response). +pub trait Sensitivity { + /// The [`MakeDebug`] and [`MakeDisplay`] for the request [`HeaderMap`] and [`Uri`]. + type RequestFmt: for<'a> MakeDebug<&'a HeaderMap> + for<'a> MakeDisplay<&'a Uri>; + /// The [`MakeDebug`] and [`MakeDisplay`] for the response [`HeaderMap`] and [`Uri`]. + type ResponseFmt: for<'a> MakeDebug<&'a HeaderMap> + MakeDisplay; + + /// Returns the [`RequestFmt`](Sensitivity::RequestFmt). + fn request_fmt() -> Self::RequestFmt; + + /// Returns the [`ResponseFmt`](Sensitivity::ResponseFmt). + fn response_fmt() -> Self::ResponseFmt; +} From 9ecbda1444a7a8a225ce60d71c1af0d2e44d3078 Mon Sep 17 00:00:00 2001 From: Harry Barber Date: Tue, 20 Sep 2022 17:23:03 +0000 Subject: [PATCH 2/3] Add Sensitivity codegen --- .../generators/ServerOperationGenerator.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt index d638a3976f..62eabeee9b 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt @@ -45,6 +45,10 @@ class ServerOperationGenerator( fun render(writer: RustWriter) { writer.documentShape(operation, model) + val generator = ServerHttpSensitivityGenerator(model, operation, runtimeConfig) + val requestFmt = generator.requestFmt() + val responseFmt = generator.responseFmt() + writer.rustTemplate( """ pub struct $operationName; @@ -56,8 +60,25 @@ class ServerOperationGenerator( type Output = crate::output::${operationName}Output; type Error = #{Error:W}; } + + impl #{SmithyHttpServer}::logging::sensitivity::Sensitivity for $operationName { + type RequestFmt = #{RequestType:W}; + type ResponseFmt = #{ResponseType:W}; + + fn request_fmt() -> Self::RequestFmt { + #{RequestValue:W} + } + + fn response_fmt() -> Self::ResponseFmt { + #{ResponseValue:W} + } + } """, "Error" to operationError(), + "RequestValue" to requestFmt.value, + "RequestType" to requestFmt.type, + "ResponseValue" to responseFmt.value, + "ResponseType" to responseFmt.type, *codegenScope, ) // Adds newline to end of render From 997115169ef8bc8938f3ceca522a5d02c5202566 Mon Sep 17 00:00:00 2001 From: Harry Barber Date: Tue, 20 Sep 2022 18:21:03 +0000 Subject: [PATCH 3/3] Improve documentation --- rust-runtime/aws-smithy-http-server/src/logging/plugin.rs | 6 ++++-- .../aws-smithy-http-server/src/logging/sensitivity/mod.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/logging/plugin.rs b/rust-runtime/aws-smithy-http-server/src/logging/plugin.rs index 494964ab3d..6edbea980d 100644 --- a/rust-runtime/aws-smithy-http-server/src/logging/plugin.rs +++ b/rust-runtime/aws-smithy-http-server/src/logging/plugin.rs @@ -34,8 +34,10 @@ where /// An extension trait for applying [`InstrumentLayer`] to all operations. pub trait InstrumentExt: Pluggable { - /// Applies [`InstrumentLayer`] to all operations. See [`InstrumentOperation`](super::InstrumentOperation) for more - /// information. + /// Applies an [`InstrumentLayer`] to all operations which respects the [@sensitive] trait given on the input and + /// output models. See [`InstrumentOperation`](super::InstrumentOperation) for more information. + /// + /// [@sensitive]: https://awslabs.github.io/smithy/2.0/spec/documentation-traits.html#sensitive-trait fn instrument(self) -> Self::Output where Self: Sized, diff --git a/rust-runtime/aws-smithy-http-server/src/logging/sensitivity/mod.rs b/rust-runtime/aws-smithy-http-server/src/logging/sensitivity/mod.rs index fff18b3d5c..e18652618a 100644 --- a/rust-runtime/aws-smithy-http-server/src/logging/sensitivity/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/logging/sensitivity/mod.rs @@ -30,7 +30,7 @@ pub const REDACTED: &str = "{redacted}"; pub trait Sensitivity { /// The [`MakeDebug`] and [`MakeDisplay`] for the request [`HeaderMap`] and [`Uri`]. type RequestFmt: for<'a> MakeDebug<&'a HeaderMap> + for<'a> MakeDisplay<&'a Uri>; - /// The [`MakeDebug`] and [`MakeDisplay`] for the response [`HeaderMap`] and [`Uri`]. + /// The [`MakeDebug`] and [`MakeDisplay`] for the response [`HeaderMap`] and [`StatusCode`]. type ResponseFmt: for<'a> MakeDebug<&'a HeaderMap> + MakeDisplay; /// Returns the [`RequestFmt`](Sensitivity::RequestFmt).