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

View File

@ -24,20 +24,27 @@ pub async fn apiserver(ctxarc: &Arc<RwLock<Context>>) -> io::Result<()> {
loop { loop {
match listener.accept().await { match listener.accept().await {
Ok((stream, _addr)) => { Ok((stream, _addr)) => {
//let mut buf = [0; 1024]; stream.readable().await.unwrap();
let data; let (reader, mut writer) = stream.into_split();
{ let mut buf: [u8; 16] = [0; 16];
let ctx = ctxarc.read().await;
data = serde_json::to_string(&ctx.blocklist);
}
match data { match reader.try_read(&mut buf) {
Ok(dt) => { Ok(_) => {}
let (_reader, mut writer) = stream.into_split(); Err(e) => {
match writer.write_all(format!("{dt}").as_bytes()).await { 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(_) => {} Ok(_) => {}
Err(err) => { 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(()) 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
}