From 4f7ab04fcefa59f80eb7485c129a2f5dd329c66b Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Tue, 7 Nov 2023 19:12:32 +0100 Subject: [PATCH] ImplementConfig Referencing System --- src/definitions/firewall.rs | 28 +++++++++++---------- src/definitions/mod.rs | 49 +++++++++++++++++++++++++++++++------ src/definitions/network.rs | 44 +++++++++++++++++++++++++-------- src/definitions/object.rs | 32 ++++++++++++++++-------- src/definitions/service.rs | 19 +++++++------- src/definitions/system.rs | 14 ++++++++--- src/definitions/vpn.rs | 30 +++++++++++++++++------ src/web/auth.rs | 21 +++++++++++----- 8 files changed, 172 insertions(+), 65 deletions(-) diff --git a/src/definitions/firewall.rs b/src/definitions/firewall.rs index ee16298..56c659d 100644 --- a/src/definitions/firewall.rs +++ b/src/definitions/firewall.rs @@ -1,6 +1,8 @@ use serde::{Deserialize, Serialize}; use validator::Validate; +use super::object::{AddressReference, ServiceReference}; + #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct Firewall { pub forward_rules: Vec, @@ -11,9 +13,9 @@ pub struct Firewall { #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct ForwardRule { pub name: String, - pub services: Vec, - pub source_addresses: Vec, - pub destination_addresses: Vec, + pub services: Vec, + pub source_addresses: Vec, + pub destination_addresses: Vec, pub comment: String, pub counter: bool, pub verdict: Verdict, @@ -22,21 +24,21 @@ pub struct ForwardRule { #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct DestinationNATRule { pub name: String, - pub services: Vec, - pub source_addresses: Vec, - pub destination_addresses: Vec, + pub services: Vec, + pub source_addresses: Vec, + pub destination_addresses: Vec, pub comment: String, pub counter: bool, - pub dnat_address: Option, - pub dnat_service: Option, + pub dnat_address: Option, + pub dnat_service: Option, } #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct SourceNATRule { pub name: String, - pub services: Vec, - pub source_addresses: Vec, - pub destination_addresses: Vec, + pub services: Vec, + pub source_addresses: Vec, + pub destination_addresses: Vec, pub comment: String, pub counter: bool, pub snat_type: SNATType, @@ -54,8 +56,8 @@ pub enum Verdict { #[serde(rename_all = "lowercase")] pub enum SNATType { SNAT { - address: Option, - service: Option, + address: Option, + service: Option, }, Masquerade, } diff --git a/src/definitions/mod.rs b/src/definitions/mod.rs index cb4dcf7..2676e6f 100644 --- a/src/definitions/mod.rs +++ b/src/definitions/mod.rs @@ -1,3 +1,5 @@ +use self::config::Config; + pub mod config; pub mod firewall; pub mod network; @@ -6,16 +8,49 @@ pub mod service; pub mod system; pub mod vpn; +pub trait Referenceable { + fn named_get(&self, name: String) -> T; + fn named_exists(&self, name: String) -> bool; +} + #[macro_export] -macro_rules! get_thing { - ($out:ty, $n:ident) => { - pub fn $n(list: Vec<$out>, name: String) -> Option<$out> { - for e in list { - if e.name == name { - return Some(e); +macro_rules! impl_referenceable_trait { + ($typ:ty, $ele:ty) => { + impl Referenceable<$ele> for $typ { + fn named_get(&self, name: String) -> $ele { + let index = self.iter().position(|e| *e.name == name); + + match index { + Some(i) => self[i].clone(), + // This is fine since the config always has to validated before commiting + None => panic!("Referenced Thing: '{:?}' does not exist ", name), } } - None + + fn named_exists(&self, name: String) -> bool { + let index = self.iter().position(|e| *e.name == name); + index.is_some() + } + } + }; +} + +pub trait References { + fn get_ref(&self, config: Config) -> T; + fn ref_exists(&self, config: Config) -> bool; +} + +#[macro_export] +macro_rules! impl_references_trait { + ($thing:ty, $referenced:ty, $( $path:ident ).+) => { + impl References<$referenced> for $thing { + fn get_ref(&self, config: Config) -> $referenced { + config.$($path).+.named_get(self.clone()) + } + + fn ref_exists(&self, config: Config) -> bool { + config.$($path).+.named_exists(self.clone()) + } } }; } diff --git a/src/definitions/network.rs b/src/definitions/network.rs index fa8d1fe..5fea499 100644 --- a/src/definitions/network.rs +++ b/src/definitions/network.rs @@ -3,14 +3,29 @@ use serde::{Deserialize, Serialize}; use std::net::IpAddr; use validator::Validate; -use crate::get_thing; +use crate::definitions::Referenceable; +use crate::{impl_referenceable_trait, impl_references_trait}; + +use super::config::Config; +use super::object::AddressReference; +use super::References; #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct Network { - pub interfaces: Vec, + pub interfaces: NetworkInterfaces, pub static_routes: Vec, } +type NetworkInterfaces = Vec; +impl_referenceable_trait!(NetworkInterfaces, NetworkInterface); + +pub type NetworkInterfaceReference = String; +impl_references_trait!( + NetworkInterfaceReference, + NetworkInterface, + network.interfaces +); + #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct NetworkInterface { pub name: String, @@ -20,29 +35,38 @@ pub struct NetworkInterface { pub addressing_mode: AddressingMode, } -get_thing!(NetworkInterface, get_network_interface); - #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "snake_case")] pub enum NetworkInterfaceType { - Hardware { device: String }, - Vlan { id: i32, parent: String }, - Bond { members: Vec }, - Bridge { members: Vec }, + // TODO figure out how to validate the device since it needs to soft fail + Hardware { + device: String, + }, + Vlan { + id: i32, + parent: NetworkInterfaceReference, + }, + Bond { + members: Vec, + }, + Bridge { + members: Vec, + }, } #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "snake_case")] pub enum AddressingMode { None, - Static { address: String }, + Static { address: AddressReference }, DHCP, } #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct StaticRoute { pub name: String, - pub interface: String, + pub interface: NetworkInterfaceReference, + // TODO make this a Address Object Reference? pub gateway: IpAddr, pub destination: IpNet, pub metric: u64, diff --git a/src/definitions/object.rs b/src/definitions/object.rs index 14461dc..54291a7 100644 --- a/src/definitions/object.rs +++ b/src/definitions/object.rs @@ -3,14 +3,24 @@ use serde::{Deserialize, Serialize}; use std::net::IpAddr; use validator::Validate; -use crate::get_thing; +// Referencing +use crate::definitions::config::Config; +use crate::definitions::Referenceable; +use crate::definitions::References; +use crate::{impl_referenceable_trait, impl_references_trait}; #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct Object { - pub addresses: Vec
, - pub services: Vec, + pub addresses: Addresses, + pub services: Services, } +type Addresses = Vec
; +impl_referenceable_trait!(Addresses, Address); + +pub type AddressReference = String; +impl_references_trait!(AddressReference, Address, object.addresses); + #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct Address { pub name: String, @@ -18,17 +28,21 @@ pub struct Address { pub comment: String, } -get_thing!(Address, get_address); - #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "snake_case")] pub enum AddressType { - Host { address: String }, + Host { address: IpAddr }, Range { range: IpAddr }, Network { network: IpNet }, - Group { members: Vec }, + Group { members: Vec }, } +type Services = Vec; +impl_referenceable_trait!(Services, Service); + +pub type ServiceReference = String; +impl_references_trait!(ServiceReference, Service, object.services); + #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct Service { pub name: String, @@ -36,8 +50,6 @@ pub struct Service { pub comment: String, } -get_thing!(Service, get_service); - #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "lowercase")] pub enum ServiceType { @@ -53,7 +65,7 @@ pub enum ServiceType { code: u8, }, Group { - members: Vec, + members: Vec, }, } diff --git a/src/definitions/service.rs b/src/definitions/service.rs index ea27f2f..8932fa2 100644 --- a/src/definitions/service.rs +++ b/src/definitions/service.rs @@ -1,9 +1,10 @@ use core::time; use macaddr::MacAddr8; use serde::{Deserialize, Serialize}; -use std::net::IpAddr; use validator::Validate; +use super::{network::NetworkInterfaceReference, object::AddressReference}; + #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct Service { pub dhcp_servers: Vec, @@ -13,8 +14,8 @@ pub struct Service { #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct DHCPServer { - pub interface: String, - pub pool: Vec, + pub interface: NetworkInterfaceReference, + pub pool: Vec, pub lease_time: time::Duration, pub gateway_mode: GatewayMode, pub dns_server_mode: DNSServerMode, @@ -25,13 +26,13 @@ pub struct DHCPServer { #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct DNSServer { - pub interface: String, + pub interface: NetworkInterfaceReference, pub comment: String, } #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct NTPServer { - pub interface: String, + pub interface: NetworkInterfaceReference, pub comment: String, } @@ -40,7 +41,7 @@ pub struct NTPServer { pub enum GatewayMode { None, Interface, - Specify { gateway: String }, + Specify { gateway: AddressReference }, } #[derive(Serialize, Deserialize, Clone, Debug)] @@ -48,7 +49,7 @@ pub enum GatewayMode { pub enum DNSServerMode { None, Interface, - Specify { dns_servers: Vec }, + Specify { dns_servers: Vec }, } #[derive(Serialize, Deserialize, Clone, Debug)] @@ -56,12 +57,12 @@ pub enum DNSServerMode { pub enum NTPServerMode { None, Interface, - Specify { ntp_servers: Vec }, + Specify { ntp_servers: Vec }, } #[derive(Serialize, Deserialize, Clone, Debug)] pub struct Reservation { - pub ip_address: IpAddr, + pub ip_address: AddressReference, pub hardware_address: MacAddr8, pub comment: String, } diff --git a/src/definitions/system.rs b/src/definitions/system.rs index 6d9194e..3e02ec2 100644 --- a/src/definitions/system.rs +++ b/src/definitions/system.rs @@ -1,18 +1,26 @@ use serde::{Deserialize, Serialize}; use validator::Validate; -use crate::get_thing; +// Referencing +use crate::definitions::config::Config; +use crate::definitions::Referenceable; +use crate::definitions::References; +use crate::{impl_referenceable_trait, impl_references_trait}; #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct System { pub users: Vec, } +type Users = Vec; +impl_referenceable_trait!(Users, User); + +pub type UserReference = String; +impl_references_trait!(UserReference, User, system.users); + #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct User { pub name: String, pub comment: String, pub hash: String, } - -get_thing!(User, get_user); diff --git a/src/definitions/vpn.rs b/src/definitions/vpn.rs index 2249ec3..af43036 100644 --- a/src/definitions/vpn.rs +++ b/src/definitions/vpn.rs @@ -1,7 +1,11 @@ use serde::{Deserialize, Serialize}; use validator::Validate; -use crate::get_thing; +// Referencing +use crate::definitions::config::Config; +use crate::definitions::Referenceable; +use crate::definitions::References; +use crate::{impl_referenceable_trait, impl_references_trait}; #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct VPN { @@ -10,21 +14,35 @@ pub struct VPN { #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] pub struct Wireguard { - pub interfaces: Vec, - pub peers: Vec, + pub interfaces: WireguardInterfaces, + pub peers: WireguardPeers, } +type WireguardInterfaces = Vec; +impl_referenceable_trait!(WireguardInterfaces, WireguardInterface); + +pub type WireguardInterfaceReference = String; +impl_references_trait!( + WireguardInterfaceReference, + WireguardInterface, + vpn.wireguard.interfaces +); + #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct WireguardInterface { pub name: String, pub public_key: String, pub private_key: String, pub listen_port: u64, - pub peers: Vec, + pub peers: Vec, pub comment: String, } -get_thing!(WireguardInterface, get_wireguard_interface); +pub type WireguardPeers = Vec; +impl_referenceable_trait!(WireguardPeers, WireguardPeer); + +type WireguardPeerReference = String; +impl_references_trait!(WireguardPeerReference, WireguardPeer, vpn.wireguard.peers); #[derive(Serialize, Deserialize, Clone, Validate, Debug)] pub struct WireguardPeer { @@ -36,5 +54,3 @@ pub struct WireguardPeer { pub persistent_keepalive: Option, pub comment: String, } - -get_thing!(WireguardPeer, get_wireguard_peer); diff --git a/src/web/auth.rs b/src/web/auth.rs index 879bd1c..cb1cbb9 100644 --- a/src/web/auth.rs +++ b/src/web/auth.rs @@ -1,11 +1,10 @@ +use crate::definitions::Referenceable; use std::collections::HashMap; use rbtag::BuildInfo; use std::sync::{Arc, RwLock}; use uuid::Uuid; -use crate::definitions::system::get_user; - use super::super::AppState; use axum::routing::post; use axum::{Json, Router}; @@ -66,10 +65,20 @@ async fn login_handler( State(state): State, Json(payload): Json, ) -> impl IntoResponse { - if let Some(user) = get_user( - state.config_manager.get_current_config().system.users, - payload.username.to_string(), - ) { + if state + .config_manager + .get_current_config() + .system + .users + .named_exists(payload.username.to_string()) + { + let user = state + .config_manager + .get_current_config() + .system + .users + .named_get(payload.username.to_string()); + if sha512_crypt::verify(payload.password, &user.hash) { let mut sessions = state.session_state.sessions.write().unwrap(); let id = Uuid::new_v4().to_string();