Skip to content

Commit d91d5d2

Browse files
committed
keylimectl: Fix API 3.0 detection on verifier
The /version endpoint was removed. To test if the API version is supported, the applications should try a GET request to the /v3.0/ endpoint instead. Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
1 parent 159c0c1 commit d91d5d2

File tree

1 file changed

+94
-33
lines changed

1 file changed

+94
-33
lines changed

keylimectl/src/client/verifier.rs

Lines changed: 94 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,8 @@ impl VerifierClient {
306306

307307
/// Auto-detect and set the API version
308308
///
309-
/// Attempts to determine the verifier's API version by first trying the `/version` endpoint.
310-
/// If that fails, it tries each supported API version from oldest to newest until one works.
309+
/// Attempts to determine the verifier's API version by testing endpoint availability.
310+
/// For API v3.0+, the /version endpoint was removed, so we test the versioned endpoints directly.
311311
/// This follows the same pattern used in the rust-keylime agent's registrar client.
312312
///
313313
/// # Returns
@@ -317,8 +317,8 @@ impl VerifierClient {
317317
///
318318
/// # Behavior
319319
///
320-
/// 1. First tries `/version` endpoint to get current and supported versions
321-
/// 2. If `/version` fails, tries API versions from newest to oldest
320+
/// 1. For v3.0+: Tests `/v3.0/` endpoint availability directly (/version endpoint was removed)
321+
/// 2. For v2.x: First tries `/version` endpoint, then falls back to endpoint testing
322322
/// 3. On success, caches the detected version for future requests
323323
/// 4. On complete failure, leaves default version unchanged
324324
///
@@ -339,28 +339,39 @@ impl VerifierClient {
339339
pub async fn detect_api_version(
340340
&mut self,
341341
) -> Result<(), KeylimectlError> {
342-
// Try to get version from /version endpoint first
343-
match self.get_verifier_api_version().await {
344-
Ok(version) => {
345-
info!("Detected verifier API version: {version}");
346-
self.api_version = version;
347-
return Ok(());
348-
}
349-
Err(e) => {
350-
debug!("Failed to get version from /version endpoint: {e}");
351-
// Continue with fallback approach
352-
}
353-
}
354-
355-
// Fallback: try each supported version from newest to oldest
342+
// Test each supported version from newest to oldest
356343
for &api_version in SUPPORTED_API_VERSIONS.iter().rev() {
357344
info!("Trying verifier API version {api_version}");
358345

359-
// Test this version by making a simple request (list agents)
360-
if self.test_api_version(api_version).await.is_ok() {
361-
info!("Successfully detected verifier API version: {api_version}");
362-
self.api_version = api_version.to_string();
363-
return Ok(());
346+
// For v3.0+, test the versioned root endpoint directly since /version was removed
347+
if api_version.starts_with("3.") {
348+
if self.test_api_version_v3(api_version).await.is_ok() {
349+
info!("Successfully detected verifier API version: {api_version}");
350+
self.api_version = api_version.to_string();
351+
return Ok(());
352+
}
353+
} else {
354+
// For v2.x, try /version endpoint first for better version info
355+
if api_version.starts_with("2.") {
356+
match self.get_verifier_api_version().await {
357+
Ok(version) => {
358+
info!("Detected verifier API version from /version endpoint: {version}");
359+
self.api_version = version;
360+
return Ok(());
361+
}
362+
Err(e) => {
363+
debug!("Failed to get version from /version endpoint: {e}");
364+
// Fall back to endpoint testing for this version
365+
}
366+
}
367+
}
368+
369+
// Test this version by making a simple request
370+
if self.test_api_version(api_version).await.is_ok() {
371+
info!("Successfully detected verifier API version: {api_version}");
372+
self.api_version = api_version.to_string();
373+
return Ok(());
374+
}
364375
}
365376
}
366377

@@ -410,7 +421,38 @@ impl VerifierClient {
410421
Ok(resp.results.current_version)
411422
}
412423

413-
/// Test if a specific API version works by making a simple request
424+
/// Test if a specific API version v3.0+ works by testing the versioned root endpoint
425+
/// In API v3.0+, the /version endpoint was removed, so we test endpoint availability directly
426+
async fn test_api_version_v3(
427+
&self,
428+
api_version: &str,
429+
) -> Result<(), KeylimectlError> {
430+
let url = format!("{}/v{}/", self.base.base_url, api_version);
431+
432+
debug!("Testing verifier API version {api_version} with root endpoint: {url}");
433+
434+
let response = self
435+
.base
436+
.client
437+
.get_request(Method::GET, &url)
438+
.send()
439+
.await
440+
.with_context(|| {
441+
format!("Failed to test API version {api_version}")
442+
})?;
443+
444+
if response.status().is_success() {
445+
Ok(())
446+
} else {
447+
Err(KeylimectlError::api_error(
448+
response.status().as_u16(),
449+
format!("API version {api_version} not supported"),
450+
None,
451+
))
452+
}
453+
}
454+
455+
/// Test if a specific API version v2.x works by making a simple request
414456
async fn test_api_version(
415457
&self,
416458
api_version: &str,
@@ -1995,16 +2037,35 @@ mod tests {
19952037

19962038
// Should try 3.0 first, then 2.3, then 2.2, then 2.1, then 2.0
19972039
assert_eq!(attempted_versions[0], "3.0");
1998-
assert_eq!(attempted_versions[1], "2.3");
1999-
assert_eq!(attempted_versions[2], "2.2");
2000-
assert_eq!(attempted_versions[3], "2.1");
2001-
assert_eq!(attempted_versions[4], "2.0");
2040+
}
20022041

2003-
// Should try all supported versions
2004-
assert_eq!(
2005-
attempted_versions.len(),
2006-
SUPPORTED_API_VERSIONS.len()
2007-
);
2042+
#[test]
2043+
fn test_v3_endpoint_detection_logic() {
2044+
// Test the logic for detecting v3.0+ vs v2.x behavior
2045+
2046+
// v3.0+ should use root endpoint testing
2047+
let v3_versions = ["3.0", "3.1"];
2048+
for version in v3_versions {
2049+
assert!(version.starts_with("3."));
2050+
}
2051+
2052+
// v2.x should use /version endpoint first
2053+
let v2_versions = ["2.0", "2.1", "2.2", "2.3"];
2054+
for version in v2_versions {
2055+
assert!(version.starts_with("2."));
2056+
}
2057+
}
2058+
2059+
#[test]
2060+
fn test_v3_test_url_format() {
2061+
// Test that v3 test URLs are formatted correctly
2062+
let base_url = "https://localhost:8881";
2063+
let api_version = "3.0";
2064+
let expected_url = format!("{base_url}/v{api_version}/");
2065+
2066+
assert_eq!(expected_url, "https://localhost:8881/v3.0/");
2067+
assert!(expected_url.ends_with("/"));
2068+
assert!(!expected_url.contains("/agents"));
20082069
}
20092070
}
20102071
}

0 commit comments

Comments
 (0)