forked from NationTech/harmony
wip: New crate opnsense-config
This commit is contained in:
55
harmony-rs/opnsense-config/src/config.rs
Normal file
55
harmony-rs/opnsense-config/src/config.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use crate::error::Error;
|
||||
use crate::modules::opnsense::OPNsense;
|
||||
use russh::client::{Config as SshConfig, Handler};
|
||||
use std::sync::Arc;
|
||||
use russh_keys::key;
|
||||
|
||||
pub struct Config {
|
||||
opnsense: OPNsense,
|
||||
ssh_config: Arc<SshConfig>,
|
||||
host: String,
|
||||
username: String,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub async fn new(host: &str, username: &str, key_path: &str) -> Result<Self, Error> {
|
||||
let key = russh_keys::load_secret_key(key_path, None).expect("Secret key failed loading");
|
||||
let config = SshConfig::default();
|
||||
let config = Arc::new(config);
|
||||
|
||||
let mut ssh = russh::client::connect(config.clone(), host, Handler).await?;
|
||||
ssh.authenticate_publickey(username, key).await?;
|
||||
|
||||
let (xml, _) = ssh.exec(true, "cat /conf/config.xml").await?;
|
||||
let xml = String::from_utf8(xml).map_err(|e| Error::Config(e.to_string()))?;
|
||||
|
||||
let opnsense = yaserde::de::from_str(&xml).map_err(|e| Error::Xml(e.to_string()))?;
|
||||
|
||||
Ok(Self {
|
||||
opnsense,
|
||||
ssh_config: config,
|
||||
host: host.to_string(),
|
||||
username: username.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_opnsense(&self) -> &OPNsense {
|
||||
&self.opnsense
|
||||
}
|
||||
|
||||
pub fn get_opnsense_mut(&mut self) -> &mut OPNsense {
|
||||
&mut self.opnsense
|
||||
}
|
||||
|
||||
pub async fn save(&self) -> Result<(), Error> {
|
||||
let xml = yaserde::ser::to_string(&self.opnsense).map_err(|e| Error::Xml(e.to_string()))?;
|
||||
|
||||
let mut ssh = russh::client::connect(self.ssh_config.clone(), &self.host, Handler).await?;
|
||||
ssh.authenticate_publickey(&self.username, key).await?;
|
||||
|
||||
ssh.exec(true, &format!("echo '{}' > /conf/config.xml", xml))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
13
harmony-rs/opnsense-config/src/error.rs
Normal file
13
harmony-rs/opnsense-config/src/error.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("XML error: {0}")]
|
||||
Xml(String),
|
||||
#[error("SSH error: {0}")]
|
||||
Ssh(#[from] russh::Error),
|
||||
#[error("I/O error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("Config error: {0}")]
|
||||
Config(String),
|
||||
}
|
||||
6
harmony-rs/opnsense-config/src/lib.rs
Normal file
6
harmony-rs/opnsense-config/src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
pub mod config;
|
||||
pub mod modules;
|
||||
pub mod error;
|
||||
|
||||
pub use config::Config;
|
||||
pub use error::Error;
|
||||
24
harmony-rs/opnsense-config/src/modules/dhcp.rs
Normal file
24
harmony-rs/opnsense-config/src/modules/dhcp.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use super::opnsense::{OPNsense, StaticMap};
|
||||
|
||||
pub struct DhcpConfig<'a> {
|
||||
opnsense: &'a mut OPNsense,
|
||||
}
|
||||
|
||||
impl<'a> DhcpConfig<'a> {
|
||||
pub fn new(opnsense: &'a mut OPNsense) -> Self {
|
||||
Self { opnsense }
|
||||
}
|
||||
|
||||
pub fn add_static_mapping(&mut self, mac: String, ipaddr: String, hostname: String) {
|
||||
let static_map = StaticMap {
|
||||
mac,
|
||||
ipaddr,
|
||||
hostname,
|
||||
};
|
||||
self.opnsense.dhcpd.lan.staticmaps.push(static_map);
|
||||
}
|
||||
|
||||
pub fn get_static_mappings(&self) -> &[StaticMap] {
|
||||
&self.opnsense.dhcpd.lan.staticmaps
|
||||
}
|
||||
}
|
||||
2
harmony-rs/opnsense-config/src/modules/mod.rs
Normal file
2
harmony-rs/opnsense-config/src/modules/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod opnsense;
|
||||
pub mod dhcp;
|
||||
44
harmony-rs/opnsense-config/src/modules/opnsense.rs
Normal file
44
harmony-rs/opnsense-config/src/modules/opnsense.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
use yaserde_derive::{YaDeserialize, YaSerialize};
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
#[yaserde(rename = "opnsense")]
|
||||
pub struct OPNsense {
|
||||
#[yaserde(rename = "dhcpd")]
|
||||
pub dhcpd: Dhcpd,
|
||||
// Add other top-level elements as needed
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct Dhcpd {
|
||||
#[yaserde(rename = "lan")]
|
||||
pub lan: DhcpInterface,
|
||||
// Add other interfaces as needed
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct DhcpInterface {
|
||||
#[yaserde(rename = "enable")]
|
||||
pub enable: bool,
|
||||
#[yaserde(rename = "range")]
|
||||
pub range: DhcpRange,
|
||||
#[yaserde(rename = "staticmap")]
|
||||
pub staticmaps: Vec<StaticMap>,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct DhcpRange {
|
||||
#[yaserde(rename = "from")]
|
||||
pub from: String,
|
||||
#[yaserde(rename = "to")]
|
||||
pub to: String,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct StaticMap {
|
||||
#[yaserde(rename = "mac")]
|
||||
pub mac: String,
|
||||
#[yaserde(rename = "ipaddr")]
|
||||
pub ipaddr: String,
|
||||
#[yaserde(rename = "hostname")]
|
||||
pub hostname: String,
|
||||
}
|
||||
Reference in New Issue
Block a user