allow manual configuration update

This commit is contained in:
core 2023-03-30 17:34:00 -04:00
parent b084ef5fed
commit ba3b3a185f
Signed by: core
GPG Key ID: FDBF740DADDCEECF
10 changed files with 109 additions and 21 deletions

View File

@ -2,6 +2,5 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" /> <mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/dnapi" vcs="Git" />
</component> </component>
</project> </project>

2
Cargo.lock generated
View File

@ -2469,7 +2469,7 @@ dependencies = [
[[package]] [[package]]
name = "tfclient" name = "tfclient"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"base64 0.21.0", "base64 0.21.0",
"base64-serde", "base64-serde",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "tfclient" name = "tfclient"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
description = "An open-source reimplementation of a Defined Networking-compatible client" description = "An open-source reimplementation of a Defined Networking-compatible client"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"

View File

@ -0,0 +1,7 @@
# The port that the tfclient daemon should listen on for JSON RPC requests.
listen_port = 8157
# Set this to true in order to disable automatic callbacks back to the API server.
# Use this if you are using an API server which you do not completley trust.
# If this is enabled, you'll need to run `tfclient --update` to manually update your client configuration.
disable_automatic_config_updates = false

View File

@ -17,6 +17,7 @@ use crate::nebulaworker::NebulaWorkerMessage;
pub enum APIWorkerMessage { pub enum APIWorkerMessage {
Shutdown, Shutdown,
Enroll { code: String }, Enroll { code: String },
Update,
Timer Timer
} }
@ -33,7 +34,7 @@ pub fn apiworker_main(_config: TFClientConfig, instance: String, url: String, tx
info!("recv on command socket: shutdown, stopping"); info!("recv on command socket: shutdown, stopping");
break; break;
}, },
APIWorkerMessage::Timer => { APIWorkerMessage::Timer | APIWorkerMessage::Update => {
info!("updating config"); info!("updating config");
let mut cdata = match load_cdata(&instance) { let mut cdata = match load_cdata(&instance) {
Ok(c) => c, Ok(c) => c,

View File

@ -18,7 +18,9 @@ fn default_port() -> u16 { DEFAULT_PORT }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct TFClientConfig { pub struct TFClientConfig {
#[serde(default = "default_port")] #[serde(default = "default_port")]
pub listen_port: u16 pub listen_port: u16,
#[serde(default = "bool_false")]
pub disable_automatic_config_updates: bool
} }
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
@ -33,7 +35,8 @@ pub fn create_config(instance: &str) -> Result<(), Box<dyn Error>> {
fs::create_dir_all(get_config_dir(instance).ok_or("Unable to load config dir")?)?; fs::create_dir_all(get_config_dir(instance).ok_or("Unable to load config dir")?)?;
info!("Copying default config file to config directory..."); info!("Copying default config file to config directory...");
let config = TFClientConfig { let config = TFClientConfig {
listen_port: DEFAULT_PORT listen_port: DEFAULT_PORT,
disable_automatic_config_updates: false,
}; };
let config_str = toml::to_string(&config)?; let config_str = toml::to_string(&config)?;
fs::write(get_config_file(instance).ok_or("Unable to load config dir")?, config_str)?; fs::write(get_config_file(instance).ok_or("Unable to load config dir")?, config_str)?;

View File

@ -95,10 +95,23 @@ pub fn daemon_main(name: String, server: String) {
}); });
info!("Starting timer thread..."); info!("Starting timer thread...");
let timer_transmitter = transmitter.clone(); if !config.disable_automatic_config_updates {
let timer_thread = thread::spawn(move || { let timer_transmitter = transmitter.clone();
timer_main(timer_transmitter, rx_timer); let timer_thread = thread::spawn(move || {
}); timer_main(timer_transmitter, rx_timer);
});
info!("Waiting for timer thread to exit...");
match timer_thread.join() {
Ok(_) => (),
Err(_) => {
error!("Error waiting for timer thread to exit.");
std::process::exit(1);
}
}
info!("Timer thread exited");
} else {
info!("automatic config updates have been disabled - not starting timer thread");
}
info!("Starting socket worker thread..."); info!("Starting socket worker thread...");
let name_socket = name.clone(); let name_socket = name.clone();
@ -126,16 +139,6 @@ pub fn daemon_main(name: String, server: String) {
} }
info!("API thread exited"); info!("API thread exited");
info!("Waiting for timer thread to exit...");
match timer_thread.join() {
Ok(_) => (),
Err(_) => {
error!("Error waiting for timer thread to exit.");
std::process::exit(1);
}
}
info!("Timer thread exited");
info!("Waiting for Nebula thread to exit..."); info!("Waiting for Nebula thread to exit...");
match nebula_thread.join() { match nebula_thread.join() {
Ok(_) => (), Ok(_) => (),

View File

@ -123,6 +123,13 @@ enum Commands {
#[clap(short, long)] #[clap(short, long)]
/// Enrollment code used to enroll this node /// Enrollment code used to enroll this node
code: String, code: String,
},
/// Manually trigger a config update. It's useful to use this in combination with the `disable_automatic_config_updates` option.
Update {
#[clap(short, long, default_value = "tfclient")]
/// Service name specified on install
name: String,
} }
} }
@ -247,6 +254,23 @@ fn main() {
std::process::exit(1); std::process::exit(1);
} }
}; };
},
Commands::Update { name } => {
info!("Loading config...");
let config = match load_config(&name) {
Ok(cfg) => cfg,
Err(e) => {
error!("Error loading configuration: {}", e);
std::process::exit(1);
}
};
match socketclient::update(&config) {
Ok(_) => (),
Err(e) => {
error!("Error sending update request: {}", e);
std::process::exit(1);
}
};
} }
} }
} }

View File

@ -50,6 +50,49 @@ pub fn enroll(code: &str, config: &TFClientConfig) -> Result<(), Box<dyn Error>>
Ok(()) Ok(())
} }
pub fn update(config: &TFClientConfig) -> Result<(), Box<dyn Error>> {
info!("Connecting to local command socket...");
let mut stream = TcpStream::connect(SocketAddr::new(IpAddr::from([127, 0, 0, 1]), config.listen_port))?;
let stream2 = stream.try_clone()?;
let mut reader = BufReader::new(&stream2);
info!("Sending Hello...");
stream.write_all(&ctob(JsonMessage::Hello {
version: JSON_API_VERSION,
}))?;
info!("Waiting for hello...");
let msg = read_msg(&mut reader)?;
match msg {
JsonMessage::Hello { .. } => {
info!("Server sent hello, connection established")
}
JsonMessage::Goodbye { reason } => {
error!("Disconnected by server. Reason: {:?}", reason);
return Err("Disconnected by server".into());
}
_ => {
error!("Server returned unexpected message: {:?}", msg);
error!("Sending goodbye and exiting");
stream.write_all(&ctob(JsonMessage::Goodbye {
reason: DisconnectReason::UnexpectedMessageType,
}))?;
return Err("Unexpected message type by server".into());
}
}
info!("Sending enroll request...");
stream.write_all(&ctob(JsonMessage::Update {}))?;
info!("Sending disconnect...");
stream.write_all(&ctob(JsonMessage::Goodbye {
reason: DisconnectReason::Done,
}))?;
info!("Told tfclient daemon to trigger a configuration update. Check tfclient's logs to see if this was successful.");
Ok(())
}
fn read_msg(reader: &mut BufReader<&TcpStream>) -> Result<JsonMessage, Box<dyn Error>> { fn read_msg(reader: &mut BufReader<&TcpStream>) -> Result<JsonMessage, Box<dyn Error>> {
let mut str = String::new(); let mut str = String::new();
reader.read_line(&mut str)?; reader.read_line(&mut str)?;

View File

@ -241,6 +241,12 @@ fn senthello_handle(client: &mut Client, transmitter: &ThreadMessageSender, comm
info!("Client sent enroll with code {}", code); info!("Client sent enroll with code {}", code);
info!("Sending enroll request to apiworker"); info!("Sending enroll request to apiworker");
transmitter.api_thread.send(APIWorkerMessage::Enroll { code }).unwrap(); transmitter.api_thread.send(APIWorkerMessage::Enroll { code }).unwrap();
},
JsonMessage::Update {} => {
info!("Client sent update request.");
info!("Telling apiworker to update configuration");
transmitter.api_thread.send(APIWorkerMessage::Update).unwrap();
} }
_ => { _ => {
@ -290,7 +296,9 @@ pub enum JsonMessage {
#[serde(rename = "enroll")] #[serde(rename = "enroll")]
Enroll { Enroll {
code: String code: String
} },
#[serde(rename = "update")]
Update {}
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]