diff --git a/src/api/common/generic_server.rs b/src/api/common/generic_server.rs index 8f9bcdfb..5783c276 100644 --- a/src/api/common/generic_server.rs +++ b/src/api/common/generic_server.rs @@ -33,6 +33,7 @@ use garage_util::metrics::{gen_trace_id, RecordDuration}; use garage_util::socket_address::UnixOrTCPSocketAddress; use crate::helpers::{BoxBody, ErrorBody}; +use crate::signature::payload::Authorization; pub trait ApiEndpoint: Send + Sync + 'static { fn name(&self) -> &'static str; @@ -58,6 +59,12 @@ pub trait ApiHandler: Send + Sync + 'static { req: Request, endpoint: Self::Endpoint, ) -> impl Future>, Self::Error>> + Send; + + /// Returns the key id used to authenticate this request. The ID returned must be safe to + /// log. + fn key_id_from_request(&self, req: &Request) -> Option { + None + } } pub struct ApiServer { @@ -142,19 +149,20 @@ impl ApiServer { ) -> Result>, http::Error> { let uri = req.uri().clone(); - if let Ok(forwarded_for_ip_addr) = + let source = if let Ok(forwarded_for_ip_addr) = forwarded_headers::handle_forwarded_for_headers(req.headers()) { - info!( - "{} (via {}) {} {}", - forwarded_for_ip_addr, - addr, - req.method(), - uri - ); + format!("{forwarded_for_ip_addr} (via {addr})") } else { - info!("{} {} {}", addr, req.method(), uri); - } + format!("{addr}") + }; + // we only do this to log the access key, so we can discard any error + let key = self + .api_handler + .key_id_from_request(&req) + .map(|k| format!("(key {k}) ")) + .unwrap_or_default(); + info!("{source} {key}{} {uri}", req.method()); debug!("{:?}", req); let tracer = opentelemetry::global::tracer("garage"); diff --git a/src/api/common/signature/payload.rs b/src/api/common/signature/payload.rs index 2d5f8603..c3a7f231 100644 --- a/src/api/common/signature/payload.rs +++ b/src/api/common/signature/payload.rs @@ -417,7 +417,7 @@ pub async fn verify_v4( // ============ Authorization header, or X-Amz-* query params ========= pub struct Authorization { - key_id: String, + pub key_id: String, scope: String, signed_headers: String, signature: String, @@ -426,7 +426,7 @@ pub struct Authorization { } impl Authorization { - fn parse_header(headers: &HeaderMap) -> Result { + pub fn parse_header(headers: &HeaderMap) -> Result { let authorization = headers .get(AUTHORIZATION) .ok_or_bad_request("Missing authorization header")? diff --git a/src/api/k2v/api_server.rs b/src/api/k2v/api_server.rs index de5775da..8e10d9a6 100644 --- a/src/api/k2v/api_server.rs +++ b/src/api/k2v/api_server.rs @@ -176,6 +176,12 @@ impl ApiHandler for K2VApiServer { Ok(resp_ok) } + + fn key_id_from_request(&self, req: &Request) -> Option { + garage_api_common::signature::payload::Authorization::parse_header(req.headers()) + .map(|auth| auth.key_id) + .ok() + } } impl ApiEndpoint for K2VApiEndpoint { diff --git a/src/api/s3/api_server.rs b/src/api/s3/api_server.rs index 337ddb23..acb0cf56 100644 --- a/src/api/s3/api_server.rs +++ b/src/api/s3/api_server.rs @@ -343,6 +343,12 @@ impl ApiHandler for S3ApiServer { Ok(resp_ok) } + + fn key_id_from_request(&self, req: &Request) -> Option { + garage_api_common::signature::payload::Authorization::parse_header(req.headers()) + .map(|auth| auth.key_id) + .ok() + } } impl ApiEndpoint for S3ApiEndpoint {