liminal-cli 0.3.0

The liminal command: serve the network, maintain its stores, or serve its discovery MCP over stdio
Documentation
use std::error::Error;
use std::os::unix::fs::PermissionsExt;
use std::process::Command;

use base64::Engine;
use base64::engine::general_purpose::STANDARD;
use lys_core::ca::verify_certificate_request;

type TestResult = Result<(), Box<dyn Error>>;

#[test]
fn identity_creates_an_agent_key_and_a_signed_request_without_disclosing_the_seed() -> TestResult {
    let root = tempfile::tempdir()?;
    let key = root.path().join("agent.key");
    let config = root.path().join("config.toml");
    std::fs::write(
        &config,
        format!(
            "[auth.lys.machine]\nagent_id = 'liminal-seats'\naudience = 'liminal'\nidentity_path = '{}'\n",
            key.display()
        ),
    )?;
    let first = Command::new(env!("CARGO_BIN_EXE_liminal"))
        .arg("identity")
        .arg("--config")
        .arg(&config)
        .output()?;
    assert!(
        first.status.success(),
        "identity refused: {}",
        String::from_utf8_lossy(&first.stderr)
    );
    let seed = std::fs::read_to_string(&key)?;
    assert_eq!(hex::decode(seed.trim())?.len(), 32);
    assert_eq!(std::fs::metadata(&key)?.permissions().mode() & 0o777, 0o600);
    let stdout = String::from_utf8(first.stdout)?;
    assert!(stdout.starts_with("agent_id: liminal-seats\npublic_key: "));
    assert!(!stdout.contains(seed.trim()), "private seed was printed");
    let public = stdout
        .lines()
        .nth(1)
        .ok_or("public key absent")?
        .strip_prefix("public_key: ")
        .ok_or("public key label absent")?;
    assert_eq!(hex::decode(public)?.len(), 32);
    let csr = stdout
        .split_once("-----BEGIN CERTIFICATE REQUEST-----")
        .ok_or("CSR absent")?
        .1;
    let encoded = csr
        .split_once("-----END CERTIFICATE REQUEST-----")
        .ok_or("CSR end absent")?
        .0;
    let mut der = STANDARD.decode(encoded.split_whitespace().collect::<String>())?;
    let verified = verify_certificate_request(&der)?;
    assert_eq!(verified.common_name(), "liminal-seats");
    assert_eq!(
        verified.subject_public_key().as_slice(),
        hex::decode(public)?.as_slice()
    );
    // Corrupting the signature must invalidate the same request info.
    *der.last_mut().ok_or("CSR signature absent")? ^= 1;
    assert!(verify_certificate_request(&der).is_err());
    let second = Command::new(env!("CARGO_BIN_EXE_liminal"))
        .arg("identity")
        .arg("--config")
        .arg(&config)
        .output()?;
    assert!(second.status.success());
    assert_eq!(String::from_utf8(second.stdout)?, stdout);
    assert_eq!(std::fs::read_to_string(&key)?, seed);
    Ok(())
}

#[test]
fn identity_refuses_an_existing_malformed_seed_without_replacing_it() -> TestResult {
    let root = tempfile::tempdir()?;
    let key = root.path().join("agent.key");
    std::fs::write(&key, "malformed")?;
    std::fs::set_permissions(&key, std::fs::Permissions::from_mode(0o600))?;
    let config = root.path().join("config.toml");
    std::fs::write(
        &config,
        format!(
            "[auth.lys.machine]\nagent_id = 'liminal-seats'\naudience = 'liminal'\nidentity_path = '{}'\n",
            key.display()
        ),
    )?;
    let answer = Command::new(env!("CARGO_BIN_EXE_liminal"))
        .arg("identity")
        .arg("--config")
        .arg(&config)
        .output()?;
    assert!(!answer.status.success());
    assert!(String::from_utf8(answer.stderr)?.contains("agent seed must be 64 hexadecimal digits"));
    assert_eq!(std::fs::read_to_string(key)?, "malformed");
    Ok(())
}

#[test]
fn identity_refuses_a_publicly_readable_seed() -> TestResult {
    let root = tempfile::tempdir()?;
    let key = root.path().join("agent.key");
    std::fs::write(&key, hex::encode([7; 32]))?;
    std::fs::set_permissions(&key, std::fs::Permissions::from_mode(0o644))?;
    let config = root.path().join("config.toml");
    std::fs::write(
        &config,
        format!(
            "[auth.lys.machine]\nagent_id = 'liminal-seats'\naudience = 'liminal'\nidentity_path = '{}'\n",
            key.display()
        ),
    )?;
    let answer = Command::new(env!("CARGO_BIN_EXE_liminal"))
        .arg("identity")
        .arg("--config")
        .arg(&config)
        .output()?;
    assert!(!answer.status.success());
    assert!(String::from_utf8(answer.stderr)?.contains("agent seed permissions must be 0600"));
    assert_eq!(std::fs::metadata(key)?.permissions().mode() & 0o777, 0o644);
    Ok(())
}