ImplementConfig Referencing System

This commit is contained in:
Samuel Lorch 2023-11-07 19:12:32 +01:00
parent c2f1845c36
commit 4f7ab04fce
8 changed files with 172 additions and 65 deletions

View file

@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use validator::Validate; use validator::Validate;
use super::object::{AddressReference, ServiceReference};
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct Firewall { pub struct Firewall {
pub forward_rules: Vec<ForwardRule>, pub forward_rules: Vec<ForwardRule>,
@ -11,9 +13,9 @@ pub struct Firewall {
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct ForwardRule { pub struct ForwardRule {
pub name: String, pub name: String,
pub services: Vec<String>, pub services: Vec<ServiceReference>,
pub source_addresses: Vec<String>, pub source_addresses: Vec<AddressReference>,
pub destination_addresses: Vec<String>, pub destination_addresses: Vec<AddressReference>,
pub comment: String, pub comment: String,
pub counter: bool, pub counter: bool,
pub verdict: Verdict, pub verdict: Verdict,
@ -22,21 +24,21 @@ pub struct ForwardRule {
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct DestinationNATRule { pub struct DestinationNATRule {
pub name: String, pub name: String,
pub services: Vec<String>, pub services: Vec<ServiceReference>,
pub source_addresses: Vec<String>, pub source_addresses: Vec<AddressReference>,
pub destination_addresses: Vec<String>, pub destination_addresses: Vec<AddressReference>,
pub comment: String, pub comment: String,
pub counter: bool, pub counter: bool,
pub dnat_address: Option<String>, pub dnat_address: Option<AddressReference>,
pub dnat_service: Option<String>, pub dnat_service: Option<ServiceReference>,
} }
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct SourceNATRule { pub struct SourceNATRule {
pub name: String, pub name: String,
pub services: Vec<String>, pub services: Vec<ServiceReference>,
pub source_addresses: Vec<String>, pub source_addresses: Vec<AddressReference>,
pub destination_addresses: Vec<String>, pub destination_addresses: Vec<AddressReference>,
pub comment: String, pub comment: String,
pub counter: bool, pub counter: bool,
pub snat_type: SNATType, pub snat_type: SNATType,
@ -54,8 +56,8 @@ pub enum Verdict {
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
pub enum SNATType { pub enum SNATType {
SNAT { SNAT {
address: Option<String>, address: Option<AddressReference>,
service: Option<String>, service: Option<ServiceReference>,
}, },
Masquerade, Masquerade,
} }

View file

@ -1,3 +1,5 @@
use self::config::Config;
pub mod config; pub mod config;
pub mod firewall; pub mod firewall;
pub mod network; pub mod network;
@ -6,16 +8,49 @@ pub mod service;
pub mod system; pub mod system;
pub mod vpn; pub mod vpn;
pub trait Referenceable<T> {
fn named_get(&self, name: String) -> T;
fn named_exists(&self, name: String) -> bool;
}
#[macro_export] #[macro_export]
macro_rules! get_thing { macro_rules! impl_referenceable_trait {
($out:ty, $n:ident) => { ($typ:ty, $ele:ty) => {
pub fn $n(list: Vec<$out>, name: String) -> Option<$out> { impl Referenceable<$ele> for $typ {
for e in list { fn named_get(&self, name: String) -> $ele {
if e.name == name { let index = self.iter().position(|e| *e.name == name);
return Some(e);
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<T> {
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())
}
} }
}; };
} }

View file

@ -3,14 +3,29 @@ use serde::{Deserialize, Serialize};
use std::net::IpAddr; use std::net::IpAddr;
use validator::Validate; 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)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct Network { pub struct Network {
pub interfaces: Vec<NetworkInterface>, pub interfaces: NetworkInterfaces,
pub static_routes: Vec<StaticRoute>, pub static_routes: Vec<StaticRoute>,
} }
type NetworkInterfaces = Vec<NetworkInterface>;
impl_referenceable_trait!(NetworkInterfaces, NetworkInterface);
pub type NetworkInterfaceReference = String;
impl_references_trait!(
NetworkInterfaceReference,
NetworkInterface,
network.interfaces
);
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct NetworkInterface { pub struct NetworkInterface {
pub name: String, pub name: String,
@ -20,29 +35,38 @@ pub struct NetworkInterface {
pub addressing_mode: AddressingMode, pub addressing_mode: AddressingMode,
} }
get_thing!(NetworkInterface, get_network_interface);
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum NetworkInterfaceType { pub enum NetworkInterfaceType {
Hardware { device: String }, // TODO figure out how to validate the device since it needs to soft fail
Vlan { id: i32, parent: String }, Hardware {
Bond { members: Vec<String> }, device: String,
Bridge { members: Vec<String> }, },
Vlan {
id: i32,
parent: NetworkInterfaceReference,
},
Bond {
members: Vec<NetworkInterfaceReference>,
},
Bridge {
members: Vec<NetworkInterfaceReference>,
},
} }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum AddressingMode { pub enum AddressingMode {
None, None,
Static { address: String }, Static { address: AddressReference },
DHCP, DHCP,
} }
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct StaticRoute { pub struct StaticRoute {
pub name: String, pub name: String,
pub interface: String, pub interface: NetworkInterfaceReference,
// TODO make this a Address Object Reference?
pub gateway: IpAddr, pub gateway: IpAddr,
pub destination: IpNet, pub destination: IpNet,
pub metric: u64, pub metric: u64,

View file

@ -3,14 +3,24 @@ use serde::{Deserialize, Serialize};
use std::net::IpAddr; use std::net::IpAddr;
use validator::Validate; 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)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct Object { pub struct Object {
pub addresses: Vec<Address>, pub addresses: Addresses,
pub services: Vec<Service>, pub services: Services,
} }
type Addresses = Vec<Address>;
impl_referenceable_trait!(Addresses, Address);
pub type AddressReference = String;
impl_references_trait!(AddressReference, Address, object.addresses);
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct Address { pub struct Address {
pub name: String, pub name: String,
@ -18,17 +28,21 @@ pub struct Address {
pub comment: String, pub comment: String,
} }
get_thing!(Address, get_address);
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum AddressType { pub enum AddressType {
Host { address: String }, Host { address: IpAddr },
Range { range: IpAddr }, Range { range: IpAddr },
Network { network: IpNet }, Network { network: IpNet },
Group { members: Vec<String> }, Group { members: Vec<AddressReference> },
} }
type Services = Vec<Service>;
impl_referenceable_trait!(Services, Service);
pub type ServiceReference = String;
impl_references_trait!(ServiceReference, Service, object.services);
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct Service { pub struct Service {
pub name: String, pub name: String,
@ -36,8 +50,6 @@ pub struct Service {
pub comment: String, pub comment: String,
} }
get_thing!(Service, get_service);
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
pub enum ServiceType { pub enum ServiceType {
@ -53,7 +65,7 @@ pub enum ServiceType {
code: u8, code: u8,
}, },
Group { Group {
members: Vec<String>, members: Vec<ServiceReference>,
}, },
} }

View file

@ -1,9 +1,10 @@
use core::time; use core::time;
use macaddr::MacAddr8; use macaddr::MacAddr8;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use validator::Validate; use validator::Validate;
use super::{network::NetworkInterfaceReference, object::AddressReference};
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct Service { pub struct Service {
pub dhcp_servers: Vec<DHCPServer>, pub dhcp_servers: Vec<DHCPServer>,
@ -13,8 +14,8 @@ pub struct Service {
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct DHCPServer { pub struct DHCPServer {
pub interface: String, pub interface: NetworkInterfaceReference,
pub pool: Vec<String>, pub pool: Vec<AddressReference>,
pub lease_time: time::Duration, pub lease_time: time::Duration,
pub gateway_mode: GatewayMode, pub gateway_mode: GatewayMode,
pub dns_server_mode: DNSServerMode, pub dns_server_mode: DNSServerMode,
@ -25,13 +26,13 @@ pub struct DHCPServer {
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct DNSServer { pub struct DNSServer {
pub interface: String, pub interface: NetworkInterfaceReference,
pub comment: String, pub comment: String,
} }
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct NTPServer { pub struct NTPServer {
pub interface: String, pub interface: NetworkInterfaceReference,
pub comment: String, pub comment: String,
} }
@ -40,7 +41,7 @@ pub struct NTPServer {
pub enum GatewayMode { pub enum GatewayMode {
None, None,
Interface, Interface,
Specify { gateway: String }, Specify { gateway: AddressReference },
} }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
@ -48,7 +49,7 @@ pub enum GatewayMode {
pub enum DNSServerMode { pub enum DNSServerMode {
None, None,
Interface, Interface,
Specify { dns_servers: Vec<String> }, Specify { dns_servers: Vec<AddressReference> },
} }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
@ -56,12 +57,12 @@ pub enum DNSServerMode {
pub enum NTPServerMode { pub enum NTPServerMode {
None, None,
Interface, Interface,
Specify { ntp_servers: Vec<String> }, Specify { ntp_servers: Vec<AddressReference> },
} }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Reservation { pub struct Reservation {
pub ip_address: IpAddr, pub ip_address: AddressReference,
pub hardware_address: MacAddr8, pub hardware_address: MacAddr8,
pub comment: String, pub comment: String,
} }

View file

@ -1,18 +1,26 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use validator::Validate; 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)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct System { pub struct System {
pub users: Vec<User>, pub users: Vec<User>,
} }
type Users = Vec<User>;
impl_referenceable_trait!(Users, User);
pub type UserReference = String;
impl_references_trait!(UserReference, User, system.users);
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct User { pub struct User {
pub name: String, pub name: String,
pub comment: String, pub comment: String,
pub hash: String, pub hash: String,
} }
get_thing!(User, get_user);

View file

@ -1,7 +1,11 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use validator::Validate; 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)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct VPN { pub struct VPN {
@ -10,21 +14,35 @@ pub struct VPN {
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
pub struct Wireguard { pub struct Wireguard {
pub interfaces: Vec<WireguardInterface>, pub interfaces: WireguardInterfaces,
pub peers: Vec<WireguardPeer>, pub peers: WireguardPeers,
} }
type WireguardInterfaces = Vec<WireguardInterface>;
impl_referenceable_trait!(WireguardInterfaces, WireguardInterface);
pub type WireguardInterfaceReference = String;
impl_references_trait!(
WireguardInterfaceReference,
WireguardInterface,
vpn.wireguard.interfaces
);
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct WireguardInterface { pub struct WireguardInterface {
pub name: String, pub name: String,
pub public_key: String, pub public_key: String,
pub private_key: String, pub private_key: String,
pub listen_port: u64, pub listen_port: u64,
pub peers: Vec<String>, pub peers: Vec<WireguardPeerReference>,
pub comment: String, pub comment: String,
} }
get_thing!(WireguardInterface, get_wireguard_interface); pub type WireguardPeers = Vec<WireguardPeer>;
impl_referenceable_trait!(WireguardPeers, WireguardPeer);
type WireguardPeerReference = String;
impl_references_trait!(WireguardPeerReference, WireguardPeer, vpn.wireguard.peers);
#[derive(Serialize, Deserialize, Clone, Validate, Debug)] #[derive(Serialize, Deserialize, Clone, Validate, Debug)]
pub struct WireguardPeer { pub struct WireguardPeer {
@ -36,5 +54,3 @@ pub struct WireguardPeer {
pub persistent_keepalive: Option<u64>, pub persistent_keepalive: Option<u64>,
pub comment: String, pub comment: String,
} }
get_thing!(WireguardPeer, get_wireguard_peer);

View file

@ -1,11 +1,10 @@
use crate::definitions::Referenceable;
use std::collections::HashMap; use std::collections::HashMap;
use rbtag::BuildInfo; use rbtag::BuildInfo;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use uuid::Uuid; use uuid::Uuid;
use crate::definitions::system::get_user;
use super::super::AppState; use super::super::AppState;
use axum::routing::post; use axum::routing::post;
use axum::{Json, Router}; use axum::{Json, Router};
@ -66,10 +65,20 @@ async fn login_handler(
State(state): State<AppState>, State(state): State<AppState>,
Json(payload): Json<LoginParameters>, Json(payload): Json<LoginParameters>,
) -> impl IntoResponse { ) -> impl IntoResponse {
if let Some(user) = get_user( if state
state.config_manager.get_current_config().system.users, .config_manager
payload.username.to_string(), .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) { if sha512_crypt::verify(payload.password, &user.hash) {
let mut sessions = state.session_state.sessions.write().unwrap(); let mut sessions = state.session_state.sessions.write().unwrap();
let id = Uuid::new_v4().to_string(); let id = Uuid::new_v4().to_string();