mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-02 18:28:11 +00:00
fix(keystone): accept Swift storage tokens (#4390)
fix(keystone): accept swift storage tokens
This commit is contained in:
@@ -15,14 +15,14 @@
|
|||||||
//! Keystone authentication middleware
|
//! Keystone authentication middleware
|
||||||
//!
|
//!
|
||||||
//! This middleware intercepts HTTP requests and checks for OpenStack Keystone
|
//! This middleware intercepts HTTP requests and checks for OpenStack Keystone
|
||||||
//! authentication headers (X-Auth-Token). If found, it validates the token
|
//! authentication headers (X-Auth-Token or Swift X-Storage-Token). If found, it validates the token
|
||||||
//! with Keystone and stores the authenticated credentials in task-local storage
|
//! with Keystone and stores the authenticated credentials in task-local storage
|
||||||
//! for use by downstream authentication handlers.
|
//! for use by downstream authentication handlers.
|
||||||
//!
|
//!
|
||||||
//! ## Authentication Flow
|
//! ## Authentication Flow
|
||||||
//!
|
//!
|
||||||
//! 1. Check if Keystone is enabled (via global provider)
|
//! 1. Check if Keystone is enabled (via global provider)
|
||||||
//! 2. Extract X-Auth-Token header from request
|
//! 2. Extract X-Auth-Token or X-Storage-Token header from request
|
||||||
//! 3. If token present:
|
//! 3. If token present:
|
||||||
//! - Validate with Keystone service
|
//! - Validate with Keystone service
|
||||||
//! - On success: Store credentials in task-local, continue processing
|
//! - On success: Store credentials in task-local, continue processing
|
||||||
@@ -50,6 +50,9 @@ use tracing::{debug, info, warn};
|
|||||||
|
|
||||||
use crate::KeystoneAuthProvider;
|
use crate::KeystoneAuthProvider;
|
||||||
|
|
||||||
|
const HEADER_X_AUTH_TOKEN: &str = "X-Auth-Token";
|
||||||
|
const HEADER_X_STORAGE_TOKEN: &str = "X-Storage-Token";
|
||||||
|
|
||||||
// Task-local storage for Keystone credentials
|
// Task-local storage for Keystone credentials
|
||||||
// This allows passing credentials from middleware to auth handlers
|
// This allows passing credentials from middleware to auth handlers
|
||||||
// without modifying the request/response types
|
// without modifying the request/response types
|
||||||
@@ -140,11 +143,10 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract X-Auth-Token header
|
|
||||||
let token = extract_keystone_token(req.headers());
|
let token = extract_keystone_token(req.headers());
|
||||||
|
|
||||||
if let Some(token) = token {
|
if let Some(token) = token {
|
||||||
debug!("Keystone middleware: Found X-Auth-Token header, validating");
|
debug!("Keystone middleware: Found Keystone token header, validating");
|
||||||
|
|
||||||
// Validate token with Keystone
|
// Validate token with Keystone
|
||||||
match keystone_auth.authenticate_with_token(token).await {
|
match keystone_auth.authenticate_with_token(token).await {
|
||||||
@@ -191,7 +193,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No Keystone token header present, pass through to normal S3 authentication
|
// No Keystone token header present, pass through to normal S3 authentication
|
||||||
debug!("Keystone middleware: No X-Auth-Token header, passing through to S3 auth");
|
debug!("Keystone middleware: No Keystone token header, passing through to S3 auth");
|
||||||
let resp = inner.call(req).await?;
|
let resp = inner.call(req).await?;
|
||||||
let (parts, body) = resp.into_parts();
|
let (parts, body) = resp.into_parts();
|
||||||
let body: BoxBody = body.map_err(Into::into).boxed_unsync();
|
let body: BoxBody = body.map_err(Into::into).boxed_unsync();
|
||||||
@@ -200,14 +202,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract Keystone token from request headers
|
|
||||||
///
|
|
||||||
/// Checks for X-Auth-Token header (Keystone v3 standard).
|
|
||||||
/// Note: X-Storage-Token (Swift) support deferred to future PR per Q4.C
|
|
||||||
fn extract_keystone_token(headers: &HeaderMap) -> Option<&str> {
|
fn extract_keystone_token(headers: &HeaderMap) -> Option<&str> {
|
||||||
headers.get("X-Auth-Token").and_then(|v| v.to_str().ok())
|
headers
|
||||||
// TODO: Add X-Storage-Token support in Phase 2 (Swift API)
|
.get(HEADER_X_AUTH_TOKEN)
|
||||||
// .or_else(|| headers.get("X-Storage-Token").and_then(|v| v.to_str().ok()))
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.or_else(|| headers.get(HEADER_X_STORAGE_TOKEN).and_then(|v| v.to_str().ok()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Escape XML special characters to prevent injection
|
/// Escape XML special characters to prevent injection
|
||||||
@@ -254,8 +253,18 @@ mod tests {
|
|||||||
let mut headers = HeaderMap::new();
|
let mut headers = HeaderMap::new();
|
||||||
assert!(extract_keystone_token(&headers).is_none());
|
assert!(extract_keystone_token(&headers).is_none());
|
||||||
|
|
||||||
headers.insert("X-Auth-Token", "test-token-123".parse().unwrap());
|
headers.insert(HEADER_X_AUTH_TOKEN, "test-token-123".parse().expect("auth token header should parse"));
|
||||||
assert_eq!(extract_keystone_token(&headers), Some("test-token-123"));
|
assert_eq!(extract_keystone_token(&headers), Some("test-token-123"));
|
||||||
|
|
||||||
|
headers.clear();
|
||||||
|
headers.insert(
|
||||||
|
HEADER_X_STORAGE_TOKEN,
|
||||||
|
"swift-token-456".parse().expect("storage token header should parse"),
|
||||||
|
);
|
||||||
|
assert_eq!(extract_keystone_token(&headers), Some("swift-token-456"));
|
||||||
|
|
||||||
|
headers.insert(HEADER_X_AUTH_TOKEN, "auth-token-789".parse().expect("auth token header should parse"));
|
||||||
|
assert_eq!(extract_keystone_token(&headers), Some("auth-token-789"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|||||||
Reference in New Issue
Block a user