server/scan-worker/tests/the_probe_runs_as_a_job.rs
//! ★ **The worker's probe runs as a job** (HOL-HEIMDALL-06): under Heimdall's runner there is
//! no sandbox of holger's own to probe from outside, so `GET /-/sandbox/probe` sends the worker
//! a `probe` job. The worker answers the way Heimdall wants it: the answer FILE it names in
//! its output (Heimdall gives a job's stdout to /dev/null), beside `probe.json`, what the box
//! looks like from inside; the write past the scratch cap is the job's `fill_mib`.
use std::path::Path;
use server_lib::job_runner::heimdall_core::Verdict;
use server_lib::job_runner::holger_job_runner::wire::{Answer, WireJob, JOB_SCHEMA};
use server_lib::sandbox::{PROBE_FILE, PROBE_PROGRAM};
fn job(base: &Path) {
let w = WireJob {
schema: JOB_SCHEMA.into(),
job_id: "probe-1".into(),
argv: vec![PROBE_PROGRAM.into()],
params: serde_json::json!({ "fill_mib": 1 }),
reads: 0,
answer: Some("answer.json".into()),
};
std::fs::create_dir_all(base.join("i")).unwrap();
std::fs::create_dir_all(base.join("out")).unwrap();
std::fs::write(base.join("job.json"), serde_json::to_vec(&w).unwrap()).unwrap();
}
#[test]
fn the_probe_job_writes_what_the_box_looks_like_from_inside() {
let tmp = tempfile::tempdir().unwrap();
let base = tmp.path().join("job");
job(&base);
let scratch = tmp.path().join("scratch");
std::fs::create_dir(&scratch).unwrap();
let out = std::process::Command::new(env!("CARGO_BIN_EXE_holger-scan-worker"))
.arg(&base)
.env("TMPDIR", &scratch)
.output()
.unwrap();
assert!(out.status.success(), "{out:?}");
assert!(
out.stdout.is_empty(),
"the answer is a file, never stdout: {:?}",
String::from_utf8_lossy(&out.stdout)
);
let answer: Answer =
serde_json::from_slice(&std::fs::read(base.join("out/answer.json")).unwrap()).unwrap();
assert_eq!(answer.verdict, Verdict::Accepted, "{answer:?}");
assert_eq!(answer.outputs, vec![PROBE_FILE.to_string()]);
let v: serde_json::Value =
serde_json::from_slice(&std::fs::read(base.join("out").join(PROBE_FILE)).unwrap()).unwrap();
for k in [
"connect_public",
"resolve",
"write_root",
"write_scratch",
"write_past_scratch_cap",
"uid",
"cap_eff",
"no_new_privs",
"seccomp",
] {
assert!(v.get(k).is_some(), "the probe answers {k}: {v}");
}
assert_eq!(v["write_scratch"], "written", "{v}");
// Here (no sandbox around the test) the one-MiB fill is simply written, and cleaned up.
assert_eq!(v["write_past_scratch_cap"], "written", "{v}");
assert!(!scratch.join("holger-fill").exists());
}