diff --git a/Cargo.lock b/Cargo.lock index 9190d2a..ce8c901 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.87" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arraydeque" @@ -539,11 +539,11 @@ dependencies = [ "nix 0.27.1", "once_cell", "parking_lot", - "prost 0.13.2", - "prost-types 0.13.2", + "prost 0.13.3", + "prost-types 0.13.3", "rand", "rand_core", - "reqwest 0.12.7", + "reqwest 0.12.9", "ring", "rusqlite", "rust-ini 0.21.1", @@ -2644,12 +2644,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2ecbe40f08db5c006b5764a2645f7f3f141ce756412ac9e1dd6087e6d32995" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.13.2", + "prost-derive 0.13.3", ] [[package]] @@ -2666,8 +2666,8 @@ dependencies = [ "once_cell", "petgraph", "prettyplease", - "prost 0.13.2", - "prost-types 0.13.2", + "prost 0.13.3", + "prost-types 0.13.3", "regex", "syn 2.0.89", "tempfile", @@ -2688,9 +2688,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf0c195eebb4af52c752bec4f52f645da98b6e92077a04110c7f349477ae5ac" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", "itertools 0.13.0", @@ -2710,11 +2710,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60caa6738c7369b940c3d49246a8d1749323674c65cb13010134f5c9bad5b519" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ - "prost 0.13.2", + "prost 0.13.3", ] [[package]] @@ -2899,9 +2899,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", @@ -3249,9 +3249,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -3290,6 +3290,27 @@ dependencies = [ "serde", ] +[[package]] +name = "server" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "config", + "dotenvy", + "jwt-simple", + "log", + "prost 0.13.3", + "prost-types 0.13.3", + "reqwest 0.12.9", + "rusqlite", + "serde", + "serde_json", + "tokio", + "tonic 0.12.3", + "tonic-build", +] + [[package]] name = "sha-1" version = "0.10.1" @@ -3591,9 +3612,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -3754,7 +3775,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost 0.13.2", + "prost 0.13.3", "socket2", "tokio", "tokio-stream", @@ -3773,7 +3794,7 @@ dependencies = [ "prettyplease", "proc-macro2", "prost-build", - "prost-types 0.13.2", + "prost-types 0.13.3", "quote", "syn 2.0.89", ] diff --git a/Cargo.toml b/Cargo.toml index 362ba2b..4494416 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["burrow", "tun"] +members = ["burrow", "server", "tun"] resolver = "2" exclude = ["burrow-gtk"] diff --git a/burrow/src/auth/mod.rs b/burrow/src/auth/mod.rs deleted file mode 100644 index c07f47e..0000000 --- a/burrow/src/auth/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod client; -pub mod server; diff --git a/burrow/src/lib.rs b/burrow/src/lib.rs index 6aae1fb..5bf0be9 100644 --- a/burrow/src/lib.rs +++ b/burrow/src/lib.rs @@ -5,18 +5,13 @@ pub mod wireguard; mod daemon; #[cfg(any(target_os = "linux", target_vendor = "apple"))] pub mod database; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] -mod auth; + pub(crate) mod tracing; #[cfg(target_vendor = "apple")] pub use daemon::apple::spawn_in_process; #[cfg(any(target_os = "linux", target_vendor = "apple"))] pub use daemon::{ - rpc::DaemonResponse, - rpc::ServerInfo, - DaemonClient, - DaemonCommand, - DaemonResponseData, + rpc::DaemonResponse, rpc::ServerInfo, DaemonClient, DaemonCommand, DaemonResponseData, DaemonStartOptions, }; diff --git a/burrow/src/main.rs b/burrow/src/main.rs index e87b4c9..e2cbba5 100644 --- a/burrow/src/main.rs +++ b/burrow/src/main.rs @@ -7,9 +7,6 @@ pub(crate) mod tracing; #[cfg(any(target_os = "linux", target_vendor = "apple"))] mod wireguard; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] -mod auth; - #[cfg(any(target_os = "linux", target_vendor = "apple"))] use daemon::{DaemonClient, DaemonCommand}; @@ -52,8 +49,6 @@ enum Commands { ServerConfig, /// Reload Config ReloadConfig(ReloadConfigArgs), - /// Authentication server - AuthServer, /// Server Status ServerStatus, /// Tunnel Config @@ -276,7 +271,6 @@ async fn main() -> Result<()> { Commands::ServerInfo => try_serverinfo().await?, Commands::ServerConfig => try_serverconfig().await?, Commands::ReloadConfig(args) => try_reloadconfig(args.interface_id.clone()).await?, - Commands::AuthServer => crate::auth::server::serve().await?, Commands::ServerStatus => try_serverstatus().await?, Commands::TunnelConfig => try_tun_config().await?, Commands::NetworkAdd(args) => { diff --git a/server/Cargo.toml b/server/Cargo.toml new file mode 100644 index 0000000..3f1d072 --- /dev/null +++ b/server/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "server" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.93" +jwt-simple = "0.12.10" +log = "0.4.22" +reqwest = { version = "0.12.9", default-features = false, features = [ + "json", + "rustls-tls", +] } +serde = "1.0.215" +serde_json = "1.0.133" +tokio = { version = "1.41.1", features = [ + "rt", + "macros", + "sync", + "io-util", + "rt-multi-thread", + "signal", + "time", + "tracing", + "fs", +] } +tonic = "0.12.3" +clap = { version = "4.4", features = ["derive"] } +rusqlite = { version = "0.31.0", features = ["blob"] } +dotenvy = "0.15.7" +config = "0.14.1" +prost = "0.13.3" +prost-types = "0.13.3" + + +[features] +bundled = ["rusqlite/bundled"] + +[build-dependencies] +tonic-build = "0.12.3" diff --git a/server/build.rs b/server/build.rs new file mode 100644 index 0000000..22aebed --- /dev/null +++ b/server/build.rs @@ -0,0 +1,4 @@ +fn main() -> Result<(), Box> { + tonic_build::configure().compile_protos(&["../proto/burrowweb.proto"], &["../proto"])?; + Ok(()) +} diff --git a/burrow/src/auth/server/providers/mod.rs b/server/src/auth/server/providers/mod.rs similarity index 100% rename from burrow/src/auth/server/providers/mod.rs rename to server/src/auth/server/providers/mod.rs diff --git a/server/src/build.rs b/server/src/build.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/server/src/build.rs @@ -0,0 +1 @@ + diff --git a/burrow/src/auth/client.rs b/server/src/client.rs similarity index 100% rename from burrow/src/auth/client.rs rename to server/src/client.rs diff --git a/server/src/main.rs b/server/src/main.rs new file mode 100644 index 0000000..60f3081 --- /dev/null +++ b/server/src/main.rs @@ -0,0 +1,6 @@ +pub mod client; +pub mod server; + +fn main() { + println!("Hello, world!"); +} diff --git a/burrow/src/auth/server/db.rs b/server/src/server/db.rs similarity index 98% rename from burrow/src/auth/server/db.rs rename to server/src/server/db.rs index 09664a7..50516b6 100644 --- a/burrow/src/auth/server/db.rs +++ b/server/src/server/db.rs @@ -1,7 +1,5 @@ use anyhow::Result; -use crate::daemon::rpc::grpc_defs::{Network, NetworkType}; - pub static PATH: &str = "./server.sqlite3"; pub fn init_db() -> Result<()> { diff --git a/burrow/src/auth/server/grpc_defs.rs b/server/src/server/grpc_defs.rs similarity index 100% rename from burrow/src/auth/server/grpc_defs.rs rename to server/src/server/grpc_defs.rs diff --git a/burrow/src/auth/server/grpc_server.rs b/server/src/server/grpc_server.rs similarity index 83% rename from burrow/src/auth/server/grpc_server.rs rename to server/src/server/grpc_server.rs index 4bc6ae6..3061e7a 100644 --- a/burrow/src/auth/server/grpc_server.rs +++ b/server/src/server/grpc_server.rs @@ -2,13 +2,12 @@ use std::sync::Arc; use tonic::{Request, Response, Status}; -use crate::auth::server::providers::{KeypairT, OpenIdUser}; +use super::providers::{KeypairT, OpenIdUser}; use super::{ grpc_defs::{ - burrowwebrpc::burrow_web_server::{BurrowWeb, BurrowWebServer}, - CreateDeviceRequest, CreateDeviceResponse, Empty, JwtInfo, ListDevicesResponse, - SlackAuthRequest, + burrowwebrpc::burrow_web_server::BurrowWeb, CreateDeviceRequest, CreateDeviceResponse, + Empty, JwtInfo, ListDevicesResponse, SlackAuthRequest, }, providers::slack::auth, settings::BurrowAuthServerConfig, diff --git a/burrow/src/auth/server/mod.rs b/server/src/server/mod.rs similarity index 77% rename from burrow/src/auth/server/mod.rs rename to server/src/server/mod.rs index 4fec23d..7c8cdd8 100644 --- a/burrow/src/auth/server/mod.rs +++ b/server/src/server/mod.rs @@ -5,29 +5,16 @@ pub mod providers; pub mod settings; use anyhow::Result; -use axum::{http::StatusCode, routing::post, Router}; use providers::slack::auth; use tokio::signal; pub async fn serve() -> Result<()> { db::init_db()?; - - let app = Router::new().route("/device/new", post(device_new)); - let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap(); log::info!("Starting auth server on port 8080"); - axum::serve(listener, app) - .with_graceful_shutdown(shutdown_signal()) - .await - .unwrap(); - Ok(()) } -async fn device_new() -> StatusCode { - StatusCode::OK -} - async fn shutdown_signal() { let ctrl_c = async { signal::ctrl_c() diff --git a/server/src/server/providers/mod.rs b/server/src/server/providers/mod.rs new file mode 100644 index 0000000..b9bfe88 --- /dev/null +++ b/server/src/server/providers/mod.rs @@ -0,0 +1,66 @@ +pub mod slack; +use self::grpc_defs::JwtInfo; + +pub use super::{db, grpc_defs, settings::BurrowAuthServerConfig}; +use anyhow::{anyhow, Result}; +use jwt_simple::{ + claims::{Claims, NoCustomClaims}, + prelude::{Duration, Ed25519KeyPair, EdDSAKeyPairLike, EdDSAPublicKeyLike}, +}; +use serde::{Deserialize, Serialize}; + +pub type KeypairT = Ed25519KeyPair; + +#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)] +pub struct OpenIdUser { + pub sub: String, + pub name: String, +} + +#[derive(Serialize, Deserialize, Debug)] +struct OpenIDCustomField { + pub name: String, +} + +impl OpenIdUser { + pub fn try_from_jwt(jwt_info: &JwtInfo, keypair: &KeypairT) -> Result { + let claims = keypair + .public_key() + .verify_token::(&jwt_info.jwt, None)?; + Ok(Self { + sub: claims.subject.ok_or(anyhow!("No Subject!"))?, + name: claims.custom.name, + }) + } +} + +impl JwtInfo { + fn try_from_oid(oid_user: OpenIdUser, keypair: &KeypairT) -> Result { + let claims = Claims::with_custom_claims( + OpenIDCustomField { name: oid_user.name }, + Duration::from_days(10), + ) + .with_subject(oid_user.sub); + let jwt = keypair.sign(claims)?; + Ok(Self { jwt }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_jwt() -> Result<()> { + let key_pair = Ed25519KeyPair::generate(); + let sample_usr = OpenIdUser { + sub: "Spanish".into(), + name: "Inquisition".into(), + }; + let encoded = JwtInfo::try_from_oid(sample_usr.clone(), &key_pair)?; + println!("{}", encoded.jwt); + let decoded = OpenIdUser::try_from_jwt(&encoded, &key_pair)?; + assert_eq!(decoded, sample_usr); + Ok(()) + } +} diff --git a/burrow/src/auth/server/providers/slack.rs b/server/src/server/providers/slack.rs similarity index 97% rename from burrow/src/auth/server/providers/slack.rs rename to server/src/server/providers/slack.rs index 38fbfe1..e6a4694 100644 --- a/burrow/src/auth/server/providers/slack.rs +++ b/server/src/server/providers/slack.rs @@ -1,9 +1,4 @@ use anyhow::Result; -use axum::{ - extract::Json, - http::StatusCode, - routing::{get, post}, -}; use reqwest::header::AUTHORIZATION; use serde::Deserialize; diff --git a/burrow/src/auth/server/settings.rs b/server/src/server/settings.rs similarity index 100% rename from burrow/src/auth/server/settings.rs rename to server/src/server/settings.rs