diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 6c37e11..4e32722 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1981,6 +1981,7 @@ name = "vss-server" version = "0.1.0" dependencies = [ "api", + "auth-impls", "bytes", "http-body-util", "hyper 1.4.1", diff --git a/rust/auth-impls/src/lib.rs b/rust/auth-impls/src/lib.rs index 86c6853..2bc0fb3 100644 --- a/rust/auth-impls/src/lib.rs +++ b/rust/auth-impls/src/lib.rs @@ -14,10 +14,12 @@ use api::auth::{AuthResponse, Authorizer}; use api::error::VssError; use async_trait::async_trait; -use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; +use jsonwebtoken::{decode, Algorithm, Validation}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +pub use jsonwebtoken::DecodingKey; + /// A JWT based authorizer, only allows requests with verified 'JsonWebToken' signed by the given /// issuer key. /// diff --git a/rust/server/Cargo.toml b/rust/server/Cargo.toml index 2a0e6f1..6c66812 100644 --- a/rust/server/Cargo.toml +++ b/rust/server/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] api = { path = "../api" } +auth-impls = { path = "../auth-impls" } impls = { path = "../impls" } hyper = { version = "1", default-features = false, features = ["server", "http1"] } diff --git a/rust/server/src/main.rs b/rust/server/src/main.rs index 38fdccd..9f08b4c 100644 --- a/rust/server/src/main.rs +++ b/rust/server/src/main.rs @@ -20,11 +20,14 @@ use hyper_util::rt::TokioIo; use crate::vss_service::VssService; use api::auth::{Authorizer, NoopAuthorizer}; use api::kv_store::KvStore; +use auth_impls::{DecodingKey, JWTAuthorizer}; use impls::postgres_store::{Certificate, PostgresPlaintextBackend, PostgresTlsBackend}; use std::sync::Arc; -pub(crate) mod util; -pub(crate) mod vss_service; +mod util; +mod vss_service; + +use util::config::{Config, ServerConfig}; fn main() { let args: Vec = std::env::args().collect(); @@ -33,22 +36,21 @@ fn main() { std::process::exit(1); } - let config = match util::config::load_config(&args[1]) { - Ok(cfg) => cfg, - Err(e) => { - eprintln!("Failed to load configuration: {}", e); - std::process::exit(1); - }, - }; - - let addr: SocketAddr = - match format!("{}:{}", config.server_config.host, config.server_config.port).parse() { - Ok(addr) => addr, + let Config { server_config: ServerConfig { host, port, rsa_pub_file_path }, postgresql_config } = + match util::config::load_config(&args[1]) { + Ok(cfg) => cfg, Err(e) => { - eprintln!("Invalid host/port configuration: {}", e); + eprintln!("Failed to load configuration: {}", e); std::process::exit(1); }, }; + let addr: SocketAddr = match format!("{}:{}", host, port).parse() { + Ok(addr) => addr, + Err(e) => { + eprintln!("Invalid host/port configuration: {}", e); + std::process::exit(1); + }, + }; let runtime = match tokio::runtime::Builder::new_multi_thread().enable_all().build() { Ok(runtime) => Arc::new(runtime), @@ -66,9 +68,29 @@ fn main() { std::process::exit(-1); }, }; - let authorizer: Arc = Arc::new(NoopAuthorizer {}); + + let authorizer: Arc = if let Some(file_path) = rsa_pub_file_path { + let rsa_pub_file = match std::fs::read(file_path) { + Ok(pem) => pem, + Err(e) => { + println!("Failed to read RSA public key file: {}", e); + std::process::exit(-1); + }, + }; + let rsa_public_key = match DecodingKey::from_rsa_pem(&rsa_pub_file) { + Ok(pem) => pem, + Err(e) => { + println!("Failed to parse RSA public key file: {}", e); + std::process::exit(-1); + }, + }; + Arc::new(JWTAuthorizer::new(rsa_public_key).await) + } else { + Arc::new(NoopAuthorizer {}) + }; + let postgresql_config = - config.postgresql_config.expect("PostgreSQLConfig must be defined in config file."); + postgresql_config.expect("PostgreSQLConfig must be defined in config file."); let endpoint = postgresql_config.to_postgresql_endpoint(); let db_name = postgresql_config.database; let store: Arc = if let Some(tls_config) = postgresql_config.tls { @@ -109,6 +131,7 @@ fn main() { Arc::new(postgres_plaintext_backend) }; println!("Connected to PostgreSQL backend with DSN: {}/{}", endpoint, db_name); + let rest_svc_listener = TcpListener::bind(&addr).await.expect("Failed to bind listening port"); println!("Listening for incoming connections on {}", addr); diff --git a/rust/server/src/util/config.rs b/rust/server/src/util/config.rs index 801d1bd..4462c5a 100644 --- a/rust/server/src/util/config.rs +++ b/rust/server/src/util/config.rs @@ -10,6 +10,7 @@ pub(crate) struct Config { pub(crate) struct ServerConfig { pub(crate) host: String, pub(crate) port: u16, + pub(crate) rsa_pub_file_path: Option, } #[derive(Deserialize)] diff --git a/rust/server/vss-server-config.toml b/rust/server/vss-server-config.toml index 8c3d9c0..76a4da4 100644 --- a/rust/server/vss-server-config.toml +++ b/rust/server/vss-server-config.toml @@ -1,6 +1,7 @@ [server_config] host = "127.0.0.1" port = 8080 +# rsa_pub_file_path = "rsa_public_key.pem" # Uncomment to verify JWT tokens in the HTTP Authorization header [postgresql_config] username = "postgres" # Optional in TOML, can be overridden by env var `VSS_POSTGRESQL_USERNAME`