lazaret/crates/lazaret-state-anchor/tests/authority.rs

109 lines
3.5 KiB
Rust
Raw Normal View History

use std::collections::BTreeMap;
use std::ffi::OsString;
use std::fs;
use std::os::unix::ffi::OsStringExt;
use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};
use lazaret_core::configuration::{
ConfigurationLoadRequest, SandboxLayoutV1, load_trusted_configuration,
};
use lazaret_state_anchor::{ProtectedRuntimeFiles, StateAnchorLayout};
static SEQUENCE: AtomicU64 = AtomicU64::new(0);
#[test]
fn replaced_runtime_root_is_refused_before_runtime_file_write() {
let tree = TestTree::new();
let configuration = configuration(&tree);
let layout = StateAnchorLayout::create(&configuration).unwrap();
let runtime_root = PathBuf::from(OsString::from_vec(
configuration
.runtime_domain_root()
.canonical_label()
.as_bytes()
.to_vec(),
));
let moved_root = runtime_root.with_extension("retained");
fs::rename(&runtime_root, &moved_root).unwrap();
let replacement_files = runtime_root.join("state-anchor/runtime-files");
fs::create_dir_all(&replacement_files).unwrap();
fs::write(replacement_files.join("hostname"), b"replacement\n").unwrap();
assert!(layout.revalidate().is_err());
assert!(
layout
.replace_protected_runtime_files(&ProtectedRuntimeFiles {
resolv_conf: b"nameserver 192.0.2.1\n",
hosts: b"127.0.0.1 localhost\n",
hostname: b"changed\n",
})
.is_err()
);
assert_eq!(
fs::read(replacement_files.join("hostname")).unwrap(),
b"replacement\n"
);
assert!(!replacement_files.join("resolv.conf").exists());
assert!(!replacement_files.join("hosts").exists());
}
struct TestTree {
path: PathBuf,
}
impl TestTree {
fn new() -> Self {
let path = std::env::temp_dir().join(format!(
"lazaret-state-anchor-authority-{}-{}",
std::process::id(),
SEQUENCE.fetch_add(1, Ordering::Relaxed)
));
fs::create_dir(&path).unwrap();
Self { path }
}
}
impl Drop for TestTree {
fn drop(&mut self) {
fs::remove_dir_all(&self.path).unwrap();
}
}
fn configuration(tree: &TestTree) -> lazaret_core::configuration::ResolvedDomainConfiguration {
let configuration_directory = tree.path.join("configuration");
let workspace = tree.path.join("workspace");
let runtime = tree.path.join("runtime");
fs::create_dir(&configuration_directory).unwrap();
fs::create_dir(&workspace).unwrap();
fs::create_dir(&runtime).unwrap();
let configuration_path = configuration_directory.join("lazaret.toml");
fs::write(
&configuration_path,
format!(
"schema = \"lazaret-trusted-host-config-v1\"\n[storage]\ndata_root = \"{}\"\n[profiles.default]\nimage = \"example.invalid/fixture:v1\"\npersistent_dirs = [\"/usr\"]\n",
tree.path.join("data").display()
),
)
.unwrap();
let layout = SandboxLayoutV1::from_production_layout([
"/workspace".to_owned(),
"/proc".to_owned(),
"/sys".to_owned(),
"/dev".to_owned(),
"/run/lazaret".to_owned(),
])
.unwrap();
load_trusted_configuration(ConfigurationLoadRequest {
explicit_configuration_path: Some(configuration_path),
selected_profile: "default".to_owned(),
workspace,
home: tree.path.join("home"),
xdg_config_home: None,
xdg_data_home: None,
xdg_runtime_dir: runtime,
environment: BTreeMap::<String, OsString>::new(),
sandbox_layout: layout,
})
.unwrap()
}