liminal-server 0.25.4

Standalone server for the liminal messaging bus
Documentation
use super::{Authority, MachinePass, PassRefusal};

pub struct PassLength<'a>(pub(crate) &'a MachinePass);

impl std::fmt::Debug for PassLength<'_> {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self.0.0.lock() {
            Ok(held) => held.token.len().fmt(formatter),
            Err(_) => PassRefusal("pass_holder_refused").fmt(formatter),
        }
    }
}

impl std::fmt::Debug for Authority {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        formatter
            .debug_struct("Authority")
            .field("current", &self.current)
            .field("pass", &PassLength(&self.pass))
            .field("dial", &self.dial)
            .field("adapter", &self.adapter)
            .field("boot_pending", &self.boot_pending)
            .finish()
    }
}

#[cfg(test)]
pub fn test_machine()
-> Result<(tempfile::TempDir, super::MachineConfig), Box<dyn std::error::Error>> {
    let root = tempfile::tempdir()?;
    let pass_path = root.path().join("machine.pass");
    let token = lys_pass::conformance::cases()
        .into_iter()
        .find(|case| case.name == "valid")
        .and_then(|case| case.token)
        .ok_or("valid conformance pass absent")?;
    std::fs::write(&pass_path, token)?;
    let mut machine: super::MachineConfig = toml::from_str("identity_path = 'unused'")?;
    machine.pass_path = pass_path;
    Ok((root, machine))
}

#[cfg(test)]
mod tests {
    use super::super::{
        Arc, Authority, Current, Ed25519Identity, LinkHost, LocalMachine, LysPassAdapter,
        LysPassConsumer, MachineConfig, MachineLinkRights, MachinePass, Mutex, Rights, Zeroizing,
    };
    use crate::link_dial::LinkDialer;

    fn authority()
    -> Result<(tempfile::TempDir, MachineConfig, Arc<Authority>), Box<dyn std::error::Error>> {
        use lys_pass::conformance::{AUDIENCE, ISSUER, KEYS, NOW};
        let (root, machine) = super::test_machine()?;
        let pass = MachinePass::configured(&machine)?;
        let adapter = Arc::new(LysPassAdapter::from_keys_json(KEYS, ISSUER.to_owned())?);
        let token = pass.current()?;
        let verified = adapter.verify_offline(token.as_bytes(), AUDIENCE, NOW)?;
        let authority = Arc::new(Authority {
            current: Mutex::new(Some(Current {
                rights: MachineLinkRights::new(&adapter, verified),
                expiry: u64::MAX,
                renew_at: u64::MAX,
                renewed: false,
            })),
            pass,
            dial: None,
            adapter,
            boot_pending: std::sync::atomic::AtomicBool::new(false),
        });
        Ok((root, machine, authority))
    }

    #[test]
    fn authority_debug_reports_pass_length() -> Result<(), Box<dyn std::error::Error>> {
        let (root, machine, authority) = authority()?;
        let token = authority.pass.current()?;
        let debug = format!("{authority:?}");
        assert!(
            debug.contains(&format!("pass: {}", token.len())),
            "pass length absent"
        );
        assert!(!debug.contains(token.as_str()), "credential bytes escaped");
        assert!(
            debug.contains("current:") && debug.contains("dial:") && debug.contains("adapter:")
        );
        assert_eq!(
            token.len(),
            std::fs::read_to_string(machine.pass_path)?.trim().len()
        );
        root.close()?;
        Ok(())
    }

    #[test]
    fn dialer_debug_reports_pass_length() -> Result<(), Box<dyn std::error::Error>> {
        let (root, machine, authority) = authority()?;
        let host = LinkHost::new(
            LocalMachine::new(Ed25519Identity::from_seed(&Zeroizing::new([1; 32]))),
            Box::new(Rights(Arc::clone(&authority))),
            std::collections::BTreeMap::new(),
        );
        let dialer = LinkDialer::new(&host, &machine);
        let token = authority.pass.current()?;
        let debug = format!("{dialer:?}");
        assert!(
            debug.contains(&format!("pass: Ok({})", token.len())),
            "pass length absent"
        );
        assert!(!debug.contains(token.as_str()), "credential bytes escaped");
        assert!(debug.contains("host:") && debug.contains("topology:"));
        root.close()?;
        Ok(())
    }
}