Skip to content

Commit 3bdf15c

Browse files
committed
test embedded replication auth
1 parent e94f7bd commit 3bdf15c

6 files changed

Lines changed: 164 additions & 4 deletions

File tree

libsql-server/src/auth/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use parsers::{parse_http_auth_header, parse_http_basic_auth_arg, parse_jwt_k
1515
pub use permission::Permission;
1616
pub use user_auth_strategies::{Disabled, HttpBasic, Jwt, UserAuthContext, UserAuthStrategy};
1717

18-
#[derive(Clone)]
18+
#[derive(Clone, Debug)]
1919
pub struct Auth {
2020
pub user_strategy: Arc<dyn UserAuthStrategy + Send + Sync>,
2121
}

libsql-server/src/auth/user_auth_strategies/disabled.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::{UserAuthContext, UserAuthStrategy};
22
use crate::auth::{AuthError, Authenticated};
33

4+
#[derive(Debug)]
45
pub struct Disabled {}
56

67
impl UserAuthStrategy for Disabled {

libsql-server/src/auth/user_auth_strategies/http_basic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::auth::{
55

66
use super::{UserAuthContext, UserAuthStrategy};
77

8+
#[derive(Debug)]
89
pub struct HttpBasic {
910
credential: String,
1011
}

libsql-server/src/auth/user_auth_strategies/jwt.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::fmt::{self, Debug, Formatter};
2+
13
use chrono::{DateTime, Utc};
24

35
use crate::{
@@ -15,6 +17,12 @@ pub struct Jwt {
1517
keys: Vec<jsonwebtoken::DecodingKey>,
1618
}
1719

20+
impl Debug for Jwt {
21+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
22+
f.debug_struct("Jwt").finish()
23+
}
24+
}
25+
1826
impl UserAuthStrategy for Jwt {
1927
fn authenticate(&self, ctx: UserAuthContext) -> Result<Authenticated, AuthError> {
2028
tracing::trace!("executing jwt auth");

libsql-server/src/auth/user_auth_strategies/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl UserAuthContext {
5555
}
5656
}
5757

58-
pub trait UserAuthStrategy: Sync + Send {
58+
pub trait UserAuthStrategy: Sync + Send + std::fmt::Debug {
5959
/// Returns a list of fields required by the stragegy.
6060
/// Every strategy implementation should override this function if it requires input to work.
6161
/// Strategy implementations should validate the content of provided fields.

libsql-server/tests/embedded_replica/mod.rs

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ use std::path::PathBuf;
66
use std::sync::Arc;
77
use std::time::{Duration, Instant};
88

9+
use crate::common::auth::encode;
910
use crate::common::http::Client;
1011
use crate::common::net::{init_tracing, SimServer, TestServer, TurmoilAcceptor, TurmoilConnector};
11-
use crate::common::snapshot_metrics;
12+
use crate::common::{self, snapshot_metrics};
1213
use libsql::Database;
13-
use libsql_server::config::{AdminApiConfig, DbConfig, RpcServerConfig, UserApiConfig};
14+
use libsql_server::auth::{user_auth_strategies, Auth};
15+
use libsql_server::config::{
16+
AdminApiConfig, DbConfig, RpcClientConfig, RpcServerConfig, UserApiConfig,
17+
};
1418
use serde_json::json;
1519
use tempfile::tempdir;
1620
use tokio::sync::Notify;
@@ -1362,3 +1366,149 @@ fn replicated_return() {
13621366

13631367
sim.run().unwrap();
13641368
}
1369+
1370+
#[test]
1371+
fn replicate_auth() {
1372+
init_tracing();
1373+
let mut sim = Builder::new()
1374+
.simulation_duration(Duration::from_secs(1000))
1375+
.build();
1376+
1377+
let (encoding, decoding) = common::auth::key_pair();
1378+
sim.host("primary", {
1379+
let decoding = decoding.clone();
1380+
move || {
1381+
let decoding = decoding.clone();
1382+
async move {
1383+
let tmp = tempdir()?;
1384+
let jwt_keys =
1385+
vec![jsonwebtoken::DecodingKey::from_ed_components(&decoding).unwrap()];
1386+
let auth = Auth::new(user_auth_strategies::Jwt::new(jwt_keys));
1387+
let server = TestServer {
1388+
path: tmp.path().to_owned().into(),
1389+
user_api_config: UserApiConfig {
1390+
hrana_ws_acceptor: None,
1391+
auth_strategy: auth,
1392+
..Default::default()
1393+
},
1394+
admin_api_config: Some(AdminApiConfig {
1395+
acceptor: TurmoilAcceptor::bind(([0, 0, 0, 0], 9090)).await?,
1396+
connector: TurmoilConnector,
1397+
disable_metrics: true,
1398+
}),
1399+
rpc_server_config: Some(RpcServerConfig {
1400+
acceptor: TurmoilAcceptor::bind(([0, 0, 0, 0], 4567)).await?,
1401+
tls_config: None,
1402+
}),
1403+
..Default::default()
1404+
};
1405+
1406+
server.start_sim(8080).await?;
1407+
1408+
Ok(())
1409+
}
1410+
}
1411+
});
1412+
1413+
sim.host("replica", {
1414+
let decoding = decoding.clone();
1415+
move || {
1416+
let decoding = decoding.clone();
1417+
async move {
1418+
let tmp = tempdir()?;
1419+
let jwt_keys =
1420+
vec![jsonwebtoken::DecodingKey::from_ed_components(&decoding).unwrap()];
1421+
let auth = Auth::new(user_auth_strategies::Jwt::new(jwt_keys));
1422+
let server = TestServer {
1423+
path: tmp.path().to_owned().into(),
1424+
user_api_config: UserApiConfig {
1425+
hrana_ws_acceptor: None,
1426+
auth_strategy: auth,
1427+
..Default::default()
1428+
},
1429+
admin_api_config: Some(AdminApiConfig {
1430+
acceptor: TurmoilAcceptor::bind(([0, 0, 0, 0], 9090)).await?,
1431+
connector: TurmoilConnector,
1432+
disable_metrics: true,
1433+
}),
1434+
rpc_client_config: Some(RpcClientConfig {
1435+
remote_url: "http://primary:4567".into(),
1436+
connector: TurmoilConnector,
1437+
tls_config: None,
1438+
}),
1439+
..Default::default()
1440+
};
1441+
1442+
server.start_sim(8080).await?;
1443+
1444+
Ok(())
1445+
}
1446+
}
1447+
});
1448+
1449+
sim.client("client", async move {
1450+
let token = encode(
1451+
&serde_json::json!({
1452+
"id": "default",
1453+
}),
1454+
&encoding,
1455+
);
1456+
1457+
// no auth
1458+
let tmp = tempdir().unwrap();
1459+
let db = Database::open_with_remote_sync_connector(
1460+
tmp.path().join("embedded").to_str().unwrap(),
1461+
"http://primary:8080",
1462+
"",
1463+
TurmoilConnector,
1464+
false,
1465+
None,
1466+
)
1467+
.await?;
1468+
1469+
assert!(db.sync().await.is_err());
1470+
1471+
let tmp = tempdir().unwrap();
1472+
let db = Database::open_with_remote_sync_connector(
1473+
tmp.path().join("embedded").to_str().unwrap(),
1474+
"http://replica:8080",
1475+
"",
1476+
TurmoilConnector,
1477+
false,
1478+
None,
1479+
)
1480+
.await?;
1481+
1482+
assert!(db.sync().await.is_err());
1483+
1484+
// auth
1485+
let tmp = tempdir().unwrap();
1486+
let db = Database::open_with_remote_sync_connector(
1487+
tmp.path().join("embedded").to_str().unwrap(),
1488+
"http://primary:8080",
1489+
token.clone(),
1490+
TurmoilConnector,
1491+
false,
1492+
None,
1493+
)
1494+
.await?;
1495+
1496+
assert!(db.sync().await.is_ok());
1497+
1498+
let tmp = tempdir().unwrap();
1499+
let db = Database::open_with_remote_sync_connector(
1500+
tmp.path().join("embedded").to_str().unwrap(),
1501+
"http://replica:8080",
1502+
token.clone(),
1503+
TurmoilConnector,
1504+
false,
1505+
None,
1506+
)
1507+
.await?;
1508+
1509+
assert!(db.sync().await.is_ok());
1510+
Ok(())
1511+
});
1512+
1513+
sim.run().unwrap();
1514+
}

0 commit comments

Comments
 (0)