// API/security contract for unauthenticated relay RPC rejection. // // Scope: preserve the security boundary between transport authentication and // handler execution for media, HID, and paste RPCs. // Targets: server entrypoint and relay helper modules. // Why: without TLS/mTLS on the server builder, any client could stream media or // HID reports into the remote controlled target. const ENTRYPOINT: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/server/src/main/entrypoint.rs" )); const SERVER_SECURITY: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/server/src/security.rs" )); const INPUT_RPC: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/server/src/main/relay_service/input_stream_rpc.rs" )); const CAMERA_RPC: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/server/src/main/relay_service/camera_stream_rpc.rs" )); const MICROPHONE_RPC: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/server/src/main/relay_service/microphone_stream_rpc.rs" )); const RPC_HELPERS: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/server/src/main/rpc_helpers.rs" )); #[test] fn server_installs_tls_before_exposing_relay_services() { let tls_idx = ENTRYPOINT .find("security::server_tls_config()?") .expect("entrypoint should request TLS config"); let relay_idx = ENTRYPOINT .find(".add_service(RelayServer::new(handler))") .expect("entrypoint should expose relay service"); assert!( tls_idx < relay_idx, "TLS must be configured before media/HID RPC services are exposed" ); assert!(ENTRYPOINT.contains("server = server.tls_config(tls)?")); } #[test] fn production_mtls_requires_a_client_ca_unless_operator_explicitly_opts_out() { assert!(SERVER_SECURITY.contains("client_ca_root")); assert!(SERVER_SECURITY.contains("LESAVKA_TLS_CLIENT_AUTH_OPTIONAL")); assert!( SERVER_SECURITY.contains("TLS enabled with required client certificate authentication"), "required client certificate auth should be the normal CA-backed path" ); } #[test] fn powerful_rpc_handlers_depend_on_transport_auth_boundary() { for (name, source, lease_marker) in [ ("keyboard", INPUT_RPC, "capture_power.acquire_session()"), ("mouse", INPUT_RPC, "capture_power.acquire_session()"), ("camera", CAMERA_RPC, "activate_camera()"), ("microphone", MICROPHONE_RPC, "reserve_microphone_sink"), ] { assert!( source.contains(lease_marker), "{name} RPC should continue using runtime leases after transport auth" ); assert!( !source.contains("LESAVKA_ALLOW_INSECURE"), "{name} RPC should not override transport security inside handler code" ); } } #[test] fn unauthenticated_paste_payloads_map_to_unauthenticated_status() { assert!(RPC_HELPERS.contains("paste::decrypt(&req)")); assert!(RPC_HELPERS.contains("Status::unauthenticated")); assert!( RPC_HELPERS .find("paste::decrypt(&req)") .expect("decrypt marker") < RPC_HELPERS .find("paste::type_text") .expect("type text marker"), "paste payloads must authenticate/decrypt before HID typing begins" ); }