149 lines
4.8 KiB
Rust
149 lines
4.8 KiB
Rust
|
|
// Contract tests for client install-time security defaults.
|
||
|
|
//
|
||
|
|
// Scope: inspect the client installer shell contract without running it.
|
||
|
|
// Targets: `scripts/install/client.sh`.
|
||
|
|
// Why: secure-by-default relay transport depends on installing the server-issued
|
||
|
|
// client cert bundle exactly where the desktop app auto-discovers it.
|
||
|
|
|
||
|
|
const CLIENT_INSTALL: &str = include_str!(concat!(
|
||
|
|
env!("CARGO_MANIFEST_DIR"),
|
||
|
|
"/scripts/install/client.sh"
|
||
|
|
));
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn client_install_accepts_server_generated_tls_bundle() {
|
||
|
|
for expected in [
|
||
|
|
"LESAVKA_CLIENT_PKI_BUNDLE",
|
||
|
|
"CLIENT_PKI_DIR",
|
||
|
|
"ca.crt",
|
||
|
|
"client.crt",
|
||
|
|
"client.key",
|
||
|
|
"install_client_pki_bundle",
|
||
|
|
"fetch_client_pki_bundle",
|
||
|
|
"LESAVKA_CLIENT_PKI_SSH_SOURCE",
|
||
|
|
"LESAVKA_CLIENT_CAPTURE_DIR",
|
||
|
|
"theia:/etc/lesavka/lesavka-client-pki.tar.gz",
|
||
|
|
"Pictures/lesavka",
|
||
|
|
"HTTPS/mTLS relay connections will not work until this bundle is installed",
|
||
|
|
"TLS identity:",
|
||
|
|
"Captures:",
|
||
|
|
"$USER_HOME/.local/bin/lesavka-client",
|
||
|
|
"User PATH alias:",
|
||
|
|
] {
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.contains(expected),
|
||
|
|
"client installer should include TLS bundle contract fragment {expected}"
|
||
|
|
);
|
||
|
|
}
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.contains(".config/lesavka/pki"),
|
||
|
|
"client cert bundle should land in the same path the desktop app auto-loads"
|
||
|
|
);
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.contains("0600"),
|
||
|
|
"client private key should be installed with private permissions"
|
||
|
|
);
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.contains("scp -q -o BatchMode=yes"),
|
||
|
|
"client installer should auto-fetch the server enrollment bundle without hanging"
|
||
|
|
);
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.contains("run_as_user mktemp"),
|
||
|
|
"auto-fetch destination should be owned by the user who runs scp"
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn client_install_prefers_invoked_checkout_for_development_installs() {
|
||
|
|
for expected in [
|
||
|
|
"INSTALL_SOURCE=${LESAVKA_INSTALL_SOURCE:-auto}",
|
||
|
|
"resolve_source_checkout",
|
||
|
|
"Using local source checkout",
|
||
|
|
"set LESAVKA_INSTALL_SOURCE=ref",
|
||
|
|
"LESAVKA_INSTALL_SOURCE=local requested",
|
||
|
|
"unsupported LESAVKA_INSTALL_SOURCE",
|
||
|
|
"source_revision",
|
||
|
|
"+dirty",
|
||
|
|
] {
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.contains(expected),
|
||
|
|
"client installer should preserve local-source install marker {expected}"
|
||
|
|
);
|
||
|
|
}
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.find("resolve_source_checkout").unwrap()
|
||
|
|
< CLIENT_INSTALL
|
||
|
|
.find("cargo clean && cargo build --release")
|
||
|
|
.unwrap(),
|
||
|
|
"client installer should resolve source before building"
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn client_install_reports_nvidia_and_open_source_media_routes() {
|
||
|
|
for expected in [
|
||
|
|
"report_client_media_acceleration",
|
||
|
|
"gst_element_available",
|
||
|
|
"first_available_gst_element",
|
||
|
|
"nvidia-smi is available",
|
||
|
|
"proprietary NVIDIA GStreamer route",
|
||
|
|
"open-source VAAPI/V4L2 GStreamer route",
|
||
|
|
"nvh265enc",
|
||
|
|
"nvh264dec",
|
||
|
|
"nvh264sldec",
|
||
|
|
"vah265enc",
|
||
|
|
"vaapih265enc",
|
||
|
|
"v4l2h265enc",
|
||
|
|
"vah264dec",
|
||
|
|
"vaapih264dec",
|
||
|
|
"v4l2h264dec",
|
||
|
|
"v4l2slh264dec",
|
||
|
|
"x265enc",
|
||
|
|
"avdec_h264",
|
||
|
|
"openh264dec",
|
||
|
|
"opusenc",
|
||
|
|
"opusdec",
|
||
|
|
"Opus upstream audio transport route",
|
||
|
|
"microphone noise suppression route",
|
||
|
|
"webrtcdsp",
|
||
|
|
"fall back to PCM",
|
||
|
|
"LESAVKA_H264_DECODER_PREFERENCE=software",
|
||
|
|
] {
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.contains(expected),
|
||
|
|
"client installer should preserve media acceleration fragment {expected}"
|
||
|
|
);
|
||
|
|
}
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL
|
||
|
|
.find("require_gst_element pipewiresrc")
|
||
|
|
.unwrap()
|
||
|
|
< CLIENT_INSTALL
|
||
|
|
.rfind("report_client_media_acceleration")
|
||
|
|
.unwrap(),
|
||
|
|
"media acceleration reporting should run after baseline GStreamer tools are verified"
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn client_install_treats_pipewire_as_one_coherent_transaction() {
|
||
|
|
for expected in [
|
||
|
|
"pacman_install()",
|
||
|
|
"libpipewire pipewire pipewire-audio pipewire-alsa pipewire-jack pipewire-pulse",
|
||
|
|
"breaks dependency '.*pipewire",
|
||
|
|
"PipeWire packages are at mixed exact versions",
|
||
|
|
"sudo pacman -Syu",
|
||
|
|
"failed retrieving file",
|
||
|
|
"sudo pacman -Syu --disable-download-timeout",
|
||
|
|
] {
|
||
|
|
assert!(
|
||
|
|
CLIENT_INSTALL.contains(expected),
|
||
|
|
"client installer should preserve PipeWire transaction marker {expected}"
|
||
|
|
);
|
||
|
|
}
|
||
|
|
assert!(
|
||
|
|
!CLIENT_INSTALL.contains("sudo pacman -Sq --needed --noconfirm \\\n git"),
|
||
|
|
"base package install should flow through pacman_install so failures get actionable diagnostics"
|
||
|
|
);
|
||
|
|
}
|