mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-07-26 07:58:14 +00:00
Merge pull request 'log access keys Garage v2' (#1124) from 1686a/log-access-key-v2 into main-v2
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/1124
This commit is contained in:
@@ -217,6 +217,13 @@ impl ApiHandler for ArcAdminApiServer {
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
self.0.handle_http_api(req, endpoint).await
|
||||
}
|
||||
|
||||
fn key_id_from_request(&self, req: &Request<IncomingBody>) -> Option<String> {
|
||||
let auth_header = req.headers().get(AUTHORIZATION)?;
|
||||
let token = parse_authorization(auth_header).ok()?;
|
||||
let key_id = token.split_once('.')?.0;
|
||||
Some(key_id.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiEndpoint for HttpEndpoint {
|
||||
@@ -244,6 +251,15 @@ fn hash_bearer_token(token: &str) -> String {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn parse_authorization(auth_header: &hyper::http::HeaderValue) -> Result<&str, Error> {
|
||||
let token = auth_header
|
||||
.to_str()?
|
||||
.strip_prefix("Bearer ")
|
||||
.ok_or_else(|| Error::forbidden("Invalid Authorization header"))?
|
||||
.trim();
|
||||
Ok(token)
|
||||
}
|
||||
|
||||
fn verify_authorization(
|
||||
garage: &Garage,
|
||||
global_token_hash: Option<&str>,
|
||||
@@ -260,11 +276,7 @@ fn verify_authorization(
|
||||
"Bearer token must be provided in Authorization header",
|
||||
))
|
||||
}
|
||||
Some(authorization) => authorization
|
||||
.to_str()?
|
||||
.strip_prefix("Bearer ")
|
||||
.ok_or_else(|| Error::forbidden("Invalid Authorization header"))?
|
||||
.trim(),
|
||||
Some(authorization) => parse_authorization(authorization)?,
|
||||
};
|
||||
|
||||
let token_hash_string = if let Some((prefix, _)) = token.split_once('.') {
|
||||
|
||||
@@ -34,6 +34,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) -> Cow<'static, str>;
|
||||
@@ -59,6 +60,12 @@ pub trait ApiHandler: Send + Sync + 'static {
|
||||
req: Request<IncomingBody>,
|
||||
endpoint: Self::Endpoint,
|
||||
) -> impl Future<Output = Result<Response<BoxBody<Self::Error>>, 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<IncomingBody>) -> Option<String> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ApiServer<A: ApiHandler> {
|
||||
@@ -143,19 +150,20 @@ impl<A: ApiHandler> ApiServer<A> {
|
||||
) -> Result<Response<BoxBody<A::Error>>, 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");
|
||||
|
||||
@@ -424,7 +424,7 @@ pub 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,
|
||||
@@ -433,7 +433,7 @@ pub struct Authorization {
|
||||
}
|
||||
|
||||
impl Authorization {
|
||||
fn parse_header(headers: &HeaderMap) -> Result<Self, Error> {
|
||||
pub fn parse_header(headers: &HeaderMap) -> Result<Self, Error> {
|
||||
let authorization = headers
|
||||
.get(AUTHORIZATION)
|
||||
.ok_or_bad_request("Missing authorization header")?
|
||||
|
||||
@@ -171,6 +171,12 @@ impl ApiHandler for K2VApiServer {
|
||||
|
||||
Ok(resp_ok)
|
||||
}
|
||||
|
||||
fn key_id_from_request(&self, req: &Request<IncomingBody>) -> Option<String> {
|
||||
garage_api_common::signature::payload::Authorization::parse_header(req.headers())
|
||||
.map(|auth| auth.key_id)
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiEndpoint for K2VApiEndpoint {
|
||||
|
||||
@@ -340,6 +340,12 @@ impl ApiHandler for S3ApiServer {
|
||||
|
||||
Ok(resp_ok)
|
||||
}
|
||||
|
||||
fn key_id_from_request(&self, req: &Request<IncomingBody>) -> Option<String> {
|
||||
garage_api_common::signature::payload::Authorization::parse_header(req.headers())
|
||||
.map(|auth| auth.key_id)
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiEndpoint for S3ApiEndpoint {
|
||||
|
||||
Reference in New Issue
Block a user