use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::time::{Duration, UNIX_EPOCH};
use isoloom_manifest::{HostOs, Manifest};
use crate::clock::FixedClock;
use crate::net::FakePorts;
use crate::process::fake::{Call, FakeProcesses, Reply};
use crate::{HostPorts, ProcessRunner, RunnerConfig};
pub(crate) const FLAG_PORTAL: &str = include_str!("../tests/fixtures/flag-portal.run.json");
pub(crate) const SOLO_WEB_PROXMOX: &str = include_str!("../tests/fixtures/solo-web.proxmox.run.json");
pub(crate) const SOLO_WEB_AWS: &str = include_str!("../tests/fixtures/solo-web.cloud-vm-aws.run.json");
pub(crate) const FLAG_VM: &str = include_str!("../tests/fixtures/flag-vm.run.json");
pub(crate) const DOCKER_VM: &str = include_str!("../tests/fixtures/flag-portal.docker-vm.run.json");
pub(crate) const DOCKER_VM_PROXMOX: &str = include_str!("../tests/fixtures/flag-portal.docker-vm-proxmox.run.json");
pub(crate) const TEST_TIME: u64 = 1_792_065_600;
pub(crate) fn proxmox_manifest() -> Manifest {
isoloom_manifest::parse(SOLO_WEB_PROXMOX).unwrap()
}
pub(crate) fn docker_manifest() -> Manifest {
isoloom_manifest::parse(FLAG_PORTAL).unwrap()
}
pub(crate) fn vagrant_manifest() -> Manifest {
isoloom_manifest::parse(FLAG_VM).unwrap()
}
pub(crate) struct LabFolder {
pub(crate) home: tempfile::TempDir,
_lab: tempfile::TempDir,
pub(crate) manifest: PathBuf,
}
impl LabFolder {
pub(crate) fn new(target: &str, manifest: &str) -> LabFolder {
let (home, lab) = (tempfile::tempdir().unwrap(), tempfile::tempdir().unwrap());
let dir = lab.path().join(".isoloom").join(target);
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(dir.join("run.json"), manifest).unwrap();
LabFolder {
manifest: dir.join("run.json"),
home,
_lab: lab,
}
}
pub(crate) fn target_dir(&self) -> &Path {
self.manifest.parent().unwrap()
}
}
pub(crate) fn modelled<E: Default + Send + 'static>(answer: fn(&Mutex<E>, &Call) -> Reply) -> (Arc<Mutex<E>>, Arc<FakeProcesses>) {
let engine = Arc::new(Mutex::new(E::default()));
let fake = Arc::new(FakeProcesses::new({
let engine = Arc::clone(&engine);
move |call| answer(&engine, call)
}));
(engine, fake)
}
pub(crate) fn processes(fake: &Arc<FakeProcesses>) -> Arc<dyn ProcessRunner> {
Arc::<FakeProcesses>::clone(fake)
}
pub(crate) fn runner_config(home: &Path, processes: Arc<dyn ProcessRunner>, ports: Arc<dyn HostPorts>, host: HostOs) -> RunnerConfig {
RunnerConfig {
home: home.to_path_buf(),
processes,
ports,
clock: Arc::new(FixedClock(UNIX_EPOCH + Duration::from_secs(TEST_TIME))),
host,
path: None,
}
}
pub(crate) fn keygen(home: &Path) -> Reply {
let key = crate::ssh::key_path(home);
std::fs::write(&key, "private").unwrap();
std::fs::write(key.with_extension("pub"), "ssh-ed25519 AAAAfake isothrum\n").unwrap();
Reply::ok("")
}
pub(crate) fn no_ports() -> Arc<dyn HostPorts> {
Arc::new(FakePorts::new([]))
}
pub(crate) fn virtualbox_options(flag: &str) -> crate::RunOptions {
let mut secrets = crate::secrets::Secrets::new();
secrets.insert("CTF_FLAG_MAIN", crate::secrets::SecretValue::new(flag));
crate::RunOptions::new().with_provider("virtualbox").with_secrets(secrets)
}