Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

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());
}