feat: update monitoring and config reload

* monitoring: added read of current config
* config: get config by single url
This commit is contained in:
Paul 2023-11-03 09:17:24 +01:00
parent 3fb83f7f77
commit 05ef0cd339
2 changed files with 63 additions and 102 deletions

View File

@ -28,6 +28,7 @@ pub struct Context {
pub flags: Flags,
pub sas: HashMap<String, SetMap>,
pub hashwd: HashMap<String, WatchDescriptor>,
pub reloadinterval: isize,
}
#[derive(Debug, Clone)]
@ -35,7 +36,7 @@ pub struct SetMap {
pub filename: String,
pub fullpath: String,
pub regex: Regex,
pub set: Set,
pub set: SetCfg,
pub watchedfiles: HashMap<String, u64>,
pub wd: WatchDescriptor,
}
@ -64,6 +65,7 @@ impl Context {
sas: HashMap::new(),
blocklist: HashMap::new(),
hashwd: HashMap::new(),
reloadinterval: 5,
};
print!("Loading config ... ");
@ -282,7 +284,7 @@ impl Context {
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Config {
pub sets: HashMap<String, Set>,
pub sets: HashMap<String, SetCfg>,
#[serde(skip_serializing)]
pub trustnets: Vec<String>,
pub ws: HashMap<String, WebSocketCfg>,
@ -294,7 +296,7 @@ impl Config {
Self {
sets: HashMap::from([
("smtp".to_string(),
Set {
SetCfg {
src: "smtp".to_string(),
filename: "mail.log".to_string(),
regex: "(SASL LOGIN authentication failed)".to_string(),
@ -303,7 +305,7 @@ impl Config {
tryfail: 5,
}),
("ssh".to_string(),
Set {
SetCfg {
src: "ssh".to_string(),
filename: "auth.log".to_string(),
regex: "(Invalid user|BREAK|not allowed because|no matching key exchange method found)".to_string(),
@ -312,7 +314,7 @@ impl Config {
tryfail: 5,
},),
("http".to_string(),
Set {
SetCfg {
src: "http".to_string(),
filename: "".to_string(),
regex: "(anonymousfox.co)".to_string(),
@ -321,7 +323,7 @@ impl Config {
tryfail: 5,
},),
("openvpn".to_string(),
Set {
SetCfg {
src: "openvpn".to_string(),
filename: "status".to_string(),
regex: "(UNDEF)".to_string(),
@ -350,96 +352,40 @@ impl Config {
}
pub async fn load(&mut self, server: &String) -> Result<(), ReqError> {
self.get_global_config(server).await?;
self.get_trustnets(server).await?;
self.get_sets(server).await?;
self.get_ws_config(server).await?;
self.get_config(server).await?;
Ok(())
}
async fn get_global_config(&mut self, server: &String) -> Result<(), ReqError> {
let resp: Result<Response, ReqError> =
httpclient().get(format!("{server}/config")).send().await;
let req = match resp {
Ok(re) => re,
Err(err) => return Err(err),
};
let data: HashMap<String, GlobalConfig> = match req.json::<Vec<GlobalConfig>>().await {
Ok(res) => {
let mut out: HashMap<String, GlobalConfig> = HashMap::new();
res.into_iter().map(|x| x).for_each(|x| {
out.insert(x.key.to_string(), x);
});
out
}
Err(err) => return Err(err),
};
let key = "".to_string();
self.api = data
.get(&key.to_string())
.unwrap_or(&GlobalConfig {
key: "api".to_string(),
value: "127.0.0.1:8060".to_string(),
})
.value
.clone();
Ok(())
}
async fn get_trustnets(&mut self, server: &String) -> Result<(), ReqError> {
async fn get_config(&mut self, server: &String) -> Result<(), ReqError> {
let resp: Result<Response, ReqError> = httpclient()
.get(format!("{server}/config/trustlist"))
.get(format!("{server}/config?v=2"))
.send()
.await;
let req = match resp {
Ok(re) => re,
Err(err) => return Err(err),
};
let data: Vec<String> = match req.json::<Vec<String>>().await {
let data: GlobalConfigV2 = match req.json::<GlobalConfigV2>().await {
Ok(res) => res,
Err(err) => return Err(err),
};
self.trustnets = data;
Ok(())
}
async fn get_sets(&mut self, server: &String) -> Result<(), ReqError> {
let resp: Result<Response, ReqError> = httpclient()
.get(format!("{server}/config/sets"))
.send()
.await;
let req = match resp {
Ok(re) => re,
Err(err) => return Err(err),
};
let data: Vec<Set> = match req.json::<Vec<Set>>().await {
Ok(res) => res,
Err(err) => return Err(err),
};
for d in data {
for d in data.sets {
self.sets.insert(d.src.clone(), d);
}
Ok(())
}
async fn get_ws_config(&mut self, server: &String) -> Result<(), ReqError> {
let resp: Result<Response, ReqError> =
httpclient().get(format!("{server}/config/ws")).send().await;
let req = match resp {
Ok(re) => re,
Err(err) => return Err(err),
};
let data: HashMap<String, WebSocketCfg> = match req.json::<Vec<WebSocketCfg>>().await {
Ok(res) => {
let mut out: HashMap<String, WebSocketCfg> = HashMap::new();
res.into_iter().map(|x| x).for_each(|x| {
out.insert(x.t.to_string(), x);
self.trustnets = data.trustlists;
data.ws.into_iter().map(|x| x).for_each(|x| {
self.ws.insert(x.t.to_string(), x);
});
out
}
Err(err) => return Err(err),
};
self.ws = data;
self.api = data
.cfg
.get(&"api".to_string())
.unwrap_or(&self.api)
.clone();
Ok(())
}
@ -508,13 +454,15 @@ pub fn httpclient() -> Client {
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct GlobalConfig {
pub key: String,
pub value: String,
pub struct GlobalConfigV2 {
pub cfg: HashMap<String, String>,
pub sets: Vec<SetCfg>,
pub trustlists: Vec<String>,
pub ws: Vec<WebSocketCfg>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Set {
pub struct SetCfg {
pub src: String,
pub filename: String,
pub regex: String,
@ -543,13 +491,13 @@ pub struct URL {
pub path: String,
}
impl PartialEq for Set {
impl PartialEq for SetCfg {
fn eq(&self, other: &Self) -> bool {
self.src == other.src
}
}
impl Hash for Set {
impl Hash for SetCfg {
fn hash<H: Hasher>(&self, state: &mut H) {
self.src.hash(state);
}

View File

@ -24,20 +24,27 @@ pub async fn apiserver(ctxarc: &Arc<RwLock<Context>>) -> io::Result<()> {
loop {
match listener.accept().await {
Ok((stream, _addr)) => {
//let mut buf = [0; 1024];
let data;
{
let ctx = ctxarc.read().await;
data = serde_json::to_string(&ctx.blocklist);
}
stream.readable().await.unwrap();
let (reader, mut writer) = stream.into_split();
let mut buf: [u8; 16] = [0; 16];
match data {
Ok(dt) => {
let (_reader, mut writer) = stream.into_split();
match writer.write_all(format!("{dt}").as_bytes()).await {
match reader.try_read(&mut buf) {
Ok(_) => {}
Err(e) => {
println!("error: {}", e);
}
};
let msg = match String::from_utf8(buf.to_vec()) {
Ok(o) => o.trim_matches(char::from(0)).trim().to_string(),
Err(_) => "".to_string(),
};
let res = format_result(&ctxarc, msg.as_str()).await;
match writer.write_all(format!("{res}").as_bytes()).await {
Ok(_) => {}
Err(err) => {
println!("{err}");
println!("ee {err}");
}
}
}
@ -46,11 +53,17 @@ pub async fn apiserver(ctxarc: &Arc<RwLock<Context>>) -> io::Result<()> {
}
}
}
Err(err) => {
println!("couldn't get client: {}", err)
}
}
}
});
Ok(())
}
async fn format_result(ctxarc: &Arc<RwLock<Context>>, mode: &str) -> String {
let data;
let ctx = ctxarc.read().await;
match mode {
"cfg" => data = serde_json::to_string(&ctx.cfg).unwrap(),
"blocklist" => data = serde_json::to_string(&ctx.blocklist).unwrap(),
_ => data = serde_json::to_string(&ctx.blocklist).unwrap(),
};
data
}