crates/gunnar-front/tests/proof_medium.rs
//! **A PROOF medium's material** — a seed of kind `front` (and one of kind
//! `gunnar`) with the installer's material beside it, for composing and booting
//! the front medium on this box when no estate's material exists.
//!
//! NOT the estate's material: `private-gunnar-ops` (`estate install`,
//! `installer::seed_for_compose`) mints that per estate and composes its own
//! media with it. This is the same shape through the same edda types, so a
//! medium composed with it proves the build and the boot, and an installer run
//! with the material beside it can reach that box's listener.
//!
//! ```text
//! GUNNAR_FRONT_PROOF_MEDIUM=<dir> cargo test --manifest-path crates/gunnar-front/Cargo.toml --target-dir target --test proof_medium -- --ignored
//! <dir>/seed-front.toml seed-gunnar.toml (0600: the bootstrap key and the link key)
//! <dir>/material/{ca.cert.pem,ca.key.pem,installer.cert.pem,installer.key.pem,link.toml}
//! ```
use nordisk_pairing::installer::{
Material, CA_CERT, CA_KEY, INSTALLER_CERT, INSTALLER_KEY, LINK_KEYS,
};
use nordisk_pairing::mtls::InstallerCa;
use nordisk_pairing::seed::{Front, Kind, LinkSeed, Seed, TunnelKind};
use std::path::Path;
use std::time::Duration;
fn write_private(path: &Path, text: &str) {
use std::io::Write as _;
use std::os::unix::fs::OpenOptionsExt as _;
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
let mut f = std::fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.mode(0o600)
.open(path)
.unwrap();
f.write_all(text.as_bytes()).unwrap();
}
/// A WireGuard key pair (private b64, public b64), minted the way a box mints
/// its own `wg0.key` (gunnar-server `pairing::ensure_tunnel_key`).
fn keypair() -> (String, String) {
let dir = tempfile::tempdir().unwrap();
let private = gunnar_server::pairing::ensure_tunnel_key(dir.path()).unwrap();
(private, gunnar_server::pairing::tunnel_pubkey(dir.path()))
}
#[test]
#[ignore = "writes a proof medium's material to $GUNNAR_FRONT_PROOF_MEDIUM"]
fn mint_a_proof_medium() {
let Ok(dir) = std::env::var("GUNNAR_FRONT_PROOF_MEDIUM") else {
panic!("set GUNNAR_FRONT_PROOF_MEDIUM=<dir>");
};
let dir = Path::new(&dir);
let estate =
std::env::var("GUNNAR_FRONT_PROOF_ESTATE").unwrap_or_else(|_| "proof.gunnar.local".into());
let valid = Duration::from_secs(30 * 24 * 3600);
let ca = InstallerCa::mint(&estate, valid).unwrap();
let boot = ca.issue_bootstrap(valid).unwrap();
let me = ca.issue_installer(valid).unwrap();
let (inst_private_b64, inst_public_b64) = keypair();
let (vm_private_b64, vm_public_b64) = keypair();
let m = dir.join("material");
write_private(&m.join(CA_CERT), &ca.cert_pem);
write_private(&m.join(CA_KEY), &ca.key_pem);
write_private(&m.join(INSTALLER_CERT), &me.cert_pem);
write_private(&m.join(INSTALLER_KEY), &me.key_pem);
write_private(
&m.join(LINK_KEYS),
&Material::link_file(&inst_private_b64, &vm_public_b64),
);
for kind in [Kind::Front, Kind::Gunnar] {
let seed = Seed {
estate: estate.clone(),
tunnel: TunnelKind::Wireguard,
front: Front::default(),
kind,
installer_ca_pem: ca.cert_pem.clone(),
bootstrap_cert_pem: boot.cert_pem.clone(),
bootstrap_key_pem: boot.key_pem.clone(),
peers_expected: 3,
mullvad: None,
tailscale: None,
installer_link: Some(LinkSeed {
installer_pubkey: inst_public_b64.clone(),
vm_private: vm_private_b64.clone(),
port: nordisk_pairing::installer_link::LINK_PORT,
psk: None,
}),
};
let text = seed.render().unwrap();
Seed::parse(&text).expect("the seed parses back");
let name = if kind == Kind::Front {
"seed-front.toml"
} else {
"seed-gunnar.toml"
};
write_private(&dir.join(name), &text);
}
Material::load(&m).expect("the installer's material loads");
eprintln!("proof medium material in {}", dir.display());
}