Skip to content

Commit

Permalink
Add e2e test for process user (#2978)
Browse files Browse the repository at this point in the history
* add-test-process-user

Signed-off-by: sat0ken <[email protected]>

* fix format

Signed-off-by: sat0ken <[email protected]>

* fix error

Signed-off-by: sat0ken <[email protected]>

* fix err and format

Signed-off-by: sat0ken <[email protected]>

* fix err to use UserBuilder

Signed-off-by: sat0ken <[email protected]>

* fix format err

Signed-off-by: sat0ken <[email protected]>

* remove unnecessary return

Signed-off-by: sat0ken <[email protected]>

* rename module name

Signed-off-by: sat0ken <[email protected]>

* fix unsafe code to use nix

Signed-off-by: sat0ken <[email protected]>

* fix err to use nix

Signed-off-by: sat0ken <[email protected]>

* fix format err

Signed-off-by: sat0ken <[email protected]>

* update fn validate_additional_gids to check group ids length

Signed-off-by: sat0ken <[email protected]>

* set additional_gids to random number

Signed-off-by: sat0ken <[email protected]>

* set umask value to variables

Signed-off-by: sat0ken <[email protected]>

* fix format err

Signed-off-by: sat0ken <[email protected]>

* change random number range

Signed-off-by: sat0ken <[email protected]>

* change err msg to use bail

Signed-off-by: sat0ken <[email protected]>

* nit: update error message in case of test failure

Signed-off-by: Yashodhan Joshi <[email protected]>

* fix: make sure random gid values are unique

Signed-off-by: Yashodhan Joshi <[email protected]>

---------

Signed-off-by: sat0ken <[email protected]>
Signed-off-by: Yashodhan Joshi <[email protected]>
Co-authored-by: Yashodhan Joshi <[email protected]>
  • Loading branch information
sat0ken and YJDoc2 authored Nov 14, 2024
1 parent 87befd9 commit d5d5fad
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 1 deletion.
3 changes: 3 additions & 0 deletions tests/contest/contest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_rlimits::get_process_rlimits_test;
use crate::tests::process_user::get_process_user_test;
use crate::tests::readonly_paths::get_ro_paths_test;
use crate::tests::scheduler::get_scheduler_test;
use crate::tests::seccomp::get_seccomp_test;
Expand Down Expand Up @@ -115,6 +116,7 @@ fn main() -> Result<()> {
let scheduler = get_scheduler_test();
let io_priority_test = get_io_priority_test();
let devices = get_devices_test();
let process_user = get_process_user_test();
let process_rlimtis = get_process_rlimits_test();
let no_pivot = get_no_pivot_test();

Expand All @@ -140,6 +142,7 @@ fn main() -> Result<()> {
tm.add_test_group(Box::new(sysctl));
tm.add_test_group(Box::new(scheduler));
tm.add_test_group(Box::new(devices));
tm.add_test_group(Box::new(process_user));
tm.add_test_group(Box::new(process_rlimtis));
tm.add_test_group(Box::new(no_pivot));

Expand Down
1 change: 1 addition & 0 deletions tests/contest/contest/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod mounts_recursive;
pub mod no_pivot;
pub mod pidfile;
pub mod process_rlimits;
pub mod process_user;
pub mod readonly_paths;
pub mod scheduler;
pub mod seccomp;
Expand Down
2 changes: 2 additions & 0 deletions tests/contest/contest/src/tests/process_user/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod process_user_test;
pub use process_user_test::get_process_user_test;
56 changes: 56 additions & 0 deletions tests/contest/contest/src/tests/process_user/process_user_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use anyhow::{Context, Ok, Result};
use oci_spec::runtime::{ProcessBuilder, Spec, SpecBuilder, UserBuilder};
use rand::Rng;
use test_framework::{test_result, Test, TestGroup, TestResult};

use crate::utils::test_inside_container;

// Generates a Vec<u32> with a random number of elements (between 5 and 15),
// where each element is a random u32 value between 0 and 65535.
fn generate_unique_random_vec() -> Vec<u32> {
let mut rng = rand::thread_rng();
let vec_size = rng.gen_range(5..=10);
let mut ret = Vec::new();
while ret.len() < vec_size {
let rand = rng.gen_range(100..=200);
if !ret.contains(&rand) {
ret.push(rand);
}
}
ret
}

fn create_spec() -> Result<Spec> {
let umask = 0o002;
let user = UserBuilder::default()
.uid(10u32)
.gid(10u32)
.additional_gids(generate_unique_random_vec())
.umask(umask as u32)
.build()?;

let spec = SpecBuilder::default()
.process(
ProcessBuilder::default()
.args(vec!["runtimetest".to_string(), "process_user".to_string()])
.user(user)
.build()
.expect("error in creating process config"),
)
.build()
.context("failed to build spec")?;
Ok(spec)
}
fn process_user_test() -> TestResult {
let spec = test_result!(create_spec());
test_inside_container(spec, &|_| Ok(()))
}

pub fn get_process_user_test() -> TestGroup {
let mut process_user_test_group = TestGroup::new("process_user");

let test = Test::new("process_user_test", Box::new(process_user_test));
process_user_test_group.add(vec![Box::new(test)]);

process_user_test_group
}
1 change: 1 addition & 0 deletions tests/contest/runtimetest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ fn main() {
"io_priority_class_be" => tests::test_io_priority_class(&spec, IoprioClassBe),
"io_priority_class_idle" => tests::test_io_priority_class(&spec, IoprioClassIdle),
"devices" => tests::validate_devices(&spec),
"process_user" => tests::validate_process_user(&spec),
"process_rlimits" => tests::validate_process_rlimits(&spec),
"no_pivot" => tests::validate_rootfs(),
_ => eprintln!("error due to unexpected execute test name: {execute_test}"),
Expand Down
62 changes: 61 additions & 1 deletion tests/contest/runtimetest/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use anyhow::{bail, Result};
use nix::errno::Errno;
use nix::libc;
use nix::sys::resource::{getrlimit, Resource};
use nix::sys::stat::{umask, Mode};
use nix::sys::utsname;
use nix::unistd::getcwd;
use nix::unistd::{getcwd, getgid, getgroups, getuid, Gid, Uid};
use oci_spec::runtime::IOPriorityClass::{self, IoprioClassBe, IoprioClassIdle, IoprioClassRt};
use oci_spec::runtime::{
LinuxDevice, LinuxDeviceType, LinuxSchedulerPolicy, PosixRlimit, PosixRlimitType, Spec,
Expand Down Expand Up @@ -549,6 +550,65 @@ pub fn test_io_priority_class(spec: &Spec, io_priority_class: IOPriorityClass) {
}
}

pub fn validate_process_user(spec: &Spec) {
let process = spec.process().as_ref().unwrap();
let expected_uid = Uid::from(process.user().uid());
let expected_gid = Gid::from(process.user().gid());
let expected_umask = Mode::from_bits(process.user().umask().unwrap()).unwrap();

let uid = getuid();
let gid = getgid();
// The umask function not only gets the current mask, but also has the ability to set a new mask,
// so we need to set it back after getting the latest value.
let current_umask = umask(nix::sys::stat::Mode::empty());
umask(current_umask);

if expected_uid != uid {
eprintln!("error due to uid want {}, got {}", expected_uid, uid)
}

if expected_gid != gid {
eprintln!("error due to gid want {}, got {}", expected_gid, gid)
}

if let Err(e) = validate_additional_gids(process.user().additional_gids().as_ref().unwrap()) {
eprintln!("error additional gids {e}");
}

if expected_umask != current_umask {
eprintln!(
"error due to umask want {:?}, got {:?}",
expected_umask, current_umask
)
}
}

// validate_additional_gids function is used to validate additional groups of user
fn validate_additional_gids(expected_gids: &Vec<u32>) -> Result<()> {
let current_gids = getgroups().unwrap();

if expected_gids.len() != current_gids.len() {
bail!(
"error : additional group mismatch, want {:?}, got {:?}",
expected_gids,
current_gids
);
}

for gid in expected_gids {
if !current_gids.contains(&Gid::from_raw(*gid)) {
bail!(
"error : additional gid {} is not in current groups, expected {:?}, got {:?}",
gid,
expected_gids,
current_gids
);
}
}

Ok(())
}

pub fn validate_process_rlimits(spec: &Spec) {
let process = spec.process().as_ref().unwrap();
let spec_rlimits: &Vec<PosixRlimit> = process.rlimits().as_ref().unwrap();
Expand Down

0 comments on commit d5d5fad

Please sign in to comment.