diff --git a/rust/auth-impls/src/jwt.rs b/rust/auth-impls/src/jwt.rs index 7bffb98..f06e4c7 100644 --- a/rust/auth-impls/src/jwt.rs +++ b/rust/auth-impls/src/jwt.rs @@ -34,8 +34,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 1c5e88d..9092ff2 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; @@ -24,8 +23,7 @@ use api::kv_store::KvStore; use auth_impls::jwt::JWTAuthorizer; #[cfg(feature = "sigs")] use auth_impls::signature::SignatureValidatingAuthorizer; -use impls::postgres_store::{Certificate, PostgresPlaintextBackend, PostgresTlsBackend}; -use util::config::{Config, ServerConfig}; +use impls::postgres_store::{PostgresPlaintextBackend, PostgresTlsBackend}; use vss_service::VssService; mod util; @@ -33,26 +31,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), @@ -74,23 +58,14 @@ fn main() { let mut authorizer: Option> = None; #[cfg(feature = "jwt")] { - 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)); - if let Some(pem) = rsa_pem { - authorizer = match JWTAuthorizer::new(pem.as_str()).await { + if let Some(rsa_pem) = config.rsa_pem { + authorizer = match JWTAuthorizer::new(&rsa_pem).await { Ok(auth) => { println!("Configured JWT authorizer with RSA public key"); Some(Arc::new(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); }, }; @@ -110,52 +85,47 @@ fn main() { Arc::new(NoopAuthorizer {}) }; - 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..3236941 100644 --- a/rust/server/src/util/config.rs +++ b/rust/server/src/util/config.rs @@ -1,57 +1,159 @@ 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, +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"; + +// The structure of the toml config file. Any settings specified therein can be overriden by the corresponding +// environment variable. +#[derive(Deserialize, Default)] +struct TomlConfig { + 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, } #[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, -} - -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) +struct TlsConfig { + crt_pem: Option, +} + +// Encapsulates the result of reading both the environment variables and the config file. +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>, +} + +#[inline] +fn read_env(env_var: &str) -> Result, String> { + match std::env::var(env_var) { + Ok(env) => Ok(Some(env)), + Err(std::env::VarError::NotPresent) => Ok(None), + Err(e) => Err(format!("Failed to load the {} environment variable: {}", env_var, e)), } } -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) +#[inline] +fn read_config<'a, T: std::fmt::Display>( + env: Option, config: Option, item: &str, var_name: &str, +) -> Result { + env.or(config).ok_or(format!( + "{} must be provided in the configuration file or the environment variable {} must be set.", + item, var_name + )) +} + +pub(crate) fn load_configuration(config_file_path: Option<&str>) -> Result { + let TomlConfig { server_config, jwt_auth_config, postgresql_config } = match config_file_path { + Some(path) => { + let config_file = std::fs::read_to_string(path) + .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))? + }, + None => TomlConfig::default(), // All fields are set to `None` + }; + + 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..7a80dff 100644 --- a/rust/server/vss-server-config.toml +++ b/rust/server/vss-server-config.toml @@ -1,27 +1,27 @@ [server_config] -host = "127.0.0.1" -port = 8080 +bind_address = "127.0.0.1:8080" # Optional in TOML, can be overridden by env var `VSS_BIND_ADDRESS` # 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` +# We first connect to `default_database` to create `vss_database` if it does not exist +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----- +# """