diff --git a/rust/auth-impls/src/lib.rs b/rust/auth-impls/src/lib.rs index 76c8786..8412df9 100644 --- a/rust/auth-impls/src/lib.rs +++ b/rust/auth-impls/src/lib.rs @@ -43,8 +43,8 @@ const BEARER_PREFIX: &str = "Bearer "; impl JWTAuthorizer { /// Creates a new instance of [`JWTAuthorizer`], fails on failure to parse the PEM formatted RSA public key pub async fn new(rsa_pem: &str) -> Result { - let jwt_issuer_key = - DecodingKey::from_rsa_pem(rsa_pem.as_bytes()).map_err(|e| e.to_string())?; + let jwt_issuer_key = DecodingKey::from_rsa_pem(rsa_pem.as_bytes()) + .map_err(|e| format!("Failed to parse the PEM formatted RSA public key: {}", e))?; Ok(Self { jwt_issuer_key }) } } diff --git a/rust/impls/src/postgres_store.rs b/rust/impls/src/postgres_store.rs index 4424a00..3bc176c 100644 --- a/rust/impls/src/postgres_store.rs +++ b/rust/impls/src/postgres_store.rs @@ -64,14 +64,16 @@ pub type PostgresPlaintextBackend = PostgresBackend; /// A postgres backend with TLS connections to the database pub type PostgresTlsBackend = PostgresBackend; -async fn make_postgres_db_connection(postgres_endpoint: &str, tls: T) -> Result +async fn make_db_connection( + postgres_endpoint: &str, db_name: &str, tls: T, +) -> Result where T: MakeTlsConnect + Clone + Send + Sync + 'static, T::Stream: Send + Sync, T::TlsConnect: Send, <>::TlsConnect as TlsConnect>::Future: Send, { - let dsn = format!("{}/{}", postgres_endpoint, "postgres"); + let dsn = format!("{}/{}", postgres_endpoint, db_name); let (client, connection) = tokio_postgres::connect(&dsn, tls) .await .map_err(|e| Error::new(ErrorKind::Other, format!("Connection error: {}", e)))?; @@ -84,8 +86,8 @@ where Ok(client) } -async fn initialize_vss_database( - postgres_endpoint: &str, db_name: &str, tls: T, +async fn create_database( + postgres_endpoint: &str, default_db: &str, db_name: &str, tls: T, ) -> Result<(), Error> where T: MakeTlsConnect + Clone + Send + Sync + 'static, @@ -93,7 +95,7 @@ where T::TlsConnect: Send, <>::TlsConnect as TlsConnect>::Future: Send, { - let client = make_postgres_db_connection(&postgres_endpoint, tls).await?; + let client = make_db_connection(postgres_endpoint, default_db, tls).await?; let num_rows = client.execute(CHECK_DB_STMT, &[&db_name]).await.map_err(|e| { Error::new( @@ -113,14 +115,16 @@ where } #[cfg(test)] -async fn drop_database(postgres_endpoint: &str, db_name: &str, tls: T) -> Result<(), Error> +async fn drop_database( + postgres_endpoint: &str, default_db: &str, db_name: &str, tls: T, +) -> Result<(), Error> where T: MakeTlsConnect + Clone + Send + Sync + 'static, T::Stream: Send + Sync, T::TlsConnect: Send, <>::TlsConnect as TlsConnect>::Future: Send, { - let client = make_postgres_db_connection(&postgres_endpoint, tls).await?; + let client = make_db_connection(postgres_endpoint, default_db, tls).await?; let drop_database_statement = format!("{} {};", DROP_DB_CMD, db_name); let num_rows = client.execute(&drop_database_statement, &[]).await.map_err(|e| { @@ -133,25 +137,38 @@ where impl PostgresPlaintextBackend { /// Constructs a [`PostgresPlaintextBackend`] using `postgres_endpoint` for PostgreSQL connection information. - pub async fn new(postgres_endpoint: &str, db_name: &str) -> Result { - PostgresBackend::new_internal(postgres_endpoint, db_name, NoTls).await + pub async fn new( + postgres_endpoint: &str, default_db: &str, vss_db: &str, + ) -> Result { + PostgresBackend::new_internal(postgres_endpoint, default_db, vss_db, NoTls).await } } impl PostgresTlsBackend { /// Constructs a [`PostgresTlsBackend`] using `postgres_endpoint` for PostgreSQL connection information. pub async fn new( - postgres_endpoint: &str, db_name: &str, additional_certificate: Option, + postgres_endpoint: &str, default_db: &str, vss_db: &str, crt_pem: Option<&str>, ) -> Result { let mut builder = TlsConnector::builder(); - if let Some(cert) = additional_certificate { - builder.add_root_certificate(cert); + if let Some(pem) = crt_pem { + let crt = Certificate::from_pem(pem.as_bytes()).map_err(|e| { + Error::new( + ErrorKind::Other, + format!("Failed to parse the PEM formatted certificate: {}", e), + ) + })?; + builder.add_root_certificate(crt); } let connector = builder.build().map_err(|e| { Error::new(ErrorKind::Other, format!("Error building tls connector: {}", e)) })?; - PostgresBackend::new_internal(postgres_endpoint, db_name, MakeTlsConnector::new(connector)) - .await + PostgresBackend::new_internal( + postgres_endpoint, + default_db, + vss_db, + MakeTlsConnector::new(connector), + ) + .await } } @@ -162,9 +179,11 @@ where T::TlsConnect: Send, <>::TlsConnect as TlsConnect>::Future: Send, { - async fn new_internal(postgres_endpoint: &str, db_name: &str, tls: T) -> Result { - initialize_vss_database(postgres_endpoint, db_name, tls.clone()).await?; - let vss_dsn = format!("{}/{}", postgres_endpoint, db_name); + async fn new_internal( + postgres_endpoint: &str, default_db: &str, vss_db: &str, tls: T, + ) -> Result { + create_database(postgres_endpoint, default_db, vss_db, tls.clone()).await?; + let vss_dsn = format!("{}/{}", postgres_endpoint, vss_db); let manager = PostgresConnectionManager::new_from_stringlike(vss_dsn, tls).map_err(|e| { Error::new( @@ -649,24 +668,27 @@ mod tests { use tokio_postgres::NoTls; const POSTGRES_ENDPOINT: &str = "postgresql://postgres:postgres@localhost:5432"; + const DEFAULT_DB: &str = "postgres"; const MIGRATIONS_START: usize = 0; const MIGRATIONS_END: usize = MIGRATIONS.len(); static START: OnceCell<()> = OnceCell::const_new(); define_kv_store_tests!(PostgresKvStoreTest, PostgresPlaintextBackend, { - let db_name = "postgres_kv_store_tests"; + let vss_db = "postgres_kv_store_tests"; START .get_or_init(|| async { - let _ = drop_database(POSTGRES_ENDPOINT, db_name, NoTls).await; - let store = - PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let _ = drop_database(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db, NoTls).await; + let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db) + .await + .unwrap(); let (start, end) = store.migrate_vss_database(MIGRATIONS).await.unwrap(); assert_eq!(start, MIGRATIONS_START); assert_eq!(end, MIGRATIONS_END); }) .await; - let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let store = + PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db).await.unwrap(); let (start, end) = store.migrate_vss_database(MIGRATIONS).await.unwrap(); assert_eq!(start, MIGRATIONS_END); assert_eq!(end, MIGRATIONS_END); @@ -678,28 +700,31 @@ mod tests { #[tokio::test] #[should_panic(expected = "We do not allow downgrades")] async fn panic_on_downgrade() { - let db_name = "panic_on_downgrade_test"; - let _ = drop_database(POSTGRES_ENDPOINT, db_name, NoTls).await; + let vss_db = "panic_on_downgrade_test"; + let _ = drop_database(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db, NoTls).await; { let mut migrations = MIGRATIONS.to_vec(); migrations.push(DUMMY_MIGRATION); - let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let store = + PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db).await.unwrap(); let (start, end) = store.migrate_vss_database(&migrations).await.unwrap(); assert_eq!(start, MIGRATIONS_START); assert_eq!(end, MIGRATIONS_END + 1); }; { - let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let store = + PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db).await.unwrap(); let _ = store.migrate_vss_database(MIGRATIONS).await.unwrap(); }; } #[tokio::test] async fn new_migrations_increments_upgrades() { - let db_name = "new_migrations_increments_upgrades_test"; - let _ = drop_database(POSTGRES_ENDPOINT, db_name, NoTls).await; + let vss_db = "new_migrations_increments_upgrades_test"; + let _ = drop_database(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db, NoTls).await; { - let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let store = + PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db).await.unwrap(); let (start, end) = store.migrate_vss_database(MIGRATIONS).await.unwrap(); assert_eq!(start, MIGRATIONS_START); assert_eq!(end, MIGRATIONS_END); @@ -707,7 +732,8 @@ mod tests { assert_eq!(store.get_schema_version().await, MIGRATIONS_END); }; { - let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let store = + PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db).await.unwrap(); let (start, end) = store.migrate_vss_database(MIGRATIONS).await.unwrap(); assert_eq!(start, MIGRATIONS_END); assert_eq!(end, MIGRATIONS_END); @@ -718,7 +744,8 @@ mod tests { let mut migrations = MIGRATIONS.to_vec(); migrations.push(DUMMY_MIGRATION); { - let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let store = + PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db).await.unwrap(); let (start, end) = store.migrate_vss_database(&migrations).await.unwrap(); assert_eq!(start, MIGRATIONS_END); assert_eq!(end, MIGRATIONS_END + 1); @@ -729,7 +756,8 @@ mod tests { migrations.push(DUMMY_MIGRATION); migrations.push(DUMMY_MIGRATION); { - let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let store = + PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db).await.unwrap(); let (start, end) = store.migrate_vss_database(&migrations).await.unwrap(); assert_eq!(start, MIGRATIONS_END + 1); assert_eq!(end, MIGRATIONS_END + 3); @@ -741,13 +769,14 @@ mod tests { }; { - let store = PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, db_name).await.unwrap(); + let store = + PostgresPlaintextBackend::new(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db).await.unwrap(); let list = store.get_upgrades_list().await; assert_eq!(list, [MIGRATIONS_START, MIGRATIONS_END, MIGRATIONS_END + 1]); let version = store.get_schema_version().await; assert_eq!(version, MIGRATIONS_END + 3); } - drop_database(POSTGRES_ENDPOINT, db_name, NoTls).await.unwrap(); + drop_database(POSTGRES_ENDPOINT, DEFAULT_DB, vss_db, NoTls).await.unwrap(); } } diff --git a/rust/server/src/main.rs b/rust/server/src/main.rs index 7d56343..1e8f699 100644 --- a/rust/server/src/main.rs +++ b/rust/server/src/main.rs @@ -9,7 +9,6 @@ #![deny(rustdoc::private_intra_doc_links)] #![deny(missing_docs)] -use std::net::SocketAddr; use std::sync::Arc; use tokio::net::TcpListener; @@ -21,8 +20,7 @@ use hyper_util::rt::TokioIo; use api::auth::{Authorizer, NoopAuthorizer}; use api::kv_store::KvStore; use auth_impls::JWTAuthorizer; -use impls::postgres_store::{Certificate, PostgresPlaintextBackend, PostgresTlsBackend}; -use util::config::{Config, ServerConfig}; +use impls::postgres_store::{PostgresPlaintextBackend, PostgresTlsBackend}; use vss_service::VssService; mod util; @@ -30,26 +28,12 @@ mod vss_service; fn main() { let args: Vec = std::env::args().collect(); - if args.len() != 2 { - eprintln!("Usage: {} ", args[0]); - std::process::exit(1); - } - let Config { server_config: ServerConfig { host, port }, jwt_auth_config, postgresql_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!("{}:{}", host, port).parse() { - Ok(addr) => addr, - Err(e) => { - eprintln!("Invalid host/port configuration: {}", e); - std::process::exit(1); - }, - }; + let config = + util::config::load_configuration(args.get(1).map(|s| s.as_str())).unwrap_or_else(|e| { + eprintln!("Failed to load configuration: {}", e); + std::process::exit(-1); + }); let runtime = match tokio::runtime::Builder::new_multi_thread().enable_all().build() { Ok(runtime) => Arc::new(runtime), @@ -68,76 +52,63 @@ fn main() { }, }; - let rsa_pem_env = match std::env::var("VSS_JWT_RSA_PEM") { - Ok(env) => Some(env), - Err(std::env::VarError::NotPresent) => None, - Err(e) => { - println!("Failed to load the VSS_JWT_RSA_PEM env var: {}", e); - std::process::exit(-1); - }, - }; - let rsa_pem = rsa_pem_env.or(jwt_auth_config.map(|config| config.rsa_pem)); - let authorizer: Arc = if let Some(pem) = rsa_pem { - let authorizer = match JWTAuthorizer::new(pem.as_str()).await { + let authorizer: Arc = if let Some(rsa_pem) = config.rsa_pem { + let jwt_authorizer = match JWTAuthorizer::new(&rsa_pem).await { Ok(auth) => auth, Err(e) => { - println!("Failed to parse the PEM formatted RSA public key: {}", e); + println!("Failed to configure JWT authorizer: {}", e); std::process::exit(-1); }, }; println!("Configured JWT authorizer with RSA public key"); - Arc::new(authorizer) + Arc::new(jwt_authorizer) } else { - println!("No JWT authentication method configured"); - Arc::new(NoopAuthorizer {}) + let noop_authorizer = NoopAuthorizer {}; + println!("No authentication method configured"); + Arc::new(noop_authorizer) }; - let postgresql_config = - 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 { - let additional_certificate = tls_config.ca_file.map(|file| { - let certificate = match std::fs::read(&file) { - Ok(cert) => cert, - Err(e) => { - println!("Failed to read certificate file: {}", e); - std::process::exit(-1); - }, - }; - match Certificate::from_pem(&certificate) { - Ok(cert) => cert, - Err(e) => { - println!("Failed to parse certificate file: {}", e); - std::process::exit(-1); - }, - } + let store: Arc = if let Some(crt_pem) = config.tls_config { + let postgres_tls_backend = PostgresTlsBackend::new( + &config.postgresql_prefix, + &config.default_db, + &config.vss_db, + crt_pem.as_deref(), + ) + .await + .unwrap_or_else(|e| { + println!("Failed to start postgres TLS backend: {}", e); + std::process::exit(-1); }); - let postgres_tls_backend = - match PostgresTlsBackend::new(&endpoint, &db_name, additional_certificate).await { - Ok(backend) => backend, - Err(e) => { - println!("Failed to start postgres tls backend: {}", e); - std::process::exit(-1); - }, - }; + println!( + "Connected to PostgreSQL TLS backend with DSN: {}/{}", + config.postgresql_prefix, config.vss_db + ); Arc::new(postgres_tls_backend) } else { - let postgres_plaintext_backend = - match PostgresPlaintextBackend::new(&endpoint, &db_name).await { - Ok(backend) => backend, - Err(e) => { - println!("Failed to start postgres plaintext backend: {}", e); - std::process::exit(-1); - }, - }; + let postgres_plaintext_backend = PostgresPlaintextBackend::new( + &config.postgresql_prefix, + &config.default_db, + &config.vss_db, + ) + .await + .unwrap_or_else(|e| { + println!("Failed to start postgres plaintext backend: {}", e); + std::process::exit(-1); + }); + println!( + "Connected to PostgreSQL plaintext backend with DSN: {}/{}", + config.postgresql_prefix, config.vss_db + ); 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); + let rest_svc_listener = TcpListener::bind(&config.bind_address).await.unwrap_or_else(|e| { + println!("Failed to bind listening port: {}", e); + std::process::exit(-1); + }); + println!("Listening for incoming connections on {}", config.bind_address); + loop { tokio::select! { res = rest_svc_listener.accept() => { diff --git a/rust/server/src/util/config.rs b/rust/server/src/util/config.rs index 1f920c6..fff5b6b 100644 --- a/rust/server/src/util/config.rs +++ b/rust/server/src/util/config.rs @@ -1,57 +1,164 @@ use serde::Deserialize; +use std::net::SocketAddr; -#[derive(Deserialize)] -pub(crate) struct Config { - pub(crate) server_config: ServerConfig, - pub(crate) jwt_auth_config: Option, - pub(crate) postgresql_config: Option, +#[derive(Deserialize, Default)] +struct Config { + server_config: Option, + jwt_auth_config: Option, + postgresql_config: Option, } #[derive(Deserialize)] -pub(crate) struct ServerConfig { - pub(crate) host: String, - pub(crate) port: u16, +struct ServerConfig { + bind_address: Option, } #[derive(Deserialize)] -pub(crate) struct JwtAuthConfig { - pub(crate) rsa_pem: String, +struct JwtAuthConfig { + rsa_pem: Option, } +const BIND_ADDR_VAR: &str = "VSS_BIND_ADDRESS"; +const JWT_RSA_PEM_VAR: &str = "VSS_JWT_RSA_PEM"; +const PSQL_USER_VAR: &str = "VSS_PSQL_USERNAME"; +const PSQL_PASS_VAR: &str = "VSS_PSQL_PASSWORD"; +const PSQL_ADDR_VAR: &str = "VSS_PSQL_ADDRESS"; +const PSQL_DB_VAR: &str = "VSS_PSQL_DEFAULT_DB"; +const PSQL_VSS_DB_VAR: &str = "VSS_PSQL_VSS_DB"; +const PSQL_TLS_VAR: &str = "VSS_PSQL_TLS"; +const PSQL_CERT_PEM_VAR: &str = "VSS_PSQL_CRT_PEM"; + #[derive(Deserialize)] -pub(crate) struct PostgreSQLConfig { - pub(crate) username: Option, // Optional in TOML, can be overridden by env - pub(crate) password: Option, // Optional in TOML, can be overridden by env - pub(crate) host: String, - pub(crate) port: u16, - pub(crate) database: String, - pub(crate) tls: Option, +struct PostgreSQLConfig { + username: Option, + password: Option, + address: Option, + default_database: Option, + vss_database: Option, + tls: Option, } #[derive(Deserialize)] -pub(crate) struct TlsConfig { - pub(crate) ca_file: Option, +struct TlsConfig { + crt_pem: Option, } -impl PostgreSQLConfig { - pub(crate) fn to_postgresql_endpoint(&self) -> String { - let username_env = std::env::var("VSS_POSTGRESQL_USERNAME"); - let username = username_env.as_ref() - .ok() - .or_else(|| self.username.as_ref()) - .expect("PostgreSQL database username must be provided in config or env var VSS_POSTGRESQL_USERNAME must be set."); - let password_env = std::env::var("VSS_POSTGRESQL_PASSWORD"); - let password = password_env.as_ref() - .ok() - .or_else(|| self.password.as_ref()) - .expect("PostgreSQL database password must be provided in config or env var VSS_POSTGRESQL_PASSWORD must be set."); - - format!("postgresql://{}:{}@{}:{}", username, password, self.host, self.port) - } +pub(crate) struct Configuration { + pub(crate) bind_address: SocketAddr, + pub(crate) rsa_pem: Option, + pub(crate) postgresql_prefix: String, + pub(crate) default_db: String, + pub(crate) vss_db: String, + pub(crate) tls_config: Option>, } -pub(crate) fn load_config(config_path: &str) -> Result> { - let config_str = std::fs::read_to_string(config_path)?; - let config: Config = toml::from_str(&config_str)?; - Ok(config) +pub(crate) fn load_configuration(config_file_path: Option<&str>) -> Result { + let Config { server_config, jwt_auth_config, postgresql_config } = if config_file_path.is_some() + && std::fs::exists(config_file_path.expect("config file path is some")) + .map_err(|e| format!("Failed to check presence of configuration file: {}", e))? + { + let config_file = + std::fs::read_to_string(config_file_path.expect("config file path is some")) + .map_err(|e| format!("Failed to read configuration file: {}", e))?; + toml::from_str(&config_file) + .map_err(|e| format!("Failed to parse configuration file: {}", e))? + } else { + Config::default() // All fields are set to `None` + }; + + macro_rules! read_env { + ($env_var:expr) => { + match std::env::var($env_var) { + Ok(env) => Some(env), + Err(std::env::VarError::NotPresent) => None, + Err(e) => { + return Err(format!( + "Failed to load the {} environment variable: {}", + $env_var, e + )) + }, + } + }; + } + + macro_rules! read_config { + ($env:expr, $config: expr, $item: expr, $var_name: expr) => { + $env.or($config).ok_or(format!( + "{} must be provided in the configuration file or the environment variable {} must be set.", + $item, $var_name + ))? + }; + } + + let bind_address_env = read_env!(BIND_ADDR_VAR) + .map(|addr| { + addr.parse().map_err(|e| { + format!("Unable to parse the bind address environment variable: {}", e) + }) + }) + .transpose()?; + let bind_address = read_config!( + bind_address_env, + server_config.and_then(|c| c.bind_address), + "VSS server bind address", + BIND_ADDR_VAR + ); + + let rsa_pem_env = read_env!(JWT_RSA_PEM_VAR); + let rsa_pem = rsa_pem_env.or(jwt_auth_config.and_then(|config| config.rsa_pem)); + + let username_env = read_env!(PSQL_USER_VAR); + let password_env = read_env!(PSQL_PASS_VAR); + let address_env: Option = read_env!(PSQL_ADDR_VAR) + .map(|address| { + address.parse().map_err(|e| { + format!("Unable to parse the postgresql address environment variable: {}", e) + }) + }) + .transpose()?; + let default_db_env = read_env!(PSQL_DB_VAR); + let vss_db_env = read_env!(PSQL_VSS_DB_VAR); + let tls_config_env = read_env!(PSQL_TLS_VAR); + let crt_pem_env = read_env!(PSQL_CERT_PEM_VAR); + + let ( + username_config, + password_config, + address_config, + default_db_config, + vss_db_config, + tls_config, + ) = match postgresql_config { + Some(c) => ( + c.username, + c.password, + c.address, + c.default_database, + c.vss_database, + c.tls.map(|tls| tls.crt_pem), + ), + None => (None, None, None, None, None, None), + }; + + let username = + read_config!(username_env, username_config, "PostgreSQL database username", PSQL_USER_VAR); + let password = + read_config!(password_env, password_config, "PostgreSQL database password", PSQL_PASS_VAR); + let address = + read_config!(address_env, address_config, "PostgreSQL service address", PSQL_ADDR_VAR); + let default_db = read_config!( + default_db_env, + default_db_config, + "PostgreSQL default database name", + PSQL_DB_VAR + ); + let vss_db = + read_config!(vss_db_env, vss_db_config, "PostgreSQL vss database name", PSQL_VSS_DB_VAR); + + let tls_config = + crt_pem_env.map(|pem| Some(pem)).or(tls_config_env.map(|_| None)).or(tls_config); + + let postgresql_prefix = format!("postgresql://{}:{}@{}", username, password, address); + + Ok(Configuration { bind_address, rsa_pem, postgresql_prefix, default_db, vss_db, tls_config }) } diff --git a/rust/server/vss-server-config.toml b/rust/server/vss-server-config.toml index c42a906..838252e 100644 --- a/rust/server/vss-server-config.toml +++ b/rust/server/vss-server-config.toml @@ -1,27 +1,26 @@ [server_config] -host = "127.0.0.1" -port = 8080 +bind_address = "127.0.0.1:8080" # Uncomment the table below to verify JWT tokens in the HTTP Authorization header against the given RSA public key, # can be overridden by env var `VSS_JWT_RSA_PEM` # [jwt_auth_config] # rsa_pem = """ # -----BEGIN PUBLIC KEY----- -# MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAstPJs4ut+tFAI0qrOyGt -# /3FN5jWc5gLv/j9Rc6lgr4hm7lyR05PU/G+4rfxdXGNyGTlQ6dRqcVy78CjxWz9f -# 8l08EKLERPh8JhE5el6vr+ehWD5iQxSP3ejpx0Mr977fKMNKg6jlFiL+y50hOEp2 -# 6iN9QzZQjLxotDT3aQvbCA/DZpI+fV6WKDKWGS+pZGDVgOz5x/RcStJQXxkX3ACK -# WhVdrtN3h6mHlhIt7ZIqVvQmY4NL03QPyljt13sYHoiFaoxINF/funBMCjrfSLcB -# ko1rWE2BWdOrFqi27RtBs5AHOSAWXuz/2SUGpFuTQuJi7U68QUfjKeQO46JpQf+v -# kQIDAQAB # -----END PUBLIC KEY----- # """ [postgresql_config] -username = "postgres" # Optional in TOML, can be overridden by env var `VSS_POSTGRESQL_USERNAME` -password = "postgres" # Optional in TOML, can be overridden by env var `VSS_POSTGRESQL_PASSWORD` -host = "localhost" -port = 5432 -database = "postgres" -# tls = { } # Uncomment to make TLS connections to the postgres database using your machine's PKI -# tls = { ca_file = "ca.pem" } # Uncomment to make TLS connections to the postgres database with an additional root certificate +username = "postgres" # Optional in TOML, can be overridden by env var `VSS_PSQL_USERNAME` +password = "postgres" # Optional in TOML, can be overridden by env var `VSS_PSQL_PASSWORD` +address = "127.0.0.1:5432" # Optional in TOML, can be overridden by env var `VSS_PSQL_ADDRESS` +default_database = "postgres" # Optional in TOML, can be overridden by env var `VSS_PSQL_DEFAULT_DB` +vss_database = "vss" # Optional in TOML, can be overridden by env var `VSS_PSQL_VSS_DB` + +# [postgresql_config.tls] # Uncomment, or set env var `VSS_PSQL_TLS` to make TLS connections to the postgres database +# +# Uncomment the lines below, or set `VSS_PSQL_CRT_PEM`, to add a root certificate to your trusted root certificates +# +# crt_pem = """ +# -----BEGIN CERTIFICATE----- +# -----END CERTIFICATE----- +# """