diff --git a/src/libs/Cargo.lock b/src/libs/Cargo.lock index e5c342a673..a259e5a3e1 100644 --- a/src/libs/Cargo.lock +++ b/src/libs/Cargo.lock @@ -1473,7 +1473,11 @@ dependencies = [ "anyhow", "hyper", "hyperlocal", + "kata-sys-util", "kata-types", + "nix 0.24.2", + "tempfile", + "test-utils", "tokio", ] diff --git a/src/libs/shim-interface/Cargo.toml b/src/libs/shim-interface/Cargo.toml index 360b4a42e4..7157b00c80 100644 --- a/src/libs/shim-interface/Cargo.toml +++ b/src/libs/shim-interface/Cargo.toml @@ -13,7 +13,13 @@ edition = "2018" [dependencies] anyhow = "^1.0" +nix = "0.24.0" tokio = { version = "1.8.0", features = ["rt-multi-thread"] } hyper = { version = "0.14.20", features = ["stream", "server", "http1"] } hyperlocal = "0.8" kata-types = { path = "../kata-types" } +kata-sys-util = {path = "../kata-sys-util" } + +[dev-dependencies] +tempfile = "3.2.0" +test-utils = {path = "../test-utils"} diff --git a/src/libs/shim-interface/src/lib.rs b/src/libs/shim-interface/src/lib.rs index add611d4ac..706734d73e 100644 --- a/src/libs/shim-interface/src/lib.rs +++ b/src/libs/shim-interface/src/lib.rs @@ -1,4 +1,5 @@ // Copyright (c) 2022 Alibaba Cloud +// Copyright (c) 2024 Ant Group // // SPDX-License-Identifier: Apache-2.0 // @@ -15,16 +16,57 @@ //! HTTP request to the server. The server inside shim will multiplex the request //! to its corresponding handler and run certain methods. -use std::path::Path; +use std::fs; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; pub mod shim_mgmt; +use kata_sys_util::validate::verify_id; use kata_types::config::KATA_PATH; pub const SHIM_MGMT_SOCK_NAME: &str = "shim-monitor.sock"; +fn get_uds_with_sid(short_id: &str, path: &str) -> Result { + verify_id(short_id).context("The short id contains invalid characters.")?; + + let kata_run_path = fs::canonicalize(path).context("failed to canonicalize path")?; + + let p = kata_run_path.join(short_id).join(SHIM_MGMT_SOCK_NAME); + if p.exists() { + return Ok(format!("unix://{}", p.display())); + } + + let target_ids: Vec = fs::read_dir(&kata_run_path)? + .filter_map(|e| { + let x = e.ok()?.file_name().to_string_lossy().into_owned(); + x.as_str().starts_with(short_id).then_some(x) + }) + .collect::>(); + + match target_ids.len() { + 0 => Err(anyhow!( + "sandbox with the provided prefix {short_id:?} is not found" + )), + 1 => { + // One element and only one exists. + Ok(format!( + "unix://{}", + kata_run_path + .join(target_ids[0].as_str()) + .join(SHIM_MGMT_SOCK_NAME) + .display() + )) + } + _ => { + // n > 1 return error + Err(anyhow!( + "more than one sandbox exists with the provided prefix {short_id:?}, please provide a unique prefix" + )) + } + } +} + // return sandbox's storage path pub fn sb_storage_path() -> String { String::from(KATA_PATH) @@ -40,28 +82,126 @@ pub fn mgmt_socket_addr(sid: &str) -> Result { )); } - let p = Path::new(&sb_storage_path()) - .join(sid) - .join(SHIM_MGMT_SOCK_NAME); - - if let Some(p) = p.to_str() { - Ok(format!("unix://{}", p)) - } else { - Err(anyhow!("Bad socket path")) - } + get_uds_with_sid(sid, &sb_storage_path()) } #[cfg(test)] mod tests { use super::*; + use std::path; + use tempfile::tempdir; + + use test_utils::skip_if_not_root; + #[test] fn test_mgmt_socket_addr() { - let sid = "414123"; - let addr = mgmt_socket_addr(sid).unwrap(); - assert_eq!(addr, "unix:///run/kata/414123/shim-monitor.sock"); + // this test has to run as root, so has to manually cleanup afterwards + skip_if_not_root!(); + let sid = "katatest"; + let sandbox_test = path::Path::new(KATA_PATH).join("katatest98654sandboxpath1"); + fs::create_dir_all(sandbox_test.as_path()).unwrap(); + let addr = mgmt_socket_addr(sid).unwrap(); + assert_eq!( + addr, + "unix:///run/kata/katatest98654sandboxpath1/shim-monitor.sock" + ); + fs::remove_dir_all(sandbox_test).unwrap(); + } + + #[test] + fn test_mgmt_socket_addr_with_sid_empty() { let sid = ""; - assert!(mgmt_socket_addr(sid).is_err()); + let result = mgmt_socket_addr(sid); + assert!(result.is_err()); + if let Err(err) = result { + let left = format!("{:?}", err.to_string()); + let left_unquoted = &left[1..left.len() - 1]; + let left_unescaped = left_unquoted.replace("\\\"", "\""); + + assert_eq!( + left_unescaped, + format!("Empty sandbox id for acquiring socket address for shim_mgmt") + ) + } + } + + #[test] + fn test_get_uds_with_sid_ok() { + let run_path = tempdir().unwrap(); + let dir1 = run_path.path().join("kata98654sandboxpath1"); + let dir2 = run_path.path().join("aata98654dangboxpath1"); + fs::create_dir_all(dir1.as_path()).unwrap(); + fs::create_dir_all(dir2.as_path()).unwrap(); + + let result = get_uds_with_sid("kata", &run_path.path().display().to_string()); + assert!(result.is_ok()); + assert_eq!( + result.unwrap(), + format!( + "unix://{}", + run_path + .path() + .join("kata98654sandboxpath1") + .join(SHIM_MGMT_SOCK_NAME) + .display() + ) + ) + } + + #[test] + fn test_get_uds_with_sid_with_zero() { + let result = get_uds_with_sid("acdsdfe", KATA_PATH); + assert!(result.is_err()); + if let Err(err) = result { + let left = format!("{:?}", err.to_string()); + let left_unquoted = &left[1..left.len() - 1]; + let left_unescaped = left_unquoted.replace("\\\"", "\""); + + assert_eq!( + left_unescaped, + format!( + "sandbox with the provided prefix {:?} is not found", + "acdsdfe" + ) + ) + } + } + + #[test] + fn test_get_uds_with_sid_with_invalid() { + let result = get_uds_with_sid("^abcdse", KATA_PATH); + assert!(result.is_err()); + if let Err(err) = result { + let left = format!("{:?}", err.to_string()); + let left_unquoted = &left[1..left.len() - 1]; + let left_unescaped = left_unquoted.replace("\\\"", "\""); + assert_eq!( + left_unescaped, + "The short id contains invalid characters.".to_owned() + ); + } + } + + #[test] + fn test_get_uds_with_sid_more_than_one() { + let run_path = tempdir().unwrap(); + + let dir1 = run_path.path().join("kata98654sandboxpath1"); + let dir2 = run_path.path().join("kata98654dangboxpath1"); + let dir3 = run_path.path().join("aata98654dangboxpath1"); + fs::create_dir_all(dir1.as_path()).unwrap(); + fs::create_dir_all(dir2.as_path()).unwrap(); + fs::create_dir_all(dir3.as_path()).unwrap(); + + let result = get_uds_with_sid("kata", &run_path.path().display().to_string()); + assert!(result.is_err()); + if let Err(err) = result { + let left = format!("{:?}", err.to_string()); + let left_unquoted = &left[1..left.len() - 1]; + let left_unescaped = left_unquoted.replace("\\\"", "\""); + assert_eq!(left_unescaped, format!("more than one sandbox exists with the provided prefix {:?}, please provide a unique prefix", "kata")) + } } } diff --git a/src/runtime-rs/Cargo.lock b/src/runtime-rs/Cargo.lock index 6ae9d503cb..360f1e1813 100644 --- a/src/runtime-rs/Cargo.lock +++ b/src/runtime-rs/Cargo.lock @@ -3688,6 +3688,7 @@ dependencies = [ "anyhow", "hyper", "hyperlocal", + "kata-sys-util", "kata-types", "tokio", ]