feat: OKD Dhcp config works and is actually savec on opnsense firewall, its alive!! First real run on wk cluster
This commit is contained in:
parent
d0d81af796
commit
b15df3c93f
@ -96,10 +96,10 @@ pub enum StorageKind {
|
||||
}
|
||||
#[derive(Debug, new, Clone)]
|
||||
pub struct Storage {
|
||||
connection: StorageConnectionType,
|
||||
kind: StorageKind,
|
||||
size: u64,
|
||||
serial: String,
|
||||
pub connection: StorageConnectionType,
|
||||
pub kind: StorageKind,
|
||||
pub size: u64,
|
||||
pub serial: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -47,6 +47,7 @@ pub trait DhcpServer: Send + Sync {
|
||||
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)>;
|
||||
fn get_ip(&self) -> IpAddress;
|
||||
fn get_host(&self) -> LogicalHost;
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError>;
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for dyn DhcpServer {
|
||||
|
@ -1,9 +1,10 @@
|
||||
mod management;
|
||||
use std::sync::{Arc, RwLock };
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use log::debug;
|
||||
pub use management::*;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::{
|
||||
executors::ExecutorError,
|
||||
@ -97,14 +98,24 @@ impl LoadBalancer for OPNSenseFirewall {
|
||||
|
||||
#[async_trait]
|
||||
impl DhcpServer for OPNSenseFirewall {
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||
self.opnsense_config
|
||||
.read()
|
||||
.await
|
||||
.apply()
|
||||
.await
|
||||
.map_err(|e| ExecutorError::UnexpectedError(e.to_string()))
|
||||
}
|
||||
|
||||
async fn add_static_mapping(&self, entry: &DHCPStaticEntry) -> Result<(), ExecutorError> {
|
||||
let mac: String = String::from(&entry.mac);
|
||||
|
||||
{
|
||||
let mut writable_opnsense = self.opnsense_config.write().unwrap();
|
||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
||||
writable_opnsense
|
||||
.dhcp()
|
||||
.add_static_mapping(&mac, entry.ip, &entry.name).unwrap();
|
||||
.add_static_mapping(&mac, entry.ip, &entry.name)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
debug!("Registered {:?}", entry);
|
||||
|
@ -87,7 +87,9 @@ impl Interpret for DhcpInterpret {
|
||||
.map(|binding| {
|
||||
let ip = match binding.logical_host.ip {
|
||||
std::net::IpAddr::V4(ipv4) => ipv4,
|
||||
std::net::IpAddr::V6(_) => unimplemented!("DHCPStaticEntry only supports ipv4 at the moment"),
|
||||
std::net::IpAddr::V6(_) => {
|
||||
unimplemented!("DHCPStaticEntry only supports ipv4 at the moment")
|
||||
}
|
||||
};
|
||||
|
||||
DHCPStaticEntry {
|
||||
@ -99,20 +101,23 @@ impl Interpret for DhcpInterpret {
|
||||
.collect();
|
||||
info!("DHCPStaticEntry : {:?}", dhcp_entries);
|
||||
|
||||
let dhcp = Arc::new(Box::new(topology.dhcp_server.clone()));
|
||||
info!("DHCP server : {:?}", dhcp);
|
||||
let dhcp_server = Arc::new(Box::new(topology.dhcp_server.clone()));
|
||||
info!("DHCP server : {:?}", dhcp_server);
|
||||
|
||||
let number_new_entries = dhcp_entries.len();
|
||||
|
||||
for entry in dhcp_entries.into_iter() {
|
||||
match dhcp.add_static_mapping(&entry).await {
|
||||
match dhcp_server.add_static_mapping(&entry).await {
|
||||
Ok(_) => info!("Successfully registered DHCPStaticEntry {}", entry),
|
||||
Err(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
todo!("Configure DHCPServer");
|
||||
dhcp_server.commit_config().await;
|
||||
|
||||
Ok(Outcome::new(
|
||||
InterpretStatus::SUCCESS,
|
||||
"Connection test successful".to_string(),
|
||||
format!("Dhcp Interpret registered {} entries", number_new_entries),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
pub mod dhcp;
|
||||
pub mod okd;
|
||||
|
45
harmony-rs/harmony/src/modules/okd/dhcp.rs
Normal file
45
harmony-rs/harmony/src/modules/okd/dhcp.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use crate::{
|
||||
inventory::Inventory,
|
||||
modules::dhcp::DhcpScore,
|
||||
score::Score,
|
||||
topology::{HAClusterTopology, HostBinding},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OKDBootstrapDhcpScore {
|
||||
dhcp_score: DhcpScore,
|
||||
}
|
||||
|
||||
impl OKDBootstrapDhcpScore {
|
||||
pub fn new(topology: &HAClusterTopology, inventory: &Inventory) -> Self {
|
||||
Self {
|
||||
dhcp_score: DhcpScore::new(
|
||||
topology
|
||||
.control_plane
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, topology_entry)| {
|
||||
HostBinding {
|
||||
logical_host: topology_entry.clone(),
|
||||
physical_host: inventory
|
||||
.control_plane_host
|
||||
.get(index)
|
||||
.expect(
|
||||
"Iventory should contain at least as many physical hosts as topology",
|
||||
)
|
||||
.clone(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Score for OKDBootstrapDhcpScore {
|
||||
type InterpretType = <DhcpScore as Score>::InterpretType;
|
||||
|
||||
fn create_interpret(self) -> Self::InterpretType {
|
||||
self.dhcp_score.create_interpret()
|
||||
}
|
||||
}
|
2
harmony-rs/harmony/src/modules/okd/mod.rs
Normal file
2
harmony-rs/harmony/src/modules/okd/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod dhcp;
|
||||
|
@ -27,7 +27,7 @@ pub struct OPNsense {
|
||||
pub opnsense: OPNsenseXmlSection,
|
||||
pub staticroutes: StaticRoutes,
|
||||
pub ca: MaybeString,
|
||||
pub gateways: Option<Gateways>,
|
||||
pub gateways: Option<RawXml>,
|
||||
pub cert: Vec<Cert>,
|
||||
pub dhcpdv6: DhcpDv6,
|
||||
pub virtualip: VirtualIp,
|
||||
@ -60,7 +60,6 @@ impl OPNsense {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct LoadBalancer {
|
||||
pub monitor_type: Vec<MonitorType>,
|
||||
@ -415,6 +414,8 @@ pub struct OPNsenseXmlSection {
|
||||
pub ipsec: Option<IPsec>,
|
||||
#[yaserde(rename = "Interfaces")]
|
||||
pub interfaces: Option<ConfigInterfaces>,
|
||||
#[yaserde(rename = "NodeExporter")]
|
||||
pub node_exporter: Option<RawXml>,
|
||||
#[yaserde(rename = "Kea")]
|
||||
pub kea: Option<RawXml>,
|
||||
pub monit: Option<Monit>,
|
||||
@ -428,6 +429,7 @@ pub struct OPNsenseXmlSection {
|
||||
pub unboundplus: Option<RawXml>,
|
||||
#[yaserde(rename = "DHCRelay")]
|
||||
pub dhcrelay: Option<RawXml>,
|
||||
pub trust: Option<RawXml>,
|
||||
pub wireguard: Option<Wireguard>,
|
||||
#[yaserde(rename = "Swanctl")]
|
||||
pub swanctl: Swanctl,
|
||||
@ -479,6 +481,8 @@ pub struct IDSGeneral {
|
||||
#[yaserde(rename = "LogPayload")]
|
||||
log_payload: Option<u8>,
|
||||
verbosity: MaybeString,
|
||||
#[yaserde(rename = "eveLog")]
|
||||
eve_log: Option<RawXml>,
|
||||
}
|
||||
|
||||
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
||||
@ -498,11 +502,15 @@ pub struct IPsec {
|
||||
key_pairs: MaybeString,
|
||||
#[yaserde(rename = "preSharedKeys")]
|
||||
pre_shared_keys: MaybeString,
|
||||
charon: Option<RawXml>,
|
||||
}
|
||||
|
||||
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
||||
pub struct GeneralIpsec {
|
||||
enabled: MaybeString,
|
||||
preferred_oldsa: MaybeString,
|
||||
disablevpnrules: MaybeString,
|
||||
passthrough_networks: MaybeString,
|
||||
}
|
||||
|
||||
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
||||
@ -1214,6 +1222,8 @@ pub struct WireguardServerItem {
|
||||
pub gateway: MaybeString,
|
||||
pub carp_depend_on: MaybeString,
|
||||
pub peers: String,
|
||||
pub endpoint: MaybeString,
|
||||
pub peer_dns: MaybeString,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
@ -1320,7 +1330,6 @@ pub struct ConfigOpenVPN {
|
||||
pub StaticKeys: MaybeString,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
#[yaserde(rename = "HAProxy")]
|
||||
pub struct HAProxy {
|
||||
@ -1411,6 +1420,8 @@ pub struct Tuning {
|
||||
#[yaserde(rename = "maxConnections")]
|
||||
pub max_connections: MaybeString,
|
||||
pub nbthread: i32,
|
||||
#[yaserde(rename = "resolversPrefer")]
|
||||
pub resolvers_prefer: String,
|
||||
#[yaserde(rename = "sslServerVerify")]
|
||||
pub ssl_server_verify: String,
|
||||
#[yaserde(rename = "maxDHSize")]
|
||||
@ -1425,6 +1436,12 @@ pub struct Tuning {
|
||||
pub lua_max_mem: i32,
|
||||
#[yaserde(rename = "customOptions")]
|
||||
pub custom_options: MaybeString,
|
||||
#[yaserde(rename = "ocspUpdateEnabled")]
|
||||
pub ocs_update_enabled: MaybeString,
|
||||
#[yaserde(rename = "ocspUpdateMinDelay")]
|
||||
pub ocs_update_min_delay: MaybeString,
|
||||
#[yaserde(rename = "ocspUpdateMaxDelay")]
|
||||
pub ocs_update_max_delay: MaybeString,
|
||||
#[yaserde(rename = "ssl_defaultsEnabled")]
|
||||
pub ssl_defaults_enabled: i32,
|
||||
#[yaserde(rename = "ssl_bindOptions")]
|
||||
@ -1437,6 +1454,19 @@ pub struct Tuning {
|
||||
pub ssl_cipher_list: String,
|
||||
#[yaserde(rename = "ssl_cipherSuites")]
|
||||
pub ssl_cipher_suites: String,
|
||||
#[yaserde(rename = "h2_initialWindowSize")]
|
||||
pub h2_initial_window_size: Option<MaybeString>,
|
||||
#[yaserde(rename = "h2_initialWindowSizeOutgoing")]
|
||||
pub h2_initial_window_size_outgoing: Option<MaybeString>,
|
||||
#[yaserde(rename = "h2_initialWindowSizeIncoming")]
|
||||
pub h2_initial_window_size_incoming: Option<MaybeString>,
|
||||
#[yaserde(rename = "h2_maxConcurrentStreams")]
|
||||
pub h2_max_concurrent_streams: Option<MaybeString>,
|
||||
#[yaserde(rename = "h2_maxConcurrentStreamsOutgoing")]
|
||||
pub h2_max_concurrent_streams_outgoing: Option<MaybeString>,
|
||||
#[yaserde(rename = "h2_maxConcurrentStreamsIncoming")]
|
||||
pub h2_max_concurrent_streams_incoming: Option<MaybeString>,
|
||||
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
@ -1684,25 +1714,22 @@ pub struct Backend {
|
||||
pub http2_enabled_nontls: u8,
|
||||
#[yaserde(rename = "ba_advertised_protocols")]
|
||||
pub ba_advertised_protocols: String,
|
||||
#[yaserde(rename = "persistence")]
|
||||
pub persistence: String,
|
||||
#[yaserde(rename = "persistence_cookiemode")]
|
||||
#[yaserde(rename = "forwardFor")]
|
||||
pub forward_for: Option<i32>,
|
||||
#[yaserde(rename = "forwardedHeader")]
|
||||
pub forwarded_header: Option<MaybeString>,
|
||||
#[yaserde(rename = "forwardedHeaderParameters")]
|
||||
pub forwarded_header_parameters: Option<MaybeString>,
|
||||
pub persistence: MaybeString,
|
||||
pub persistence_cookiemode: String,
|
||||
#[yaserde(rename = "persistence_cookiename")]
|
||||
pub persistence_cookiename: MaybeString,
|
||||
#[yaserde(rename = "persistence_stripquotes")]
|
||||
pub persistence_stripquotes: u8,
|
||||
#[yaserde(rename = "stickiness_pattern")]
|
||||
pub stickiness_pattern: String,
|
||||
pub stickiness_pattern: MaybeString,
|
||||
#[yaserde(rename = "stickiness_dataTypes")]
|
||||
pub stickiness_data_types: MaybeString,
|
||||
#[yaserde(rename = "stickiness_expire")]
|
||||
pub stickiness_expire: String,
|
||||
#[yaserde(rename = "stickiness_size")]
|
||||
pub stickiness_size: String,
|
||||
#[yaserde(rename = "stickiness_cookiename")]
|
||||
pub stickiness_cookiename: MaybeString,
|
||||
#[yaserde(rename = "stickiness_cookielength")]
|
||||
pub stickiness_cookielength: MaybeString,
|
||||
#[yaserde(rename = "stickiness_connRatePeriod")]
|
||||
pub stickiness_conn_rate_period: String,
|
||||
@ -1863,12 +1890,6 @@ pub struct StaticRoutes {
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct Ca {}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct Gateways {
|
||||
#[yaserde(rename = "gateway_item")]
|
||||
pub gateway_item: RawXml
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct Cert {
|
||||
#[yaserde(attribute)]
|
||||
@ -1975,14 +1996,14 @@ pub struct Bridges {
|
||||
pub struct Gifs {
|
||||
#[yaserde(attribute)]
|
||||
pub version: Option<String>,
|
||||
pub gif: MaybeString,
|
||||
pub gif: Option<MaybeString>,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct Gres {
|
||||
#[yaserde(attribute)]
|
||||
pub version: Option<String>,
|
||||
pub gre: MaybeString,
|
||||
pub gre: Option<MaybeString>,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
|
@ -24,9 +24,10 @@ impl SshConfigManager {
|
||||
|
||||
impl SshConfigManager {
|
||||
async fn backup_config_remote(&self) -> Result<String, Error> {
|
||||
let backup_filename = format!("config_{}.xml", chrono::Local::now().format("%Y%m%d%H%M%S"));
|
||||
let ts = chrono::Utc::now();
|
||||
let backup_filename = format!("config-{}-harmony.xml", ts.format("%s%.3f"));
|
||||
|
||||
self.opnsense_shell.exec(&format!("cp /conf/config.xml /tmp/{}", backup_filename))
|
||||
self.opnsense_shell.exec(&format!("cp /conf/config.xml /conf/backup/{}", backup_filename))
|
||||
.await
|
||||
}
|
||||
|
||||
|
@ -84,9 +84,13 @@ impl<'a> DhcpConfig<'a> {
|
||||
return Err(DhcpError::InvalidMacAddress(mac));
|
||||
}
|
||||
|
||||
if !Self::is_ip_in_range(&ipaddr, range) {
|
||||
return Err(DhcpError::IpAddressOutOfRange(ipaddr.to_string()));
|
||||
}
|
||||
// TODO verify if address is in subnet range
|
||||
// This check here does not do what we want to do, as we want to assign static leases
|
||||
// outside of the dynamic DHCP pool
|
||||
//
|
||||
// if !Self::is_ip_in_range(&ipaddr, range) {
|
||||
// return Err(DhcpError::IpAddressOutOfRange(ipaddr.to_string()));
|
||||
// }
|
||||
|
||||
if existing_mappings.iter().any(|m| {
|
||||
m.ipaddr
|
||||
@ -123,7 +127,7 @@ impl<'a> DhcpConfig<'a> {
|
||||
|
||||
parts
|
||||
.iter()
|
||||
.all(|part| part.len() == 2 && part.chars().all(|c| c.is_ascii_hexdigit()))
|
||||
.all(|part| part.len() <= 2 && part.chars().all(|c| c.is_ascii_hexdigit()))
|
||||
}
|
||||
|
||||
fn is_ip_in_range(ip: &Ipv4Addr, range: &Range) -> bool {
|
||||
|
Loading…
Reference in New Issue
Block a user