From abdf4e3893234af063e6ca79958acc5c33c0a235 Mon Sep 17 00:00:00 2001 From: hdbg Date: Sat, 14 Feb 2026 19:25:56 +0100 Subject: [PATCH] tests(server): `UserAgent` invalid bootstrap token --- mise.lock | 4 ++ mise.toml | 1 + server/Cargo.lock | 46 +++++++++++++ server/crates/arbiter-server/Cargo.toml | 1 + .../arbiter-server/src/actors/user_agent.rs | 64 ++++++++++++++++++- 5 files changed, 115 insertions(+), 1 deletion(-) diff --git a/mise.lock b/mise.lock index b54380c..847643a 100644 --- a/mise.lock +++ b/mise.lock @@ -10,6 +10,10 @@ backend = "cargo:cargo-features" version = "0.11.1" backend = "cargo:cargo-features-manager" +[[tools."cargo:cargo-insta"]] +version = "1.46.3" +backend = "cargo:cargo-insta" + [[tools."cargo:cargo-nextest"]] version = "0.9.126" backend = "cargo:cargo-nextest" diff --git a/mise.toml b/mise.toml index ae98d2d..22adad3 100644 --- a/mise.toml +++ b/mise.toml @@ -9,3 +9,4 @@ rust = "1.93.0" "cargo:cargo-features-manager" = "0.11.1" "cargo:cargo-nextest" = "0.9.126" "cargo:cargo-shear" = "latest" +"cargo:cargo-insta" = "1.46.3" diff --git a/server/Cargo.lock b/server/Cargo.lock index 5c52185..a089289 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -72,6 +72,7 @@ dependencies = [ "diesel_migrations", "ed25519-dalek", "futures", + "insta", "kameo", "memsafe", "miette", @@ -342,6 +343,18 @@ dependencies = [ "cc", ] +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "windows-sys 0.59.0", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -641,6 +654,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "equivalent" version = "1.0.2" @@ -1060,6 +1079,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "insta" +version = "1.46.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e82db8c87c7f1ccecb34ce0c24399b8a73081427f3c7c50a5d597925356115e4" +dependencies = [ + "console", + "once_cell", + "similar", + "tempfile", +] + [[package]] name = "is_ci" version = "1.2.0" @@ -1883,6 +1914,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + [[package]] name = "slab" version = "0.4.12" @@ -2651,6 +2688,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.60.2" diff --git a/server/crates/arbiter-server/Cargo.toml b/server/crates/arbiter-server/Cargo.toml index 5cfe75f..e947511 100644 --- a/server/crates/arbiter-server/Cargo.toml +++ b/server/crates/arbiter-server/Cargo.toml @@ -46,4 +46,5 @@ zeroize = { version = "1.8.2", features = ["std", "simd"] } kameo.workspace = true [dev-dependencies] +insta = "1.46.3" test-log = { version = "0.2", default-features = false, features = ["trace"] } diff --git a/server/crates/arbiter-server/src/actors/user_agent.rs b/server/crates/arbiter-server/src/actors/user_agent.rs index 0b98e5b..9893e24 100644 --- a/server/crates/arbiter-server/src/actors/user_agent.rs +++ b/server/crates/arbiter-server/src/actors/user_agent.rs @@ -311,10 +311,12 @@ mod tests { UserAgentResponse, auth::{AuthChallengeRequest, AuthOk}, user_agent_response::Payload as UserAgentResponsePayload, }; + use diesel::QueryDsl; + use diesel_async::RunQueryDsl; use kameo::actor::Spawn; use crate::{ - actors::user_agent::HandleAuthChallengeRequest, context::bootstrap::BootstrapActor, db, + actors::user_agent::HandleAuthChallengeRequest, context::bootstrap::BootstrapActor, db::{self, schema}, }; use super::UserAgentActor; @@ -362,6 +364,66 @@ mod tests { )), } ); + + // key is succesfully recorded in database + let mut conn = db.get().await.unwrap(); + let stored_pubkey: Vec = schema::useragent_client::table + .select(schema::useragent_client::public_key) + .first::>(&mut conn) + .await + .unwrap(); + assert_eq!(stored_pubkey, new_key.verifying_key().to_bytes().to_vec()); + } + + #[tokio::test] + #[test_log::test] + pub async fn test_bootstrap_invalid_token_auth() { + let db = db::create_test_pool().await; + // explicitly not installing any user_agent pubkeys + let bootstrapper = BootstrapActor::new(&db).await.unwrap(); // this will create bootstrap token + + let bootstrapper_ref = BootstrapActor::spawn(bootstrapper); + let user_agent = UserAgentActor::new_manual( + db.clone(), + bootstrapper_ref, + tokio::sync::mpsc::channel(1).0, // dummy channel, we won't actually send responses in this test + ); + let user_agent_ref = UserAgentActor::spawn(user_agent); + + // simulate client sending auth request with bootstrap token + let new_key = ed25519_dalek::SigningKey::generate(&mut rand::rng()); + let pubkey_bytes = new_key.verifying_key().to_bytes().to_vec(); + + let result = user_agent_ref + .ask(HandleAuthChallengeRequest { + req: AuthChallengeRequest { + pubkey: pubkey_bytes, + bootstrap_token: Some("invalid_token".to_string()), + }, + }) + .await + ; + + match result { + Err(kameo::error::SendError::HandlerError(status)) => { + assert_eq!(status.code(), tonic::Code::InvalidArgument); + insta::assert_debug_snapshot!(status, @r#" + Status { + code: InvalidArgument, + message: "Invalid bootstrap token", + source: None, + } + "#); + }, + Err(other) => { + panic!("Expected SendError::HandlerError, got {other:?}"); + }, + Ok(_) => { + panic!("Expected error due to invalid bootstrap token, but got success"); + } + } + + } }