Add some base code
This commit is contained in:
		
							
								
								
									
										4
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					# VirtWeb Remote
 | 
				
			||||||
 | 
					WIP project
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This project aims to use the VirtWeb API to start and stop VM without directly exposing the VirtWEB API to the Internet.
 | 
				
			||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
target
 | 
					target
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
							
								
								
									
										2582
									
								
								remote_backend/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2582
									
								
								remote_backend/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										17
									
								
								remote_backend/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								remote_backend/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "remote_backend"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					log = "0.4.21"
 | 
				
			||||||
 | 
					env_logger = "0.11.3"
 | 
				
			||||||
 | 
					clap = { version = "4.5.4", features = ["derive", "env"] }
 | 
				
			||||||
 | 
					serde = { version = "1.0.198", features = ["derive"] }
 | 
				
			||||||
 | 
					light-openid = { version = "1.0.2", features = ["crypto-wrapper"] }
 | 
				
			||||||
 | 
					basic-jwt = "0.2.0"
 | 
				
			||||||
 | 
					actix-remote-ip = "0.1.0"
 | 
				
			||||||
 | 
					lazy_static = "1.4.0"
 | 
				
			||||||
 | 
					actix-web = "4.5.1"
 | 
				
			||||||
							
								
								
									
										143
									
								
								remote_backend/src/app_config.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								remote_backend/src/app_config.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,143 @@
 | 
				
			|||||||
 | 
					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:3000")]
 | 
				
			||||||
 | 
					    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/.well-known/openid-configuration"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    pub oidc_configuration_url: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Disable OpenID authentication
 | 
				
			||||||
 | 
					    #[arg(long, env)]
 | 
				
			||||||
 | 
					    pub disable_oidc: 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)]
 | 
				
			||||||
 | 
					    pub 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)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[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()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								remote_backend/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								remote_backend/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					pub mod app_config;
 | 
				
			||||||
							
								
								
									
										25
									
								
								remote_backend/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								remote_backend/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					use actix_remote_ip::RemoteIPConfig;
 | 
				
			||||||
 | 
					use actix_web::middleware::Logger;
 | 
				
			||||||
 | 
					use actix_web::web::Data;
 | 
				
			||||||
 | 
					use actix_web::{App, HttpServer};
 | 
				
			||||||
 | 
					use light_openid::basic_state_manager::BasicStateManager;
 | 
				
			||||||
 | 
					use remote_backend::app_config::AppConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[actix_web::main]
 | 
				
			||||||
 | 
					async fn main() -> std::io::Result<()> {
 | 
				
			||||||
 | 
					    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let state_manager = Data::new(BasicStateManager::new());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    HttpServer::new(move || {
 | 
				
			||||||
 | 
					        App::new()
 | 
				
			||||||
 | 
					            .wrap(Logger::default())
 | 
				
			||||||
 | 
					            .app_data(state_manager.clone())
 | 
				
			||||||
 | 
					            .app_data(Data::new(RemoteIPConfig {
 | 
				
			||||||
 | 
					                proxy: AppConfig::get().proxy_ip.clone(),
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .bind(&AppConfig::get().listen_address)?
 | 
				
			||||||
 | 
					    .run()
 | 
				
			||||||
 | 
					    .await
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,8 +0,0 @@
 | 
				
			|||||||
[package]
 | 
					 | 
				
			||||||
name = "virtweb_remote"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
edition = "2021"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[dependencies]
 | 
					 | 
				
			||||||
@@ -1,3 +0,0 @@
 | 
				
			|||||||
fn main() {
 | 
					 | 
				
			||||||
    println!("Hello, world!");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user