🛂 Secured sideload
This commit is contained in:
		
							
								
								
									
										1318
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1318
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										14
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Cargo.toml
									
									
									
									
									
								
							| @@ -9,25 +9,15 @@ edition = "2021" | |||||||
| actix-files = "0.6.5" | actix-files = "0.6.5" | ||||||
| actix-proxy = "0.2.0" | actix-proxy = "0.2.0" | ||||||
| actix-web = "4.5.1" | actix-web = "4.5.1" | ||||||
|  | actix-web-httpauth = "0.8.1" | ||||||
| awc = "3.4.0" | awc = "3.4.0" | ||||||
| config = { version = "0.13.4", features = ["toml"] } | config = { version = "0.14.0", features = ["toml"] } | ||||||
| futures-util = "0.3.30" |  | ||||||
| http = "1.0.0" |  | ||||||
| hyper-util = { version = "0.1.2", features = ["full"] } |  | ||||||
| lazy_static = "1.4.0" | lazy_static = "1.4.0" | ||||||
| mime = "0.3.17" | mime = "0.3.17" | ||||||
| percent-encoding = "2.3.1" | percent-encoding = "2.3.1" | ||||||
| poem = { version = "2.0.0", features = [ |  | ||||||
|   "tokio-metrics", |  | ||||||
|   "websocket", |  | ||||||
|   "static-files", |  | ||||||
|   "reqwest", |  | ||||||
| ] } |  | ||||||
| poem-openapi = { version = "4.0.0" } |  | ||||||
| queryst = "3.0.0" | queryst = "3.0.0" | ||||||
| rand = "0.8.5" | rand = "0.8.5" | ||||||
| regex = "1.10.2" | regex = "1.10.2" | ||||||
| reqwest = { git = "https://github.com/seanmonstar/reqwest.git", branch = "hyper-v1", version = "0.11.23" } |  | ||||||
| serde = "1.0.195" | serde = "1.0.195" | ||||||
| serde_json = "1.0.111" | serde_json = "1.0.111" | ||||||
| tokio = { version = "1.35.1", features = [ | tokio = { version = "1.35.1", features = [ | ||||||
|   | |||||||
							
								
								
									
										50
									
								
								src/auth.rs
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/auth.rs
									
									
									
									
									
								
							| @@ -1,50 +0,0 @@ | |||||||
| use http::StatusCode; |  | ||||||
| use poem::{ |  | ||||||
|     web::headers::{self, authorization::Basic, HeaderMapExt}, |  | ||||||
|     Endpoint, Error, Middleware, Request, Response, Result, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| pub struct BasicAuth { |  | ||||||
|     pub username: String, |  | ||||||
|     pub password: String, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<E: Endpoint> Middleware<E> for BasicAuth { |  | ||||||
|     type Output = BasicAuthEndpoint<E>; |  | ||||||
|  |  | ||||||
|     fn transform(&self, ep: E) -> Self::Output { |  | ||||||
|         BasicAuthEndpoint { |  | ||||||
|             ep, |  | ||||||
|             username: self.username.clone(), |  | ||||||
|             password: self.password.clone(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub struct BasicAuthEndpoint<E> { |  | ||||||
|     ep: E, |  | ||||||
|     username: String, |  | ||||||
|     password: String, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[poem::async_trait] |  | ||||||
| impl<E: Endpoint> Endpoint for BasicAuthEndpoint<E> { |  | ||||||
|     type Output = E::Output; |  | ||||||
|  |  | ||||||
|     async fn call(&self, req: Request) -> Result<Self::Output> { |  | ||||||
|         if let Some(auth) = req.headers().typed_get::<headers::Authorization<Basic>>() { |  | ||||||
|             if auth.0.username() == self.username && auth.0.password() == self.password { |  | ||||||
|                 return self.ep.call(req).await; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         Err(Error::from_response( |  | ||||||
|             Response::builder() |  | ||||||
|                 .header( |  | ||||||
|                     "WWW-Authenticate", |  | ||||||
|                     "Basic realm=\"RoadSig\", charset=\"UTF-8\"", |  | ||||||
|                 ) |  | ||||||
|                 .status(StatusCode::UNAUTHORIZED) |  | ||||||
|                 .finish(), |  | ||||||
|         )) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										19
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -1,10 +1,12 @@ | |||||||
| pub mod auth; |  | ||||||
| mod config; | mod config; | ||||||
| mod proxies; | mod proxies; | ||||||
| mod sideload; | mod sideload; | ||||||
| pub mod warden; | pub mod warden; | ||||||
|  |  | ||||||
| use actix_web::{App, HttpServer, web}; | use actix_web::{App, HttpServer, web}; | ||||||
|  | use actix_web_httpauth::extractors::AuthenticationError; | ||||||
|  | use actix_web_httpauth::headers::www_authenticate::basic::Basic; | ||||||
|  | use actix_web_httpauth::middleware::HttpAuthentication; | ||||||
| use awc::Client; | use awc::Client; | ||||||
| use lazy_static::lazy_static; | use lazy_static::lazy_static; | ||||||
| use proxies::RoadInstance; | use proxies::RoadInstance; | ||||||
| @@ -54,7 +56,20 @@ async fn main() -> Result<(), std::io::Error> { | |||||||
|  |  | ||||||
|     // Sideload |     // Sideload | ||||||
|     let sideload_server = HttpServer::new(|| { |     let sideload_server = HttpServer::new(|| { | ||||||
|         App::new().service(sideload::service()) |         App::new() | ||||||
|  |             .wrap(HttpAuthentication::basic(|req, credentials| async move { | ||||||
|  |                 let password = config::C | ||||||
|  |                     .read() | ||||||
|  |                     .await | ||||||
|  |                     .get_string("secret") | ||||||
|  |                     .unwrap_or("".to_string()); | ||||||
|  |                 if credentials.password().unwrap_or("") != password { | ||||||
|  |                     Err((AuthenticationError::new(Basic::new()).into(), req)) | ||||||
|  |                 } else { | ||||||
|  |                     Ok(req) | ||||||
|  |                 } | ||||||
|  |             })) | ||||||
|  |             .service(sideload::service()) | ||||||
|     }).bind( |     }).bind( | ||||||
|         config::C |         config::C | ||||||
|             .read() |             .read() | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
|  |  | ||||||
| use poem_openapi::Object; |  | ||||||
| use queryst::parse; | use queryst::parse; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
| use serde_json::json; | use serde_json::json; | ||||||
| @@ -9,14 +8,14 @@ use crate::warden::Application; | |||||||
|  |  | ||||||
| use super::responder::StaticResponderConfig; | use super::responder::StaticResponderConfig; | ||||||
|  |  | ||||||
| #[derive(Debug, Object, Clone, Serialize, Deserialize)] | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
| pub struct Region { | pub struct Region { | ||||||
|     pub id: String, |     pub id: String, | ||||||
|     pub locations: Vec<Location>, |     pub locations: Vec<Location>, | ||||||
|     pub applications: Vec<Application>, |     pub applications: Vec<Application>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Object, Clone, Serialize, Deserialize)] | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
| pub struct Location { | pub struct Location { | ||||||
|     pub id: String, |     pub id: String, | ||||||
|     pub hosts: Vec<String>, |     pub hosts: Vec<String>, | ||||||
| @@ -27,7 +26,7 @@ pub struct Location { | |||||||
|     pub destinations: Vec<Destination>, |     pub destinations: Vec<Destination>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Object, Clone, Serialize, Deserialize)] | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
| pub struct Destination { | pub struct Destination { | ||||||
|     pub id: String, |     pub id: String, | ||||||
|     pub uri: String, |     pub uri: String, | ||||||
|   | |||||||
| @@ -1,11 +1,10 @@ | |||||||
| use std::collections::VecDeque; | use std::collections::VecDeque; | ||||||
|  |  | ||||||
| use poem_openapi::Object; |  | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
|  |  | ||||||
| use super::config::{Destination, Location, Region}; | use super::config::{Destination, Location, Region}; | ||||||
|  |  | ||||||
| #[derive(Debug, Object, Clone, Serialize, Deserialize, PartialEq)] | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] | ||||||
| pub struct RoadTrace { | pub struct RoadTrace { | ||||||
|     pub region: String, |     pub region: String, | ||||||
|     pub location: String, |     pub location: String, | ||||||
|   | |||||||
| @@ -2,10 +2,9 @@ pub mod runner; | |||||||
|  |  | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
|  |  | ||||||
| use futures_util::lock::Mutex; |  | ||||||
| use lazy_static::lazy_static; | use lazy_static::lazy_static; | ||||||
| use poem_openapi::Object; |  | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
|  | use tokio::sync::Mutex; | ||||||
| use tracing::{debug, warn}; | use tracing::{debug, warn}; | ||||||
|  |  | ||||||
| use crate::proxies::config::Region; | use crate::proxies::config::Region; | ||||||
| @@ -63,7 +62,7 @@ impl Default for WardenInstance { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Object, Clone, Serialize, Deserialize)] | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
| pub struct Application { | pub struct Application { | ||||||
|     pub id: String, |     pub id: String, | ||||||
|     pub exe: String, |     pub exe: String, | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| use std::{borrow::BorrowMut, collections::HashMap, io}; | use std::{borrow::BorrowMut, collections::HashMap, io}; | ||||||
|  |  | ||||||
| use super::Application; | use super::Application; | ||||||
| use futures_util::lock::Mutex; |  | ||||||
| use lazy_static::lazy_static; | use lazy_static::lazy_static; | ||||||
| use tokio::{ | use tokio::{ | ||||||
|     io::{AsyncBufReadExt, BufReader}, |     io::{AsyncBufReadExt, BufReader}, | ||||||
|     process::{Child, Command}, |     process::{Child, Command}, | ||||||
| }; | }; | ||||||
|  | use tokio::sync::Mutex; | ||||||
|  |  | ||||||
| lazy_static! { | lazy_static! { | ||||||
|     static ref STDOUT: Mutex<HashMap<String, String>> = Mutex::new(HashMap::new()); |     static ref STDOUT: Mutex<HashMap<String, String>> = Mutex::new(HashMap::new()); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user