From 61a7c1634c4921f7655a292378307aefc41c3869 Mon Sep 17 00:00:00 2001 From: Kazuki Massaki Date: Wed, 4 Dec 2024 08:37:03 +0900 Subject: [PATCH 1/5] add test process_capabilities_fail Signed-off-by: Kazuki Massaki Signed-off-by: kazuki.massaki --- tests/contest/contest/src/main.rs | 3 + tests/contest/contest/src/tests/mod.rs | 1 + .../tests/process_capabilities_fail/mod.rs | 2 + .../process_capabilities_fail_test.rs | 56 +++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 tests/contest/contest/src/tests/process_capabilities_fail/mod.rs create mode 100644 tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs diff --git a/tests/contest/contest/src/main.rs b/tests/contest/contest/src/main.rs index bb1019ca8..3a1a7a1d8 100644 --- a/tests/contest/contest/src/main.rs +++ b/tests/contest/contest/src/main.rs @@ -22,6 +22,7 @@ use crate::tests::mounts_recursive::get_mounts_recursive_test; use crate::tests::no_pivot::get_no_pivot_test; use crate::tests::pidfile::get_pidfile_test; use crate::tests::process::get_process_test; +use crate::tests::process_capabilities_fail::get_process_capabilities_fail_test; use crate::tests::process_oom_score_adj::get_process_oom_score_adj_test; use crate::tests::process_rlimits::get_process_rlimits_test; use crate::tests::process_user::get_process_user_test; @@ -125,6 +126,7 @@ fn main() -> Result<()> { let process_rlimtis = get_process_rlimits_test(); let no_pivot = get_no_pivot_test(); let process_oom_score_adj = get_process_oom_score_adj_test(); + let process_capabilities_fail = get_process_capabilities_fail_test(); tm.add_test_group(Box::new(cl)); tm.add_test_group(Box::new(cc)); @@ -154,6 +156,7 @@ fn main() -> Result<()> { tm.add_test_group(Box::new(process_rlimtis)); tm.add_test_group(Box::new(no_pivot)); tm.add_test_group(Box::new(process_oom_score_adj)); + tm.add_test_group(Box::new(process_capabilities_fail)); tm.add_test_group(Box::new(io_priority_test)); tm.add_cleanup(Box::new(cgroups::cleanup_v1)); diff --git a/tests/contest/contest/src/tests/mod.rs b/tests/contest/contest/src/tests/mod.rs index 6e8e39be8..d7ae631fe 100644 --- a/tests/contest/contest/src/tests/mod.rs +++ b/tests/contest/contest/src/tests/mod.rs @@ -12,6 +12,7 @@ pub mod mounts_recursive; pub mod no_pivot; pub mod pidfile; pub mod process; +pub mod process_capabilities_fail; pub mod process_oom_score_adj; pub mod process_rlimits; pub mod process_user; diff --git a/tests/contest/contest/src/tests/process_capabilities_fail/mod.rs b/tests/contest/contest/src/tests/process_capabilities_fail/mod.rs new file mode 100644 index 000000000..37bf429b5 --- /dev/null +++ b/tests/contest/contest/src/tests/process_capabilities_fail/mod.rs @@ -0,0 +1,2 @@ +mod process_capabilities_fail_test; +pub use process_capabilities_fail_test::get_process_capabilities_fail_test; diff --git a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs new file mode 100644 index 000000000..9062f0c9e --- /dev/null +++ b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs @@ -0,0 +1,56 @@ +use anyhow::{anyhow, Context, Ok, Result}; +use oci_spec::runtime::{Capability, LinuxCapabilitiesBuilder, ProcessBuilder, Spec, SpecBuilder}; +use std::collections::HashSet; +use std::str::FromStr; +use test_framework::{test_result, Test, TestGroup, TestResult}; + +use crate::utils::test_inside_container; +use crate::utils::test_utils::CreateOptions; + +fn create_spec() -> Result { + let cap_test = Capability::from_str("CAP_TEST").context("invalid capability: CAP_TEST")?; + + let linux_capability = LinuxCapabilitiesBuilder::default() + .bounding(HashSet::from([cap_test])) + // .bounding(HashSet::from([Capability::from_str("CAP_TEST")])) + .build()?; + + let process = ProcessBuilder::default() + .args(vec![ + "runtimetest".to_string(), + "process_capabilities_fail".to_string(), + ]) + .capabilities(linux_capability) + .build() + .expect("error in creating process config"); + + let spec = SpecBuilder::default() + .process(process) + .build() + .context("failed to build spec")?; + + Ok(spec) +} + +fn process_capabilities_fail_test() -> TestResult { + let spec = test_result!(create_spec()); + + let result = test_inside_container(spec, &CreateOptions::default(), &|_| Ok(())); + + match result { + TestResult::Failed(_) => TestResult::Passed, + TestResult::Passed => TestResult::Failed(anyhow!("test unexpectedly passed.")), + _ => TestResult::Failed(anyhow!("test result was unexpected.")), + } +} + +pub fn get_process_capabilities_fail_test() -> TestGroup { + let mut process_capabilities_fail_test_group = TestGroup::new("process_capabilities_fail"); + let test = Test::new( + "process_capabilities_fail_test", + Box::new(process_capabilities_fail_test), + ); + process_capabilities_fail_test_group.add(vec![Box::new(test)]); + + process_capabilities_fail_test_group +} From 8372fa992346853bea6d17ee51a16f777e821bf3 Mon Sep 17 00:00:00 2001 From: Kazuki Massaki Date: Wed, 4 Dec 2024 14:21:54 +0900 Subject: [PATCH 2/5] change the expected value to the capability generation error Signed-off-by: Kazuki Massaki Signed-off-by: kazuki.massaki --- .../process_capabilities_fail_test.rs | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs index 9062f0c9e..9f8d288d0 100644 --- a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs +++ b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs @@ -1,18 +1,14 @@ -use anyhow::{anyhow, Context, Ok, Result}; +use anyhow::{Context, Error, Ok, Result}; use oci_spec::runtime::{Capability, LinuxCapabilitiesBuilder, ProcessBuilder, Spec, SpecBuilder}; use std::collections::HashSet; use std::str::FromStr; -use test_framework::{test_result, Test, TestGroup, TestResult}; - -use crate::utils::test_inside_container; -use crate::utils::test_utils::CreateOptions; +use test_framework::{Test, TestGroup, TestResult}; fn create_spec() -> Result { - let cap_test = Capability::from_str("CAP_TEST").context("invalid capability: CAP_TEST")?; + let capability = Capability::from_str("CAP_TEST").context("invalid capability")?; let linux_capability = LinuxCapabilitiesBuilder::default() - .bounding(HashSet::from([cap_test])) - // .bounding(HashSet::from([Capability::from_str("CAP_TEST")])) + .bounding(HashSet::from([capability])) .build()?; let process = ProcessBuilder::default() @@ -33,14 +29,9 @@ fn create_spec() -> Result { } fn process_capabilities_fail_test() -> TestResult { - let spec = test_result!(create_spec()); - - let result = test_inside_container(spec, &CreateOptions::default(), &|_| Ok(())); - - match result { - TestResult::Failed(_) => TestResult::Passed, - TestResult::Passed => TestResult::Failed(anyhow!("test unexpectedly passed.")), - _ => TestResult::Failed(anyhow!("test result was unexpected.")), + match create_spec() { + Result::Ok(_) => TestResult::Failed(Error::msg("create_spec succeeded unexpectedly.")), + Err(_e) => TestResult::Passed, } } From 841a6851ba76393ff22cc8cb96fc9eb80e566b37 Mon Sep 17 00:00:00 2001 From: Kazuki Massaki Date: Wed, 4 Dec 2024 14:28:51 +0900 Subject: [PATCH 3/5] add error message verification Signed-off-by: Kazuki Massaki Signed-off-by: kazuki.massaki --- .../process_capabilities_fail_test.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs index 9f8d288d0..89864aa99 100644 --- a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs +++ b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs @@ -31,7 +31,13 @@ fn create_spec() -> Result { fn process_capabilities_fail_test() -> TestResult { match create_spec() { Result::Ok(_) => TestResult::Failed(Error::msg("create_spec succeeded unexpectedly.")), - Err(_e) => TestResult::Passed, + Err(e) => { + if e.to_string() == "invalid capability" { + TestResult::Passed + } else { + TestResult::Failed(Error::msg(format!("unexpected error: {}", e))) + } + } } } From 098586efef41153c3fd8c4b0662ade673e66c032 Mon Sep 17 00:00:00 2001 From: "kazuki.massaki" Date: Mon, 9 Dec 2024 09:14:38 +0900 Subject: [PATCH 4/5] fix formmat error Signed-off-by: kazuki.massaki --- .../process_capabilities_fail_test.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs index 89864aa99..9866a1c1b 100644 --- a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs +++ b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs @@ -1,7 +1,8 @@ -use anyhow::{Context, Error, Ok, Result}; -use oci_spec::runtime::{Capability, LinuxCapabilitiesBuilder, ProcessBuilder, Spec, SpecBuilder}; use std::collections::HashSet; use std::str::FromStr; + +use anyhow::{Context, Error, Ok, Result}; +use oci_spec::runtime::{Capability, LinuxCapabilitiesBuilder, ProcessBuilder, Spec, SpecBuilder}; use test_framework::{Test, TestGroup, TestResult}; fn create_spec() -> Result { From 2b72e7407538358e8435f31b20276a55a89f2eb3 Mon Sep 17 00:00:00 2001 From: "kazuki.massaki" Date: Thu, 26 Dec 2024 11:50:51 +0900 Subject: [PATCH 5/5] handling capability modification in the callback function Signed-off-by: kazuki.massaki --- .../process_capabilities_fail_test.rs | 53 ++++++++++++++----- tests/contest/contest/src/utils/test_utils.rs | 5 +- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs index 9866a1c1b..c4eac8386 100644 --- a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs +++ b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs @@ -1,15 +1,16 @@ -use std::collections::HashSet; -use std::str::FromStr; +use std::{collections::HashSet, fs, fs::OpenOptions, io::Write}; -use anyhow::{Context, Error, Ok, Result}; +use anyhow::{anyhow, Context, Ok, Result}; use oci_spec::runtime::{Capability, LinuxCapabilitiesBuilder, ProcessBuilder, Spec, SpecBuilder}; -use test_framework::{Test, TestGroup, TestResult}; +use test_framework::{test_result, Test, TestGroup, TestResult}; -fn create_spec() -> Result { - let capability = Capability::from_str("CAP_TEST").context("invalid capability")?; +use serde_json::Value; + +use crate::utils::{test_inside_container, test_utils::CreateOptions}; +fn create_spec() -> Result { let linux_capability = LinuxCapabilitiesBuilder::default() - .bounding(HashSet::from([capability])) + .bounding(HashSet::from([Capability::Syslog])) .build()?; let process = ProcessBuilder::default() @@ -30,15 +31,39 @@ fn create_spec() -> Result { } fn process_capabilities_fail_test() -> TestResult { - match create_spec() { - Result::Ok(_) => TestResult::Failed(Error::msg("create_spec succeeded unexpectedly.")), - Err(e) => { - if e.to_string() == "invalid capability" { - TestResult::Passed - } else { - TestResult::Failed(Error::msg(format!("unexpected error: {}", e))) + let spec = test_result!(create_spec()); + let result = test_inside_container(spec, &CreateOptions::default(), &|bundle| { + let spec_path = bundle.join("../config.json"); + let spec_str = fs::read_to_string(spec_path.clone()).unwrap(); + + let mut spec_json: Value = serde_json::from_str(&spec_str)?; + + if let Some(bounding) = spec_json.pointer_mut("/process/capabilities/bounding") { + if let Some(bounding_array) = bounding.as_array_mut() { + for capanility in bounding_array.iter_mut() { + if capanility == "CAP_SYSLOG" { + *capanility = Value::String("TEST_CAP".to_string()); + } + } } } + + let updated_spec_str = serde_json::to_string_pretty(&spec_json)?; + + let mut file = OpenOptions::new() + .write(true) + .truncate(true) + .open(spec_path)?; + file.write_all(updated_spec_str.as_bytes())?; + + Ok(()) + }); + match result { + TestResult::Failed(_e) => TestResult::Passed, + TestResult::Skipped => TestResult::Failed(anyhow!("test was skipped unexpectedly.")), + TestResult::Passed => { + TestResult::Failed(anyhow!("container creation succeeded unexpectedly.")) + } } } diff --git a/tests/contest/contest/src/utils/test_utils.rs b/tests/contest/contest/src/utils/test_utils.rs index 0964a9a04..4a980c2cf 100644 --- a/tests/contest/contest/src/utils/test_utils.rs +++ b/tests/contest/contest/src/utils/test_utils.rs @@ -201,7 +201,10 @@ pub fn test_inside_container( .join("runtimetest"), ) .unwrap(); - let create_process = create_container(&id_str, &bundle, options).unwrap(); + let create_process = match create_container(&id_str, &bundle, options) { + Ok(p) => p, + Err(e) => return TestResult::Failed(anyhow!("container create failed : {:?}", e)), + }; // here we do not wait for the process by calling wait() as in the test_outside_container // function because we need the output of the runtimetest. If we call wait, it will return // and we won't have an easy way of getting the stdio of the runtimetest.