wip(opnsense-config): It compiles now, still have to test it

This commit is contained in:
Jean-Gabriel Gill-Couture 2024-10-14 07:53:02 -04:00
parent 32cea6c3ff
commit 8459c38499

View File

@ -1,27 +1,68 @@
use crate::error::Error; use crate::error::Error;
use crate::modules::opnsense::OPNsense; use crate::modules::opnsense::OPNsense;
use async_trait::async_trait;
use russh::client::{Config as SshConfig, Handler}; use russh::client::{Config as SshConfig, Handler};
use std::sync::Arc;
use russh_keys::key; use russh_keys::key;
use std::{fmt::Write as _, sync::Arc};
use tokio::io::AsyncWriteExt;
struct Client {}
// More SSH event handlers
// can be defined in this trait
// In this example, we're only using Channel, so these aren't needed.
#[async_trait]
impl Handler for Client {
type Error = Error;
async fn check_server_key(
&mut self,
_server_public_key: &key::PublicKey,
) -> Result<bool, Self::Error> {
Ok(true)
}
}
pub struct Config { pub struct Config {
opnsense: OPNsense, opnsense: OPNsense,
ssh_config: Arc<SshConfig>, ssh_config: Arc<SshConfig>,
host: String, host: String,
username: String, username: String,
key: Arc<key::KeyPair>,
} }
impl Config { impl Config {
pub async fn new(host: &str, username: &str, key_path: &str) -> Result<Self, Error> { 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 key = russh_keys::load_secret_key(key_path, None).expect("Secret key failed loading");
let key = Arc::new(key);
let config = SshConfig::default(); let config = SshConfig::default();
let config = Arc::new(config); let config = Arc::new(config);
let mut ssh = russh::client::connect(config.clone(), host, Handler).await?; let mut ssh = russh::client::connect(config.clone(), host, Client {}).await?;
ssh.authenticate_publickey(username, key).await?; ssh.authenticate_publickey(username, key.clone()).await?;
let (xml, _) = ssh.exec(true, "cat /conf/config.xml").await?; let mut channel = ssh.channel_open_session().await?;
let xml = String::from_utf8(xml).map_err(|e| Error::Config(e.to_string()))?;
channel.exec(true, "cat /conf/config.xml").await?;
let mut code;
let mut output = String::new();
loop {
let Some(msg) = channel.wait().await else {
break;
};
match msg {
russh::ChannelMsg::Data { ref data } => {
write!(&mut output, "{:?}", data);
println!("Got data {output}");
}
russh::ChannelMsg::ExitStatus { exit_status } => {
code = Some(exit_status);
}
_ => todo!(),
}
}
let xml = output;
let opnsense = yaserde::de::from_str(&xml).map_err(|e| Error::Xml(e.to_string()))?; let opnsense = yaserde::de::from_str(&xml).map_err(|e| Error::Xml(e.to_string()))?;
@ -30,6 +71,7 @@ impl Config {
ssh_config: config, ssh_config: config,
host: host.to_string(), host: host.to_string(),
username: username.to_string(), username: username.to_string(),
key,
}) })
} }
@ -44,12 +86,14 @@ impl Config {
pub async fn save(&self) -> Result<(), Error> { pub async fn save(&self) -> Result<(), Error> {
let xml = yaserde::ser::to_string(&self.opnsense).map_err(|e| Error::Xml(e.to_string()))?; 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?; let mut ssh =
ssh.authenticate_publickey(&self.username, key).await?; russh::client::connect(self.ssh_config.clone(), &self.host, Client {}).await?;
ssh.authenticate_publickey(&self.username, self.key.clone()).await?;
todo!("Writing config file to remote host {xml}");
ssh.exec(true, &format!("echo '{}' > /conf/config.xml", xml)) // ssh.exec(true, &format!("echo '{}' > /conf/config.xml", xml))
.await?; // .await?;
Ok(()) // Ok(())
} }
} }