wip: New crate opnsense-config

This commit is contained in:
Jean-Gabriel Gill-Couture
2024-10-13 08:48:56 -04:00
parent 6a5ebdbac7
commit 32cea6c3ff
10 changed files with 272 additions and 12 deletions

View 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(())
}
}

View 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),
}

View File

@@ -0,0 +1,6 @@
pub mod config;
pub mod modules;
pub mod error;
pub use config::Config;
pub use error::Error;

View 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
}
}

View File

@@ -0,0 +1,2 @@
pub mod opnsense;
pub mod dhcp;

View 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,
}