All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			
		
			
				
	
	
		
			152 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use basic_jwt::JWTPrivateKey;
 | |
| use clap::Parser;
 | |
| 
 | |
| /// VirtWeb backend API
 | |
| #[derive(Parser, Debug, Clone)]
 | |
| #[clap(author, version, about, long_about = None)]
 | |
| pub struct AppConfig {
 | |
|     /// Listen address
 | |
|     #[clap(short, long, env, default_value = "0.0.0.0:8002")]
 | |
|     pub listen_address: String,
 | |
| 
 | |
|     /// Website main origin
 | |
|     #[clap(short, long, env, default_value = "http://localhost:5173")]
 | |
|     pub website_origin: String,
 | |
| 
 | |
|     /// Proxy IP, might end with a star "*"
 | |
|     #[clap(short, long, env)]
 | |
|     pub proxy_ip: Option<String>,
 | |
| 
 | |
|     /// Secret key, used to sign some resources. Must be randomly generated
 | |
|     #[clap(short = 'S', long, env, default_value = "")]
 | |
|     secret: String,
 | |
| 
 | |
|     /// Specify whether the cookie should be transmitted only over secure connections
 | |
|     #[clap(long, env)]
 | |
|     pub cookie_secure: bool,
 | |
| 
 | |
|     /// URL where the OpenID configuration can be found
 | |
|     #[arg(
 | |
|         long,
 | |
|         env,
 | |
|         default_value = "http://localhost:9001/dex/.well-known/openid-configuration"
 | |
|     )]
 | |
|     pub oidc_configuration_url: String,
 | |
| 
 | |
|     /// Disable authentication (for development purposes ONLY)
 | |
|     #[arg(long, env)]
 | |
|     pub unsecure_disable_login: bool,
 | |
| 
 | |
|     /// OpenID client ID
 | |
|     #[arg(long, env, default_value = "foo")]
 | |
|     pub oidc_client_id: String,
 | |
| 
 | |
|     /// OpenID client secret
 | |
|     #[arg(long, env, default_value = "bar")]
 | |
|     pub oidc_client_secret: String,
 | |
| 
 | |
|     /// OpenID login redirect URL
 | |
|     #[arg(long, env, default_value = "APP_ORIGIN/oidc_cb")]
 | |
|     oidc_redirect_url: String,
 | |
| 
 | |
|     /// VirtWeb base URL
 | |
|     #[arg(long, env, default_value = "http://localhost:8000")]
 | |
|     pub virtweb_base_url: String,
 | |
| 
 | |
|     /// VirtWeb API token ID
 | |
|     #[arg(long, env)]
 | |
|     pub virtweb_token_id: String,
 | |
| 
 | |
|     /// VirtWeb API token private key
 | |
|     #[arg(long, env)]
 | |
|     virtweb_token_private_key: String,
 | |
| }
 | |
| 
 | |
| lazy_static::lazy_static! {
 | |
|     static ref ARGS: AppConfig = {
 | |
|         AppConfig::parse()
 | |
|     };
 | |
| }
 | |
| 
 | |
| impl AppConfig {
 | |
|     /// Get parsed command line arguments
 | |
|     pub fn get() -> &'static AppConfig {
 | |
|         &ARGS
 | |
|     }
 | |
| 
 | |
|     /// Get auth cookie domain
 | |
|     pub fn cookie_domain(&self) -> Option<String> {
 | |
|         if cfg!(debug_assertions) {
 | |
|             let domain = self.website_origin.split_once("://")?.1;
 | |
|             Some(
 | |
|                 domain
 | |
|                     .split_once(':')
 | |
|                     .map(|s| s.0)
 | |
|                     .unwrap_or(domain)
 | |
|                     .to_string(),
 | |
|             )
 | |
|         } else {
 | |
|             // In release mode, the web app is hosted on the same origin as the API
 | |
|             None
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Get app secret
 | |
|     pub fn secret(&self) -> &str {
 | |
|         let mut secret = self.secret.as_str();
 | |
| 
 | |
|         if cfg!(debug_assertions) && secret.is_empty() {
 | |
|             secret = "DEBUGKEYDEBUGKEYDEBUGKEYDEBUGKEYDEBUGKEYDEBUGKEYDEBUGKEYDEBUGKEY";
 | |
|         }
 | |
| 
 | |
|         if secret.is_empty() {
 | |
|             panic!("SECRET is undefined or too short (min 64 chars)!")
 | |
|         }
 | |
| 
 | |
|         secret
 | |
|     }
 | |
| 
 | |
|     /// Get OpenID providers configuration
 | |
|     pub fn openid_provider(&self) -> OIDCProvider<'_> {
 | |
|         OIDCProvider {
 | |
|             client_id: self.oidc_client_id.as_str(),
 | |
|             client_secret: self.oidc_client_secret.as_str(),
 | |
|             configuration_url: self.oidc_configuration_url.as_str(),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Get OIDC callback URL
 | |
|     pub fn oidc_redirect_url(&self) -> String {
 | |
|         self.oidc_redirect_url
 | |
|             .replace("APP_ORIGIN", &self.website_origin)
 | |
|     }
 | |
| 
 | |
|     /// Get VirtWeb token private key
 | |
|     pub fn token_private_key(&self) -> JWTPrivateKey {
 | |
|         JWTPrivateKey::ES384 {
 | |
|             r#priv: self.virtweb_token_private_key.to_string(),
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Debug, Clone, serde::Serialize)]
 | |
| pub struct OIDCProvider<'a> {
 | |
|     #[serde(skip_serializing)]
 | |
|     pub client_id: &'a str,
 | |
|     #[serde(skip_serializing)]
 | |
|     pub client_secret: &'a str,
 | |
|     #[serde(skip_serializing)]
 | |
|     pub configuration_url: &'a str,
 | |
| }
 | |
| 
 | |
| #[cfg(test)]
 | |
| mod test {
 | |
|     use crate::app_config::AppConfig;
 | |
| 
 | |
|     #[test]
 | |
|     fn verify_cli() {
 | |
|         use clap::CommandFactory;
 | |
|         AppConfig::command().debug_assert()
 | |
|     }
 | |
| }
 |