volli-server 0.1.10

Server for volli
Documentation
#![allow(unused_crate_dependencies)]
use hex;
use serial_test::serial;
use sha2::{Digest, Sha256};
use volli_server::{
    add_join_host, add_join_host_from_token, load_agent_whitelist, load_bind_host,
    load_coord_whitelist, load_join_hosts, load_profile_host, load_quic_port, load_tcp_port,
    remove_join_host_index, save_agent_whitelist, save_bind_host, save_coord_whitelist,
    save_join_hosts, save_profile_host, save_quic_port, save_tcp_port, secret_dir,
};

#[test]
#[serial]
fn secret_dir_adds_profile() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    let mut expected = std::path::PathBuf::from(base.path());
    expected.push("profiles");
    expected.push("coordinator");
    expected.push("p1");
    assert_eq!(secret_dir(Some("p1")), expected);
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn join_secret_roundtrip() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    save_join_hosts(
        "prof",
        &[volli_server::JoinHostEntry {
            coord_id: None,
            host: "h".into(),
            tcp_port: None,
            quic_port: None,
            token: None,
            cert: None,
            fingerprint: None,
            last_ok: None,
            last_fail: None,
        }],
    )
    .unwrap();
    let hosts = load_join_hosts("prof").unwrap();
    assert_eq!(hosts[0].host, "h");
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn host_roundtrip() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    save_profile_host("prof", "127.0.0.1").unwrap();
    let loaded = load_profile_host("prof").unwrap().unwrap();
    assert_eq!(loaded, "127.0.0.1");
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn join_host_roundtrip() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    let entry = volli_server::JoinHostEntry {
        coord_id: None,
        host: "jhost".into(),
        tcp_port: Some(1111),
        quic_port: Some(2222),
        token: None,
        cert: None,
        fingerprint: None,
        last_ok: None,
        last_fail: None,
    };
    add_join_host("prof", entry.clone()).unwrap();
    let hosts = load_join_hosts("prof").unwrap();
    assert_eq!(hosts, vec![entry]);
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn remove_join_host_index_works() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    let e1 = volli_server::JoinHostEntry {
        coord_id: None,
        host: "h1".into(),
        tcp_port: None,
        quic_port: None,
        token: None,
        cert: None,
        fingerprint: None,
        last_ok: None,
        last_fail: None,
    };
    let e2 = volli_server::JoinHostEntry {
        coord_id: None,
        host: "h2".into(),
        tcp_port: None,
        quic_port: None,
        token: None,
        cert: None,
        fingerprint: None,
        last_ok: None,
        last_fail: None,
    };
    add_join_host("prof", e1.clone()).unwrap();
    add_join_host("prof", e2.clone()).unwrap();
    remove_join_host_index("prof", 0).unwrap();
    let hosts = load_join_hosts("prof").unwrap();
    assert_eq!(hosts, vec![e2]);
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn add_join_host_from_token_roundtrip() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    let mut csk = [0u8; 32];
    getrandom::getrandom(&mut csk).unwrap();
    let token = volli_core::token::issue_token(&csk, "t", "c", "aid", 60).unwrap();
    let secret = volli_core::BootstrapSecret {
        host: "jhost".into(),
        quic_port: 4243,
        tcp_port: 4242,
        token,
        cert: vec![],
    };
    let encoded = secret.encode().unwrap();
    add_join_host_from_token("prof", &encoded).unwrap();
    let hosts = load_join_hosts("prof").unwrap();
    assert_eq!(hosts.len(), 1);
    assert_eq!(hosts[0].host, "jhost");
    let fp = hex::encode(Sha256::digest(&[]));
    assert_eq!(hosts[0].fingerprint.as_deref(), Some(fp.as_str()));
    assert_eq!(
        volli_core::token::decode_token(hosts[0].token.as_deref().unwrap())
            .unwrap()
            .payload
            .agent_id,
        "aid"
    );
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn bind_host_roundtrip() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    save_bind_host("prof", "bhost").unwrap();
    let loaded = load_bind_host("prof").unwrap().unwrap();
    assert_eq!(loaded, "bhost");
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn join_ports_roundtrip() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_SECRET_DIR", base.path());
    }
    let entry = volli_server::JoinHostEntry {
        coord_id: None,
        host: "h".into(),
        tcp_port: Some(1111),
        quic_port: Some(2222),
        token: None,
        cert: None,
        fingerprint: None,
        last_ok: None,
        last_fail: None,
    };
    add_join_host("prof", entry.clone()).unwrap();
    let hosts = load_join_hosts("prof").unwrap();
    assert_eq!(hosts, vec![entry]);
    unsafe {
        std::env::remove_var("VOLLI_SECRET_DIR");
    }
}

#[test]
#[serial]
fn add_join_host_merges_fields() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    let entry1 = volli_server::JoinHostEntry {
        coord_id: None,
        host: "h".into(),
        tcp_port: Some(1),
        quic_port: Some(2),
        token: Some("tok".into()),
        cert: Some("cert".into()),
        fingerprint: Some("fp".into()),
        last_ok: None,
        last_fail: None,
    };
    let entry2 = volli_server::JoinHostEntry {
        coord_id: None,
        host: "h".into(),
        tcp_port: Some(3),
        quic_port: Some(4),
        token: None,
        cert: None,
        fingerprint: None,
        last_ok: Some(42),
        last_fail: None,
    };
    add_join_host("prof", entry1).unwrap();
    add_join_host("prof", entry2).unwrap();
    let hosts = load_join_hosts("prof").unwrap();
    assert_eq!(hosts.len(), 1);
    let h = &hosts[0];
    assert_eq!(h.tcp_port, Some(3));
    assert_eq!(h.quic_port, Some(4));
    assert_eq!(h.token.as_deref(), Some("tok"));
    assert_eq!(h.cert.as_deref(), Some("cert"));
    assert_eq!(h.fingerprint.as_deref(), Some("fp"));
    assert_eq!(h.last_ok, Some(42));
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn bind_ports_roundtrip() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_SECRET_DIR", base.path());
    }
    save_tcp_port("prof", 3333).unwrap();
    save_quic_port("prof", 4444).unwrap();
    assert_eq!(load_tcp_port("prof").unwrap().unwrap(), 3333);
    assert_eq!(load_quic_port("prof").unwrap().unwrap(), 4444);
    unsafe {
        std::env::remove_var("VOLLI_SECRET_DIR");
    }
}

#[test]
#[serial]
fn secret_dir_default() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    let mut expected = std::path::PathBuf::from(base.path());
    expected.push("profiles");
    expected.push("coordinator");
    assert_eq!(secret_dir(None), expected);
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn join_secret_missing() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    let hosts = load_join_hosts("unknown").unwrap();
    assert!(hosts.is_empty());
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn list_and_delete_profiles() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    save_profile_host("p1", "h1").unwrap();
    save_profile_host("p2", "h2").unwrap();
    let mut profiles = volli_server::list_profiles().unwrap();
    profiles.sort();
    assert_eq!(profiles, vec!["p1", "p2"]);
    volli_server::delete_profile("p1").unwrap();
    let profiles = volli_server::list_profiles().unwrap();
    assert_eq!(profiles, vec!["p2"]);
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn profile_exists_checks_presence() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    save_profile_host("p1", "h1").unwrap();
    assert!(volli_server::profile_exists("p1"));
    volli_server::delete_profile("p1").unwrap();
    assert!(!volli_server::profile_exists("p1"));
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn rename_profile_moves_dir() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    save_profile_host("old", "h").unwrap();
    volli_server::rename_profile("old", "new").unwrap();
    assert!(!volli_server::profile_exists("old"));
    assert!(volli_server::profile_exists("new"));
    assert_eq!(load_profile_host("new").unwrap().unwrap(), "h");
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn rename_profile_conflict() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    save_profile_host("old", "h1").unwrap();
    save_profile_host("new", "h2").unwrap();
    assert!(volli_server::rename_profile("old", "new").is_err());
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}

#[test]
#[serial]
fn whitelist_roundtrip() {
    let base = tempfile::TempDir::new().unwrap();
    unsafe {
        std::env::set_var("VOLLI_CONFIG_DIR", base.path());
    }
    save_agent_whitelist("p1", &["127.0.0.1/32".into()]).unwrap();
    save_coord_whitelist("p1", &["10.0.0.0/8".into()]).unwrap();
    let a = load_agent_whitelist("p1").unwrap().unwrap();
    let c = load_coord_whitelist("p1").unwrap().unwrap();
    assert_eq!(a, vec!["127.0.0.1/32".to_string()]);
    assert_eq!(c, vec!["10.0.0.0/8".to_string()]);
    unsafe {
        std::env::remove_var("VOLLI_CONFIG_DIR");
    }
}