Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
401 changes: 205 additions & 196 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions aws_secretsmanager_agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion aws_secretsmanager_agent/src/cache_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
return Err(HttpError(status, err_response(&code, &msg)));
}
Err(e) => {
error!("Internal error for {secret_id} - {:?}", e);
error!("Internal error for {secret_id} - {e:?}");

Check warning on line 87 in aws_secretsmanager_agent/src/cache_manager.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/cache_manager.rs#L87

Added line #L87 was not covered by tests
return Err(int_err());
}
};
Expand Down
3 changes: 1 addition & 2 deletions aws_secretsmanager_agent/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,7 @@
///
/// # 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

Check warning on line 183 in aws_secretsmanager_agent/src/config.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/config.rs#L183

Added line #L183 was not covered by tests
pub fn log_to_file(&self) -> bool {
self.log_to_file
}
Expand Down
2 changes: 1 addition & 1 deletion aws_secretsmanager_agent/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
5 changes: 1 addition & 4 deletions aws_secretsmanager_agent/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
10 changes: 5 additions & 5 deletions aws_secretsmanager_agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
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 warning on line 105 in aws_secretsmanager_agent/src/main.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/main.rs#L105

Added line #L105 was not covered by tests
}

// Check for end of test in unit tests.
Expand Down Expand Up @@ -169,7 +169,7 @@
// 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, "")
});
Expand Down Expand Up @@ -335,7 +335,7 @@
// 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}");

Check warning on line 338 in aws_secretsmanager_agent/src/main.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/main.rs#L338

Added line #L338 was not covered by tests
}
});

Expand Down Expand Up @@ -400,7 +400,7 @@
// 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:?}");

Check warning on line 403 in aws_secretsmanager_agent/src/main.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/main.rs#L403

Added line #L403 was not covered by tests
}

// Return the responses in the original request order and strip out the index.
Expand Down Expand Up @@ -744,7 +744,7 @@
#[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);
}
Expand Down
39 changes: 15 additions & 24 deletions aws_secretsmanager_agent/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl GSVQuery {

pub(crate) fn try_from_query(s: &str) -> Result<Self, HttpError> {
// 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)?;

Expand All @@ -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}"))),
}
}

Expand All @@ -55,7 +55,7 @@ impl GSVQuery {

pub(crate) fn try_from_path_query(s: &str, path_prefix: &str) -> Result<Self, HttpError> {
// 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)?;

Expand All @@ -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}"))),
}
}

Expand All @@ -92,13 +92,12 @@ 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);
assert_eq!(query.version_stage, None);
assert_eq!(query.refresh_now, false);
assert!(!query.refresh_now);
}

#[test]
Expand All @@ -113,7 +112,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]
Expand All @@ -128,7 +127,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]
Expand All @@ -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) => {
Expand All @@ -160,7 +158,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]
Expand All @@ -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,
)
Expand All @@ -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) => {
Expand All @@ -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,
) {
Expand All @@ -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) => {
Expand All @@ -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"),
Expand Down
66 changes: 44 additions & 22 deletions aws_secretsmanager_agent/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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;

Expand All @@ -27,6 +28,13 @@
max_conn: usize,
}

/// HTTP response relevant fields
#[derive(Debug)]

Check warning on line 32 in aws_secretsmanager_agent/src/server.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/server.rs#L31-L32

Added lines #L31 - L32 were not covered by tests
struct ResponseContent {
rsp_body: String,
content_type: Mime,
}

Check warning on line 37 in aws_secretsmanager_agent/src/server.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/server.rs#L35-L37

Added lines #L35 - L37 were not covered by tests
/// Handle incoming HTTP requests.
///
/// Implements the HTTP handler. Each incomming request is handled in its own
Expand Down Expand Up @@ -80,7 +88,7 @@
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:?}");

Check warning on line 91 in aws_secretsmanager_agent/src/server.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/server.rs#L91

Added line #L91 was not covered by tests
};
});

Expand Down Expand Up @@ -108,11 +116,16 @@

// Format the response.
match result {
Ok(rsp_body) => Ok(Response::builder()
Ok(ResponseContent {

Check warning on line 119 in aws_secretsmanager_agent/src/server.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/server.rs#L119

Added line #L119 was not covered by tests
rsp_body,
content_type,
}) => Ok(Response::builder()
.header("Content-Type", content_type.essence_str())
.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()),
}
Expand All @@ -134,40 +147,49 @@
&self,
req: &Request<IncomingBody>,
count: usize,
) -> Result<String, HttpError> {
) -> Result<ResponseContent, HttpError> {
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: mime::TEXT_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 {

Check warning on line 164 in aws_secretsmanager_agent/src/server.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/server.rs#L164

Added line #L164 was not covered by tests
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: mime::APPLICATION_JSON,
})

Check warning on line 175 in aws_secretsmanager_agent/src/server.rs

View check run for this annotation

Codecov / codecov/patch

aws_secretsmanager_agent/src/server.rs#L175

Added line #L175 was not covered by tests
}

// 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: mime::APPLICATION_JSON,
})
}
_ => Err(HttpError(404, "Not found".into())),
}
Expand Down
Loading
Loading