From f2de4e884fe0f40bd72464382b893a1dca19c608 Mon Sep 17 00:00:00 2001 From: Simon Marty Date: Thu, 20 Mar 2025 13:22:37 -0700 Subject: [PATCH 1/6] Provide a prefer-post-quantum crate feature --- Cargo.lock | 6 ++++-- README.md | 11 +++++++++++ aws_secretsmanager_agent/Cargo.toml | 7 +++++-- aws_secretsmanager_caching/Cargo.toml | 6 +++++- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b0b798..cd59519 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -544,7 +544,7 @@ dependencies = [ [[package]] name = "aws_secretsmanager_agent" -version = "1.0.1" +version = "1.1.0" dependencies = [ "aws-config", "aws-sdk-secretsmanager", @@ -571,7 +571,7 @@ dependencies = [ [[package]] name = "aws_secretsmanager_caching" -version = "1.0.1" +version = "1.1.0" dependencies = [ "aws-config", "aws-sdk-secretsmanager", @@ -581,6 +581,7 @@ dependencies = [ "aws-smithy-types", "http 0.2.12", "linked-hash-map", + "rustls 0.23.25", "serde", "serde_json", "serde_with", @@ -2338,6 +2339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" dependencies = [ "aws-lc-rs", + "log", "once_cell", "rustls-pki-types", "rustls-webpki 0.103.0", diff --git a/README.md b/README.md index e9e0c9b..5263c6e 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,13 @@ To download the source code, see [https://github\.com/aws/aws\-secretsmanager\-a - [Step 3: Retrieve secrets with the Secrets Manager Agent](#step-3-retrieve-secrets-with-the-secrets-manager-agent) - [\[ curl \]](#-curl-) - [\[ Python \]](#-python-) + - [`refreshNow` parameter behavior](#refreshnow-parameter-behavior) + - [Using the refreshNow parameter](#using-the-refreshnow-parameter) + - [Example - Secrets Manager Agent GET request with refreshNow parameter](#example---secrets-manager-agent-get-request-with-refreshnow-parameter) + - [\[ curl \]](#-curl--1) + - [\[ Python \]](#-python--1) - [Configure the Secrets Manager Agent](#configure-the-secrets-manager-agent) + - [Optional features](#optional-features) - [Logging](#logging) - [Security considerations](#security-considerations) @@ -451,6 +457,11 @@ The following list shows the options you can configure for the Secrets Manager A + **path\_prefix** – The URI prefix used to determine if the request is a path based request\. The default is "/v1/"\. + **max\_conn** – The maximum number of connections from HTTP clients that the Secrets Manager Agent allows, in the range 1 to 1000\. The default is 800\. +## Optional features + +The Secrets Manager Agent can be built with optional features by passing the `--features` flag to `cargo build`. The available features are: +* `prefer-post-quantum`: makes `X25519MLKEM768` the highest-priority key exchange algorithm. Otherwise, it is available but not highest-priority. `X25519MLKEM768` is a hybrid, post-quantum-secure key exchange algorithm. + ## Logging The Secrets Manager Agent logs errors locally to the file `logs/secrets_manager_agent.log`\. When your application calls the Secrets Manager Agent to get a secret, those calls appear in the local log\. They do not appear in the CloudTrail logs\. diff --git a/aws_secretsmanager_agent/Cargo.toml b/aws_secretsmanager_agent/Cargo.toml index 3cd0864..0b39796 100644 --- a/aws_secretsmanager_agent/Cargo.toml +++ b/aws_secretsmanager_agent/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws_secretsmanager_agent" -version = "1.0.1" +version = "1.1.0" edition = "2021" license = "Apache-2.0" description = "The AWS Secrets Manager Agent is a local HTTP service that you can install and use in your compute environments to read secrets from Secrets Manager and cache them in memory." @@ -28,7 +28,7 @@ aws-sdk-sts = "1" log = "0.4.20" log4rs = { version = "1.2.0", features = ["gzip"] } url = "2" -aws_secretsmanager_caching = { version = "1.0.1", path = "../aws_secretsmanager_caching" } +aws_secretsmanager_caching = { version = "1.1.0", path = "../aws_secretsmanager_caching" } # For unit tests [dev-dependencies] @@ -37,3 +37,6 @@ aws-smithy-runtime = { version = "1", features = ["test-util"] } tokio = {version = "1", features = ["test-util", "rt-multi-thread", "net", "macros"] } http = "0.2.9" aws-smithy-types = "1" + +[features] +prefer-post-quantum = ["aws_secretsmanager_caching/prefer-post-quantum"] diff --git a/aws_secretsmanager_caching/Cargo.toml b/aws_secretsmanager_caching/Cargo.toml index ff40675..4b85cd4 100644 --- a/aws_secretsmanager_caching/Cargo.toml +++ b/aws_secretsmanager_caching/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws_secretsmanager_caching" -version = "1.0.1" +version = "1.1.0" edition = "2021" license = "Apache-2.0" description = "The AWS Secrets Manager Rust caching client enables in-process caching of secrets for Rust applications." @@ -19,6 +19,7 @@ thiserror = "2" tokio = { version = "1", features = ["rt", "sync"] } linked-hash-map = "0.5.6" aws-config = "1" +rustls = "*" [dev-dependencies] aws-smithy-mocks-experimental = "0" @@ -27,3 +28,6 @@ aws-sdk-secretsmanager = { version = "1", features = ["test-util"] } tokio = { version = "1", features = ["macros", "rt", "sync", "test-util"] } http = "0" tokio-test = "0.4.4" + +[features] +prefer-post-quantum = ["rustls/prefer-post-quantum"] From 458a33b88ed2626edfb11d62b48b95449875683e Mon Sep 17 00:00:00 2001 From: Simon Marty Date: Tue, 25 Mar 2025 13:42:15 -0700 Subject: [PATCH 2/6] Add Content-Type header --- aws_secretsmanager_agent/src/constants.rs | 2 +- aws_secretsmanager_agent/src/server.rs | 76 ++++++++++++++++------- aws_secretsmanager_caching/src/lib.rs | 12 ++-- 3 files changed, 62 insertions(+), 28 deletions(-) diff --git a/aws_secretsmanager_agent/src/constants.rs b/aws_secretsmanager_agent/src/constants.rs index 9d4edde..6862ed4 100644 --- a/aws_secretsmanager_agent/src/constants.rs +++ b/aws_secretsmanager_agent/src/constants.rs @@ -13,7 +13,7 @@ pub const EMPTY_ENV_LIST_MSG: &str = pub const BAD_PREFIX_MSG: &str = "The path prefix specified in the configuration file must begin with /."; -/// Other constants that are used across the code base. +// Other constants that are used across the code base. // The application name. pub const APPNAME: &str = "aws-secrets-manager-agent"; diff --git a/aws_secretsmanager_agent/src/server.rs b/aws_secretsmanager_agent/src/server.rs index 5c1826c..78d598a 100644 --- a/aws_secretsmanager_agent/src/server.rs +++ b/aws_secretsmanager_agent/src/server.rs @@ -27,6 +27,20 @@ pub struct Server { max_conn: usize, } +/// HTTP response relevant fields +#[derive(Debug)] +struct ResponseContent { + rsp_body: String, + content_type: ContentType, +} + +/// Used to set Content-Type header +#[derive(Debug)] +enum ContentType { + Plain, + Json, +} + /// Handle incoming HTTP requests. /// /// Implements the HTTP handler. Each incomming request is handled in its own @@ -108,11 +122,22 @@ impl Server { // Format the response. match result { - Ok(rsp_body) => Ok(Response::builder() + Ok(ResponseContent { + rsp_body, + content_type, + }) => Ok(Response::builder() + .header( + "Content-Type", + match content_type { + ContentType::Plain => "text/plain", + ContentType::Json => "application/json", + }, + ) .body(Full::new(Bytes::from(rsp_body))) .unwrap()), Err(e) => Ok(Response::builder() .status(e.0) + .header("Content-Type", "text/plain") .body(Full::new(Bytes::from(e.1))) .unwrap()), } @@ -134,40 +159,49 @@ impl Server { &self, req: &Request, count: usize, - ) -> Result { + ) -> Result { self.validate_max_conn(req, count)?; // Verify connection limits are not exceeded self.validate_token(req)?; // Check for a valid SSRF token self.validate_method(req)?; // Allow only GET requests match req.uri().path() { - "/ping" => Ok("healthy".into()), // Standard health check + "/ping" => Ok(ResponseContent { + rsp_body: "healthy".into(), + content_type: ContentType::Plain, + }), // Standard health check // Lambda extension style query "/secretsmanager/get" => { let qry = GSVQuery::try_from_query(&req.uri().to_string())?; - Ok(self - .cache_mgr - .fetch( - &qry.secret_id, - qry.version_id.as_deref(), - qry.version_stage.as_deref(), - qry.refresh_now, - ) - .await?) + Ok(ResponseContent { + rsp_body: self + .cache_mgr + .fetch( + &qry.secret_id, + qry.version_id.as_deref(), + qry.version_stage.as_deref(), + qry.refresh_now, + ) + .await?, + content_type: ContentType::Json, + }) } // Path style request path if path.starts_with(self.path_prefix.as_str()) => { let qry = GSVQuery::try_from_path_query(&req.uri().to_string(), &self.path_prefix)?; - Ok(self - .cache_mgr - .fetch( - &qry.secret_id, - qry.version_id.as_deref(), - qry.version_stage.as_deref(), - qry.refresh_now, - ) - .await?) + Ok(ResponseContent { + rsp_body: self + .cache_mgr + .fetch( + &qry.secret_id, + qry.version_id.as_deref(), + qry.version_stage.as_deref(), + qry.refresh_now, + ) + .await?, + content_type: ContentType::Json, + }) } _ => Err(HttpError(404, "Not found".into())), } diff --git a/aws_secretsmanager_caching/src/lib.rs b/aws_secretsmanager_caching/src/lib.rs index 49c27ac..e2cff6f 100644 --- a/aws_secretsmanager_caching/src/lib.rs +++ b/aws_secretsmanager_caching/src/lib.rs @@ -51,7 +51,7 @@ impl SecretsManagerCachingClient { /// use aws_secretsmanager_caching::SecretsManagerCachingClient; /// use std::num::NonZeroUsize; /// use std::time::Duration; - + /// /// let asm_client = SecretsManagerClient::from_conf( /// Config::builder() /// .behavior_version_latest() @@ -118,15 +118,15 @@ impl SecretsManagerCachingClient { /// use std::num::NonZeroUsize; /// use std::time::Duration; /// use aws_config::{BehaviorVersion, Region}; - + /// /// let config = aws_config::load_defaults(BehaviorVersion::latest()) /// .await /// .into_builder() /// .region(Region::from_static("us-west-2")) /// .build(); - + /// /// let asm_builder = aws_sdk_secretsmanager::config::Builder::from(&config); - + /// /// let client = SecretsManagerCachingClient::from_builder( /// asm_builder, /// NonZeroUsize::new(1000).unwrap(), @@ -164,9 +164,9 @@ impl SecretsManagerCachingClient { refresh_now: bool, ) -> Result> { if refresh_now { - return Ok(self + return self .refresh_secret_value(secret_id, version_id, version_stage, None) - .await?); + .await; } let read_lock = self.store.read().await; From f90bc2e56d3c89adb1ad66aa53065ffbc11b1103 Mon Sep 17 00:00:00 2001 From: Simon Marty Date: Tue, 25 Mar 2025 13:45:36 -0700 Subject: [PATCH 3/6] Cargo update --- Cargo.lock | 59 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd59519..9787861 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -720,9 +720,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", @@ -955,9 +955,9 @@ checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" [[package]] name = "deranged" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" dependencies = [ "powerfmt", "serde", @@ -1471,14 +1471,15 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -1773,9 +1774,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" dependencies = [ "serde", ] @@ -2010,9 +2011,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" dependencies = [ "memchr", "thiserror 2.0.12", @@ -2021,9 +2022,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" +checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" dependencies = [ "pest", "pest_generator", @@ -2031,9 +2032,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" +checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" dependencies = [ "pest", "pest_meta", @@ -2044,9 +2045,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" dependencies = [ "once_cell", "pest", @@ -2077,7 +2078,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] @@ -2342,7 +2343,7 @@ dependencies = [ "log", "once_cell", "rustls-pki-types", - "rustls-webpki 0.103.0", + "rustls-webpki 0.103.1", "subtle", "zeroize", ] @@ -2398,9 +2399,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.0" +version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ "aws-lc-rs", "ring", @@ -2770,9 +2771,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d9c75b47bdff86fa3334a3db91356b8d7d86a9b839dab7d0bdc5c3d3a077618" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -2791,9 +2792,9 @@ checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29aa485584182073ed57fd5004aa09c371f021325014694e432313345865fd04" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -3453,11 +3454,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "zerocopy-derive 0.8.23", + "zerocopy-derive 0.8.24", ] [[package]] @@ -3473,9 +3474,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", From 1e7b1ac8890826e19ebdd6884cfcb837766acc84 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 14 Jun 2025 14:48:45 -0700 Subject: [PATCH 4/6] Formatting & Clippy --- Cargo.lock | 2 +- aws_secretsmanager_agent/src/config.rs | 3 +-- aws_secretsmanager_agent/src/main.rs | 2 +- aws_secretsmanager_agent/src/parse.rs | 8 ++++---- aws_secretsmanager_caching/src/lib.rs | 8 ++++---- .../src/secret_store/memory_store/mod.rs | 1 - 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0eb832f..c3693aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" diff --git a/aws_secretsmanager_agent/src/config.rs b/aws_secretsmanager_agent/src/config.rs index 8b7878d..870f2ee 100644 --- a/aws_secretsmanager_agent/src/config.rs +++ b/aws_secretsmanager_agent/src/config.rs @@ -180,8 +180,7 @@ impl Config { /// /// # Returns /// - /// * `log_to_file` - `true` if writing logs to a file (default), `false` if writing logs to - /// stdout/stderr + /// * `log_to_file` - `true` if writing logs to a file (default), `false` if writing logs to stdout/stderr pub fn log_to_file(&self) -> bool { self.log_to_file } diff --git a/aws_secretsmanager_agent/src/main.rs b/aws_secretsmanager_agent/src/main.rs index 61d94a3..e0f8ac4 100644 --- a/aws_secretsmanager_agent/src/main.rs +++ b/aws_secretsmanager_agent/src/main.rs @@ -744,7 +744,7 @@ mod tests { #[tokio::test] async fn path_refresh_success() { let req = "/v1/My/Test?versionStage=AWSPENDING&refreshNow=0"; - let (status, body) = run_request(&req).await; + let (status, body) = run_request(req).await; assert_eq!(status, StatusCode::OK); validate_response_extra("My/Test", DEFAULT_VERSION, vec!["AWSPENDING"], body); } diff --git a/aws_secretsmanager_agent/src/parse.rs b/aws_secretsmanager_agent/src/parse.rs index baf8fdf..3add241 100644 --- a/aws_secretsmanager_agent/src/parse.rs +++ b/aws_secretsmanager_agent/src/parse.rs @@ -98,7 +98,7 @@ mod tests { assert_eq!(query.secret_id, secret_id); assert_eq!(query.version_id, None); assert_eq!(query.version_stage, None); - assert_eq!(query.refresh_now, false); + assert!(!query.refresh_now); } #[test] @@ -113,7 +113,7 @@ mod tests { assert_eq!(query.secret_id, secret_id); assert_eq!(query.version_id, None); assert_eq!(query.version_stage, None); - assert_eq!(query.refresh_now, true); + assert!(query.refresh_now); } #[test] @@ -128,7 +128,7 @@ mod tests { assert_eq!(query.secret_id, secret_id); assert_eq!(query.version_id, None); assert_eq!(query.version_stage, None); - assert_eq!(query.refresh_now, false); + assert!(!query.refresh_now); } #[test] @@ -160,7 +160,7 @@ mod tests { assert_eq!(query.secret_id, secret_id); assert_eq!(query.version_id, None); assert_eq!(query.version_stage, None); - assert_eq!(query.refresh_now, false); + assert!(!query.refresh_now); } #[test] diff --git a/aws_secretsmanager_caching/src/lib.rs b/aws_secretsmanager_caching/src/lib.rs index 160d982..53d9680 100644 --- a/aws_secretsmanager_caching/src/lib.rs +++ b/aws_secretsmanager_caching/src/lib.rs @@ -206,9 +206,9 @@ impl SecretsManagerCachingClient { ); } - return Ok(self + return self .refresh_secret_value(secret_id, version_id, version_stage, None) - .await); + .await; } let read_lock = self.store.read().await; @@ -424,12 +424,12 @@ impl SecretsManagerCachingClient { } #[cfg(debug_assertions)] - fn increment_counter(&self, counter: &AtomicU32) -> () { + fn increment_counter(&self, counter: &AtomicU32) { counter.fetch_add(1, Ordering::SeqCst); } #[cfg(debug_assertions)] - fn reset_counter(&self, counter: &AtomicU32) -> () { + fn reset_counter(&self, counter: &AtomicU32) { counter.store(0, Ordering::SeqCst); } diff --git a/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs b/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs index 4f2e182..a926ca3 100644 --- a/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs +++ b/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs @@ -97,7 +97,6 @@ impl SecretStore for MemoryStore { } /// Write the secret value to the store - #[cfg(test)] mod tests { From 55301c531ae26ca358cd59404e3bf06c2cfc4309 Mon Sep 17 00:00:00 2001 From: Simon Marty Date: Mon, 7 Jul 2025 16:32:50 -0700 Subject: [PATCH 5/6] cargo clippy --fix --- aws_secretsmanager_agent/src/cache_manager.rs | 2 +- aws_secretsmanager_agent/src/logging.rs | 5 +-- aws_secretsmanager_agent/src/main.rs | 8 ++--- aws_secretsmanager_agent/src/parse.rs | 31 +++++++------------ aws_secretsmanager_agent/src/server.rs | 2 +- .../src/secret_store/memory_store/mod.rs | 6 ++-- 6 files changed, 21 insertions(+), 33 deletions(-) diff --git a/aws_secretsmanager_agent/src/cache_manager.rs b/aws_secretsmanager_agent/src/cache_manager.rs index 9e5c425..6640a95 100644 --- a/aws_secretsmanager_agent/src/cache_manager.rs +++ b/aws_secretsmanager_agent/src/cache_manager.rs @@ -84,7 +84,7 @@ impl CacheManager { return Err(HttpError(status, err_response(&code, &msg))); } Err(e) => { - error!("Internal error for {secret_id} - {:?}", e); + error!("Internal error for {secret_id} - {e:?}"); return Err(int_err()); } }; diff --git a/aws_secretsmanager_agent/src/logging.rs b/aws_secretsmanager_agent/src/logging.rs index 3c40218..c105746 100644 --- a/aws_secretsmanager_agent/src/logging.rs +++ b/aws_secretsmanager_agent/src/logging.rs @@ -104,10 +104,7 @@ pub fn init_logger( return Err(Box::new(err)); } - info!( - "{} logger initialized with `{:?}` log level.", - logger_type, log_level - ); + info!("{logger_type} logger initialized with `{log_level:?}` log level."); Ok(()) } diff --git a/aws_secretsmanager_agent/src/main.rs b/aws_secretsmanager_agent/src/main.rs index e0f8ac4..c6deeb0 100644 --- a/aws_secretsmanager_agent/src/main.rs +++ b/aws_secretsmanager_agent/src/main.rs @@ -102,7 +102,7 @@ async fn run bool>( loop { // Report errors on accept. if let Err(msg) = svr.serve_request().await { - error!("Could not accept connection: {:?}", msg); + error!("Could not accept connection: {msg:?}"); } // Check for end of test in unit tests. @@ -169,7 +169,7 @@ async fn init(args: impl IntoIterator) -> (Config, TcpListener) { // Bind the listener to the specified port let addr: SocketAddr = ([127, 0, 0, 1], config.http_port()).into(); let listener: TcpListener = TcpListener::bind(addr).await.unwrap_or_else(|err| { - let msg = format!("Could not bind to {addr}: {}", err); + let msg = format!("Could not bind to {addr}: {err}"); error!("{msg}"); err_exit(&msg, "") }); @@ -335,7 +335,7 @@ mod tests { // spawn a task to poll the connection and drive the HTTP state tokio::spawn(async move { if let Err(e) = conn.await { - panic!("Error in connection: {}", e); + panic!("Error in connection: {e}"); } }); @@ -400,7 +400,7 @@ mod tests { // Make sure everything shutdown cleanly. tx_lock.send(true).expect("could not sync"); // Tell the server to shut down. if let Err(msg) = thr.join() { - panic!("server failed: {:?}", msg); + panic!("server failed: {msg:?}"); } // Return the responses in the original request order and strip out the index. diff --git a/aws_secretsmanager_agent/src/parse.rs b/aws_secretsmanager_agent/src/parse.rs index 3add241..b63b717 100644 --- a/aws_secretsmanager_agent/src/parse.rs +++ b/aws_secretsmanager_agent/src/parse.rs @@ -25,7 +25,7 @@ impl GSVQuery { pub(crate) fn try_from_query(s: &str) -> Result { // url library can only parse complete URIs. The host/port/scheme used is irrelevant since it is not used - let complete_uri = format!("http://localhost{}", s); + let complete_uri = format!("http://localhost{s}"); let url = Url::parse(&complete_uri)?; @@ -42,7 +42,7 @@ impl GSVQuery { "versionId" => query.version_id = Some(v.into()), "versionStage" => query.version_stage = Some(v.into()), "refreshNow" => query.refresh_now = GSVQuery::parse_refresh_value(&v)?, - p => return Err(HttpError(400, format!("unknown parameter: {}", p))), + p => return Err(HttpError(400, format!("unknown parameter: {p}"))), } } @@ -55,7 +55,7 @@ impl GSVQuery { pub(crate) fn try_from_path_query(s: &str, path_prefix: &str) -> Result { // url library can only parse complete URIs. The host/port/scheme used is irrelevant since it gets stripped - let complete_uri = format!("http://localhost{}", s); + let complete_uri = format!("http://localhost{s}"); let url = Url::parse(&complete_uri)?; @@ -76,7 +76,7 @@ impl GSVQuery { "versionId" => query.version_id = Some(v.into()), "versionStage" => query.version_stage = Some(v.into()), "refreshNow" => query.refresh_now = GSVQuery::parse_refresh_value(&v)?, - p => return Err(HttpError(400, format!("unknown parameter: {}", p))), + p => return Err(HttpError(400, format!("unknown parameter: {p}"))), } } @@ -92,8 +92,7 @@ mod tests { fn parse_query() { let secret_id = "MyTest".to_owned(); let query = - GSVQuery::try_from_query(&format!("/secretsmanager/get?secretId={}", secret_id)) - .unwrap(); + GSVQuery::try_from_query(&format!("/secretsmanager/get?secretId={secret_id}")).unwrap(); assert_eq!(query.secret_id, secret_id); assert_eq!(query.version_id, None); @@ -137,8 +136,7 @@ mod tests { let version_id = "myversion".to_owned(); let version_stage = "dev".to_owned(); match GSVQuery::try_from_query(&format!( - "/secretsmanager/get?secretId={}&versionId={}&versionStage={}&refreshNow=123", - secret_id, version_id, version_stage + "/secretsmanager/get?secretId={secret_id}&versionId={version_id}&versionStage={version_stage}&refreshNow=123" )) { Ok(_) => panic!("should not parse"), Err(e) => { @@ -172,8 +170,7 @@ mod tests { let query = GSVQuery::try_from_path_query( &format!( - "{}{}?versionId={}&versionStage={}", - path_prefix, secret_id, version_id, version_stage + "{path_prefix}{secret_id}?versionId={version_id}&versionStage={version_stage}" ), path_prefix, ) @@ -190,8 +187,7 @@ mod tests { let version_id = "myversion".to_owned(); let version_stage = "dev".to_owned(); match GSVQuery::try_from_query(&format!( - "/secretsmanager/get?secretId={}&versionId={}&versionStage={}&abc=123", - secret_id, version_id, version_stage + "/secretsmanager/get?secretId={secret_id}&versionId={version_id}&versionStage={version_stage}&abc=123" )) { Ok(_) => panic!("should not parse"), Err(e) => { @@ -210,8 +206,7 @@ mod tests { match GSVQuery::try_from_path_query( &format!( - "{}{}?versionId={}&versionStage={}&abc=123", - path_prefix, secret_id, version_id, version_stage + "{path_prefix}{secret_id}?versionId={version_id}&versionStage={version_stage}&abc=123" ), path_prefix, ) { @@ -228,8 +223,7 @@ mod tests { let version_id = "myversion".to_owned(); let version_stage = "dev".to_owned(); match GSVQuery::try_from_query(&format!( - "/secretsmanager/get?&versionId={}&versionStage={}", - version_id, version_stage + "/secretsmanager/get?&versionId={version_id}&versionStage={version_stage}" )) { Ok(_) => panic!("should not parse"), Err(e) => { @@ -246,10 +240,7 @@ mod tests { let path_prefix = "/v1/"; match GSVQuery::try_from_path_query( - &format!( - "{}?versionId={}&versionStage={}&abc=123", - path_prefix, version_id, version_stage - ), + &format!("{path_prefix}?versionId={version_id}&versionStage={version_stage}&abc=123"), path_prefix, ) { Ok(_) => panic!("should not parse"), diff --git a/aws_secretsmanager_agent/src/server.rs b/aws_secretsmanager_agent/src/server.rs index 78d598a..e3fd26f 100644 --- a/aws_secretsmanager_agent/src/server.rs +++ b/aws_secretsmanager_agent/src/server.rs @@ -94,7 +94,7 @@ impl Server { let mut http = http1::Builder::new(); let http = http.max_buf_size(MAX_BUF_BYTES); if let Err(err) = timeout(time_out(), http.serve_connection(io, svc_fn)).await { - error!("Failed to serve connection: {:?}", err); + error!("Failed to serve connection: {err:?}"); }; }); diff --git a/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs b/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs index a926ca3..3f74868 100644 --- a/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs +++ b/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs @@ -115,11 +115,11 @@ mod tests { fn get_secret_value_output(suffix: Option<&str>) -> GetSecretValueOutputDef { GetSecretValueOutputDef { name: match suffix { - Some(suffix) => Some(format!("{}{}", NAME, suffix)), + Some(suffix) => Some(format!("{NAME}{suffix}")), None => Some(NAME.to_string()), }, arn: match suffix { - Some(suffix) => Some(format!("{}{}", ARN, suffix)), + Some(suffix) => Some(format!("{ARN}{suffix}")), None => Some(ARN.to_string()), }, version_id: Some(VERSION_ID.to_string()), @@ -137,7 +137,7 @@ mod tests { stage: Option, ) { let name = match suffix { - Some(suffix) => format!("{}{}", NAME, suffix), + Some(suffix) => format!("{NAME}{suffix}"), None => NAME.to_string(), }; From e836a37e34b83ea3ff8cff9e3da38d195cd543e7 Mon Sep 17 00:00:00 2001 From: Simon Marty Date: Mon, 7 Jul 2025 16:52:34 -0700 Subject: [PATCH 6/6] Use mime crate --- Cargo.lock | 7 +++++++ aws_secretsmanager_agent/Cargo.toml | 1 + aws_secretsmanager_agent/src/server.rs | 24 ++++++------------------ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3693aa..5196cb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -581,6 +581,7 @@ dependencies = [ "hyper-util", "log", "log4rs", + "mime", "pretty_env_logger", "serde", "serde_derive", @@ -1828,6 +1829,12 @@ version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" diff --git a/aws_secretsmanager_agent/Cargo.toml b/aws_secretsmanager_agent/Cargo.toml index 07f9063..2b1259c 100644 --- a/aws_secretsmanager_agent/Cargo.toml +++ b/aws_secretsmanager_agent/Cargo.toml @@ -29,6 +29,7 @@ log = "0.4.20" log4rs = { version = "1.2.0", features = ["gzip"] } url = "2" aws_secretsmanager_caching = { version = "2.0.0", path = "../aws_secretsmanager_caching" } +mime = "0.3.17" # For unit tests [dev-dependencies] diff --git a/aws_secretsmanager_agent/src/server.rs b/aws_secretsmanager_agent/src/server.rs index e3fd26f..0c281cc 100644 --- a/aws_secretsmanager_agent/src/server.rs +++ b/aws_secretsmanager_agent/src/server.rs @@ -5,6 +5,7 @@ use hyper::service::service_fn; use hyper::{body::Incoming as IncomingBody, Method, Request, Response}; use hyper_util::rt::TokioIo; use log::error; +use mime::Mime; use tokio::net::TcpListener; use tokio::time::timeout; @@ -31,14 +32,7 @@ pub struct Server { #[derive(Debug)] struct ResponseContent { rsp_body: String, - content_type: ContentType, -} - -/// Used to set Content-Type header -#[derive(Debug)] -enum ContentType { - Plain, - Json, + content_type: Mime, } /// Handle incoming HTTP requests. @@ -126,13 +120,7 @@ impl Server { rsp_body, content_type, }) => Ok(Response::builder() - .header( - "Content-Type", - match content_type { - ContentType::Plain => "text/plain", - ContentType::Json => "application/json", - }, - ) + .header("Content-Type", content_type.essence_str()) .body(Full::new(Bytes::from(rsp_body))) .unwrap()), Err(e) => Ok(Response::builder() @@ -167,7 +155,7 @@ impl Server { match req.uri().path() { "/ping" => Ok(ResponseContent { rsp_body: "healthy".into(), - content_type: ContentType::Plain, + content_type: mime::TEXT_PLAIN, }), // Standard health check // Lambda extension style query @@ -183,7 +171,7 @@ impl Server { qry.refresh_now, ) .await?, - content_type: ContentType::Json, + content_type: mime::APPLICATION_JSON, }) } @@ -200,7 +188,7 @@ impl Server { qry.refresh_now, ) .await?, - content_type: ContentType::Json, + content_type: mime::APPLICATION_JSON, }) } _ => Err(HttpError(404, "Not found".into())),