trifid/tfclient/src/apiworker.rs

223 lines
9.1 KiB
Rust

use std::fs;
use std::sync::mpsc::Receiver;
use dnapi_rs::client_blocking::Client;
use log::{error, info, warn};
use url::Url;
use crate::config::{load_cdata, save_cdata, TFClientConfig};
use crate::daemon::ThreadMessageSender;
use crate::dirs::nebula_yml;
use crate::nebulaworker::NebulaWorkerMessage;
pub enum APIWorkerMessage {
Shutdown,
Enroll { code: String },
Update,
Timer,
}
pub fn apiworker_main(
_config: TFClientConfig,
instance: String,
url: String,
tx: ThreadMessageSender,
rx: Receiver<APIWorkerMessage>,
) {
let server = Url::parse(&url).unwrap();
let client = Client::new(format!("tfclient/{}", env!("CARGO_PKG_VERSION")), server).unwrap();
loop {
match rx.recv() {
Ok(msg) => {
match msg {
APIWorkerMessage::Shutdown => {
info!("recv on command socket: shutdown, stopping");
break;
}
APIWorkerMessage::Timer | APIWorkerMessage::Update => {
info!("updating config");
let mut cdata = match load_cdata(&instance) {
Ok(c) => c,
Err(e) => {
error!("error in api worker thread: {}", e);
error!("APIWorker exiting with error");
return;
}
};
if cdata.creds.is_none() {
info!("not enrolled, cannot perform config update");
match save_cdata(&instance, cdata) {
Ok(_) => (),
Err(e) => {
error!("Error saving cdata: {}", e);
error!("APIWorker exiting with error");
return;
}
}
continue;
}
let creds = cdata.clone().creds.unwrap_or_else(|| unreachable!());
info!("checking for update");
let update_available = match client.check_for_update(&creds) {
Ok(ua) => ua,
Err(e) => {
error!("error checking for config update: {}", e);
match save_cdata(&instance, cdata) {
Ok(_) => (),
Err(e) => {
error!("Error saving cdata: {}", e);
error!("APIWorker exiting with error");
return;
}
}
continue;
}
};
if !update_available {
match save_cdata(&instance, cdata) {
Ok(_) => (),
Err(e) => {
error!("Error saving cdata: {}", e);
error!("APIWorker exiting with error");
return;
}
}
info!("no config update available");
continue;
}
info!("updated configuration is avaliable");
info!("updating configuration");
let (config, dh_privkey, creds) = match client.do_update(&creds) {
Ok(d) => d,
Err(e) => {
error!("error requesting updated config: {}", e);
match save_cdata(&instance, cdata) {
Ok(_) => (),
Err(e) => {
error!("Error saving cdata: {}", e);
error!("APIWorker exiting with error");
return;
}
}
continue;
}
};
cdata.creds = Some(creds);
cdata.dh_privkey = Some(dh_privkey);
match fs::write(
nebula_yml(&instance),
config,
) {
Ok(_) => (),
Err(e) => {
error!("unable to save nebula config: {}", e);
match save_cdata(&instance, cdata) {
Ok(_) => (),
Err(e) => {
error!("Error saving cdata: {}", e);
error!("APIWorker exiting with error");
return;
}
}
continue;
}
}
match save_cdata(&instance, cdata) {
Ok(_) => (),
Err(e) => {
error!("Error saving cdata: {}", e);
error!("APIWorker exiting with error");
return;
}
}
info!("configuration updated successfully!");
info!("sending signal to nebula thread to reload config");
match tx.nebula_thread.send(NebulaWorkerMessage::ConfigUpdated) {
Ok(_) => (),
Err(e) => {
error!("unable to tell nebula thread to update config: {}", e);
error!("APIWorker exiting with error");
return;
}
}
}
APIWorkerMessage::Enroll { code } => {
info!("recv on command socket: enroll {}", code);
let mut cdata = match load_cdata(&instance) {
Ok(c) => c,
Err(e) => {
error!("error in api worker thread: {}", e);
error!("APIWorker exiting with error");
return;
}
};
if cdata.creds.is_some() {
warn!("enrollment failed: already enrolled");
continue;
}
let (config, dh_privkey, creds, meta) = match client.enroll(&code) {
Ok(resp) => resp,
Err(e) => {
error!("error with enrollment request: {}", e);
continue;
}
};
match fs::write(
nebula_yml(&instance),
config,
) {
Ok(_) => (),
Err(e) => {
error!("unable to save nebula config: {}", e);
continue;
}
}
cdata.creds = Some(creds);
cdata.dh_privkey = Some(dh_privkey);
cdata.meta = Some(meta);
// Save vardata
match save_cdata(&instance, cdata) {
Ok(_) => (),
Err(e) => {
error!("Error saving cdata: {}", e);
error!("APIWorker exiting with error");
return;
}
}
info!("Configuration updated. Sending signal to Nebula worker thread");
match tx.nebula_thread.send(NebulaWorkerMessage::ConfigUpdated) {
Ok(_) => (),
Err(e) => {
error!("unable to tell nebula thread to update config: {}", e);
error!("APIWorker exiting with error");
return;
}
}
}
}
}
Err(e) => {
error!("error on command socket: {}", e);
return;
}
}
}
}