fix(keystone): accept Swift storage tokens (#4390)

fix(keystone): accept swift storage tokens
This commit is contained in:
Zhengchao An
2026-07-08 06:01:40 +08:00
committed by GitHub
parent f021e4f321
commit 45435d83ab
+22 -13
View File
@@ -15,14 +15,14 @@
//! Keystone authentication middleware
//!
//! 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
//! for use by downstream authentication handlers.
//!
//! ## Authentication Flow
//!
//! 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:
//! - Validate with Keystone service
//! - On success: Store credentials in task-local, continue processing
@@ -50,6 +50,9 @@ use tracing::{debug, info, warn};
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
// This allows passing credentials from middleware to auth handlers
// without modifying the request/response types
@@ -140,11 +143,10 @@ where
}
};
// Extract X-Auth-Token header
let token = extract_keystone_token(req.headers());
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
match keystone_auth.authenticate_with_token(token).await {
@@ -191,7 +193,7 @@ where
}
// 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 (parts, body) = resp.into_parts();
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> {
headers.get("X-Auth-Token").and_then(|v| v.to_str().ok())
// TODO: Add X-Storage-Token support in Phase 2 (Swift API)
// .or_else(|| headers.get("X-Storage-Token").and_then(|v| v.to_str().ok()))
headers
.get(HEADER_X_AUTH_TOKEN)
.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
@@ -254,8 +253,18 @@ mod tests {
let mut headers = HeaderMap::new();
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"));
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]