use kitsune2_bootstrap_srv::{BootstrapSrv, Config};
use kitsune2_core::{Ed25519LocalAgent, Ed25519Verifier};
use kitsune2_test_utils::enable_tracing;
use std::sync::Arc;
use url::Url;
use kitsune2_bootstrap_client::*;
#[test]
fn connect_with_client() {
enable_tracing();
let s = BootstrapSrv::new(Config::testing()).unwrap();
let local_agent: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent);
let server_url =
Url::parse(&format!("http://{:?}", s.listen_addrs()[0])).unwrap();
blocking_put(server_url.clone(), &info).unwrap();
let infos = blocking_get(
server_url.clone(),
info.space.clone(),
Arc::new(Ed25519Verifier),
)
.unwrap();
assert_eq!(1, infos.len());
assert_eq!(info, infos[0]);
}
#[test]
fn connect_with_auth() {
enable_tracing();
let s = BootstrapSrv::new(Config::testing()).unwrap();
let local_agent: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent);
let server_url =
Url::parse(&format!("http://{:?}", s.listen_addrs()[0])).unwrap();
let auth = AuthMaterial::new(b"hello".to_vec());
blocking_put_auth(server_url.clone(), &info, Some(&auth)).unwrap();
let infos = blocking_get_auth(
server_url.clone(),
info.space.clone(),
Arc::new(Ed25519Verifier),
Some(&auth),
)
.unwrap();
assert_eq!(1, infos.len());
assert_eq!(info, infos[0]);
}
#[test]
fn connect_with_bad_auth_retries() {
enable_tracing();
let s = BootstrapSrv::new(Config::testing()).unwrap();
let local_agent: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent);
let server_url =
Url::parse(&format!("http://{:?}", s.listen_addrs()[0])).unwrap();
let auth = AuthMaterial::new(b"hello".to_vec());
*auth.danger_access_token().lock().unwrap() = Some("bob".into());
assert_eq!(
"bob",
auth.danger_access_token().lock().unwrap().as_ref().unwrap()
);
blocking_put_auth(server_url.clone(), &info, Some(&auth)).unwrap();
assert_ne!(
"bob",
auth.danger_access_token().lock().unwrap().as_ref().unwrap()
);
}
#[tokio::test(flavor = "multi_thread")]
async fn auth_with_real_token_provider() {
enable_tracing();
async fn handle_auth(body: bytes::Bytes) -> axum::response::Response {
if &body[..] != b"hello" {
return axum::response::IntoResponse::into_response((
axum::http::StatusCode::UNAUTHORIZED,
"Unauthorized",
));
}
axum::response::IntoResponse::into_response(axum::Json(
serde_json::json!({
"authToken": "bob",
}),
))
}
let app: axum::Router<()> = axum::Router::new()
.route("/authenticate", axum::routing::put(handle_auth));
let h = axum_server::Handle::default();
let h2 = h.clone();
let auth_hook_server_task = tokio::task::spawn(async move {
axum_server::bind(([127, 0, 0, 1], 0).into())
.handle(h2)
.serve(app.into_make_service_with_connect_info::<std::net::SocketAddr>())
.await
.unwrap();
});
let hook_addr = h.listening().await.unwrap();
println!("hook_addr: {hook_addr:?}");
let mut config = Config::testing();
let auth_hook_url = format!("http://{hook_addr:?}");
config.auth.authentication_hook_server = Some(auth_hook_url.clone());
config.sbd.authentication_hook_server =
Some(format!("{auth_hook_url}/authenticate"));
config.allowed_origins = Some(vec!["http://localhost".into()]);
let s =
tokio::task::block_in_place(move || BootstrapSrv::new(config).unwrap());
let server_url =
Url::parse(&format!("http://{:?}", s.listen_addrs()[0])).unwrap();
let local_agent: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent);
let auth1 = AuthMaterial::new(b"hello".to_vec());
tokio::task::block_in_place(|| {
blocking_put_auth(server_url.clone(), &info, Some(&auth1)).unwrap();
});
let local_agent: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent);
let auth2 = AuthMaterial::new(b"bad".to_vec());
tokio::task::block_in_place(|| {
blocking_put_auth(server_url.clone(), &info, Some(&auth2)).unwrap_err();
});
auth_hook_server_task.abort();
}
#[tokio::test(flavor = "multi_thread")]
async fn auth_feature_independent() {
enable_tracing();
async fn handle_auth(body: bytes::Bytes) -> axum::response::Response {
if &body[..] != b"secret" {
return axum::response::IntoResponse::into_response((
axum::http::StatusCode::UNAUTHORIZED,
"Unauthorized",
));
}
axum::response::IntoResponse::into_response(axum::Json(
serde_json::json!({
"authToken": "valid-token-123",
}),
))
}
let app: axum::Router<()> = axum::Router::new()
.route("/authenticate", axum::routing::put(handle_auth));
let h = axum_server::Handle::default();
let h2 = h.clone();
let auth_hook_server_task = tokio::task::spawn(async move {
axum_server::bind(([127, 0, 0, 1], 0).into())
.handle(h2)
.serve(app.into_make_service_with_connect_info::<std::net::SocketAddr>())
.await
.unwrap();
});
let hook_addr = h.listening().await.unwrap();
println!("hook_addr: {hook_addr:?}");
let mut config = Config::testing();
config.auth.authentication_hook_server =
Some(format!("http://{hook_addr:?}"));
config.no_relay_server = true;
config.allowed_origins = Some(vec!["http://localhost".into()]);
let s =
tokio::task::block_in_place(move || BootstrapSrv::new(config).unwrap());
let server_url =
Url::parse(&format!("http://{:?}", s.listen_addrs()[0])).unwrap();
let local_agent: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent);
let valid_auth = AuthMaterial::new(b"secret".to_vec());
tokio::task::block_in_place(|| {
blocking_put_auth(server_url.clone(), &info, Some(&valid_auth))
.unwrap();
let infos = blocking_get_auth(
server_url.clone(),
info.space.clone(),
Arc::new(Ed25519Verifier),
Some(&valid_auth),
)
.unwrap();
assert_eq!(1, infos.len());
assert_eq!(info, infos[0]);
});
let local_agent2: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info2 =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent2);
let invalid_auth = AuthMaterial::new(b"wrong-secret".to_vec());
tokio::task::block_in_place(|| {
blocking_put_auth(server_url.clone(), &info2, Some(&invalid_auth))
.unwrap_err();
});
let local_agent3: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info3 =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent3);
tokio::task::block_in_place(|| {
blocking_put(server_url.clone(), &info3).unwrap_err();
blocking_get(
server_url.clone(),
info3.space.clone(),
Arc::new(Ed25519Verifier),
)
.unwrap_err();
});
auth_hook_server_task.abort();
}
#[tokio::test(flavor = "multi_thread")]
async fn reauth_on_token_expiration() {
enable_tracing();
async fn handle_auth(body: bytes::Bytes) -> axum::response::Response {
if &body[..] != b"secret" {
return axum::response::IntoResponse::into_response((
axum::http::StatusCode::UNAUTHORIZED,
"Unauthorized",
));
}
axum::response::IntoResponse::into_response(axum::Json(
serde_json::json!({
"authToken": "valid-token",
}),
))
}
let app: axum::Router<()> = axum::Router::new()
.route("/authenticate", axum::routing::put(handle_auth));
let h = axum_server::Handle::default();
let h2 = h.clone();
let auth_hook_server_task = tokio::task::spawn(async move {
axum_server::bind(([127, 0, 0, 1], 0).into())
.handle(h2)
.serve(app.into_make_service_with_connect_info::<std::net::SocketAddr>())
.await
.unwrap();
});
let hook_addr = h.listening().await.unwrap();
let mut config = Config::testing();
config.auth.authentication_hook_server =
Some(format!("http://{hook_addr:?}"));
config.auth.auth_token_idle_timeout = std::time::Duration::from_millis(200);
config.no_relay_server = true;
config.allowed_origins = Some(vec!["http://localhost".into()]);
let s =
tokio::task::block_in_place(move || BootstrapSrv::new(config).unwrap());
let server_url =
Url::parse(&format!("http://{:?}", s.listen_addrs()[0])).unwrap();
let local_agent: kitsune2_api::DynLocalAgent =
Arc::new(Ed25519LocalAgent::default());
let info =
kitsune2_test_utils::agent::AgentBuilder::default().build(local_agent);
let auth = AuthMaterial::new(b"secret".to_vec());
tokio::task::block_in_place(|| {
blocking_put_auth(server_url.clone(), &info, Some(&auth)).unwrap();
});
tokio::time::sleep(std::time::Duration::from_millis(300)).await;
tokio::task::block_in_place(|| {
let infos = blocking_get_auth(
server_url.clone(),
info.space.clone(),
Arc::new(Ed25519Verifier),
Some(&auth),
)
.unwrap();
assert_eq!(1, infos.len());
assert_eq!(info, infos[0]);
});
auth_hook_server_task.abort();
}