mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2026-10-25 14:20:05 -05:00
Preserve API credentials across config updates
This commit is contained in:
1 parent
bfc1d3f2d9
commit
dd5ed5d15b
4 files changed
+81
-16
No files matched your search
@@ -647,6 +647,11 @@ pub enum BusRequest {
|
||||
|
||||
/// Retrieve current Insight license summary (licensed + optional max circuits).
|
||||
GetInsightLicenseSummary,
|
||||
|
||||
/// Update configuration while preserving authoritative API credentials.
|
||||
///
|
||||
/// This variant is appended to preserve existing bincode discriminants.
|
||||
UpdateLqosdConfigPreserveApiCredentials(Box<lqos_config::Config>),
|
||||
}
|
||||
|
||||
impl BusRequest {
|
||||
@@ -756,6 +761,9 @@ impl BusRequest {
|
||||
Self::GetGlobalWarnings => "GetGlobalWarnings",
|
||||
Self::GetLtsCapabilities => "GetLtsCapabilities",
|
||||
Self::GetInsightLicenseSummary => "GetInsightLicenseSummary",
|
||||
Self::UpdateLqosdConfigPreserveApiCredentials(_) => {
|
||||
"UpdateLqosdConfigPreserveApiCredentials"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,12 @@ async fn handle_requests_with_deadline_for_duration(
|
||||
) -> BusReply {
|
||||
let request_count = requests.len();
|
||||
let request_kinds = requests.iter().map(BusRequest::kind).collect::<Vec<_>>();
|
||||
debug!(
|
||||
source = request_source,
|
||||
request_count,
|
||||
request_kinds = %request_kind_summary(&request_kinds),
|
||||
"Handling bus request"
|
||||
);
|
||||
let can_fail_fast = requests.iter().all(BusRequest::can_fail_fast_on_timeout);
|
||||
let start = Instant::now();
|
||||
let mut handler = spawn_blocking(move || {
|
||||
@@ -331,8 +337,6 @@ impl UnixSocketServer {
|
||||
warn!("Invalid data on local socket");
|
||||
break;
|
||||
};
|
||||
debug!("Received request: {:?}", request);
|
||||
|
||||
// Handle the request and build the response
|
||||
let response = handle_requests_with_deadline(
|
||||
handle_bus_requests,
|
||||
|
||||
+33
-12
@@ -509,6 +509,21 @@ fn memory_debug() {
|
||||
#[cfg(not(feature = "flamegraphs"))]
|
||||
fn memory_debug() {}
|
||||
|
||||
fn update_lqosd_config_from_bus(config: &lqos_config::Config) -> BusResponse {
|
||||
match lqos_config::update_config(config) {
|
||||
Ok(()) => {
|
||||
if let Ok(cfg) = lqos_config::load_config() {
|
||||
let _ = stick::recompute_stick_offset(&cfg);
|
||||
}
|
||||
BusResponse::Ack
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Error updating config: {err:?}");
|
||||
BusResponse::Fail(err.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_bus_requests(requests: &[BusRequest], responses: &mut Vec<BusResponse>) {
|
||||
for req in requests.iter() {
|
||||
//println!("Request: {:?}", req);
|
||||
@@ -612,18 +627,7 @@ fn handle_bus_requests(requests: &[BusRequest], responses: &mut Vec<BusResponse>
|
||||
lqos_bus::BusResponse::Ack
|
||||
}
|
||||
BusRequest::UpdateLqosDTuning(..) => tuning::tune_lqosd_from_bus(req),
|
||||
BusRequest::UpdateLqosdConfig(config) => match lqos_config::update_config(config) {
|
||||
Ok(()) => {
|
||||
if let Ok(cfg) = lqos_config::load_config() {
|
||||
let _ = stick::recompute_stick_offset(&cfg);
|
||||
}
|
||||
BusResponse::Ack
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Error updating config: {err:?}");
|
||||
BusResponse::Fail(err.to_string())
|
||||
}
|
||||
},
|
||||
BusRequest::UpdateLqosdConfig(config) => update_lqosd_config_from_bus(config),
|
||||
BusRequest::CreateDynamicCircuit { shaped_device } => {
|
||||
crate::dynamic_circuits::create_dynamic_circuit((**shaped_device).clone())
|
||||
}
|
||||
@@ -1198,6 +1202,23 @@ fn handle_bus_requests(requests: &[BusRequest], responses: &mut Vec<BusResponse>
|
||||
max_circuits,
|
||||
})
|
||||
}
|
||||
BusRequest::UpdateLqosdConfigPreserveApiCredentials(config) => {
|
||||
let _guard =
|
||||
node_manager::local_api::local_api_keys::lock_config_update_blocking();
|
||||
match lqos_config::load_config() {
|
||||
Ok(current) => {
|
||||
let config = node_manager::local_api::local_api_keys::preserve_api_credentials(
|
||||
(**config).clone(),
|
||||
¤t,
|
||||
);
|
||||
update_lqosd_config_from_bus(&config)
|
||||
}
|
||||
Err(error) => {
|
||||
error!("Unable to load config while preserving local API keys: {error:?}");
|
||||
BusResponse::Fail(error.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,14 @@ pub(crate) fn lock_config_update_blocking() -> MutexGuard<'static, ()> {
|
||||
CONFIG_UPDATE_LOCK.blocking_lock()
|
||||
}
|
||||
|
||||
/// Replaces a proposed configuration's API credentials with the current
|
||||
/// authoritative local API section and Insight/API license key.
|
||||
pub(crate) fn preserve_api_credentials(mut proposed: Config, current: &Config) -> Config {
|
||||
proposed.local_api = current.local_api.clone();
|
||||
proposed.long_term_stats.license_key = current.long_term_stats.license_key.clone();
|
||||
proposed
|
||||
}
|
||||
|
||||
/// Persists an updated configuration through `lqosd`'s local bus.
|
||||
pub(super) async fn persist_config(config: Config) -> Result<(), String> {
|
||||
let mut responses = bus_request_with_timeout(
|
||||
@@ -243,8 +251,8 @@ pub async fn remove_legacy(login: LoginResult) -> Result<(), String> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
append_key, build_key, create, remove_legacy, remove_legacy_from_config, revoke,
|
||||
revoke_from_config,
|
||||
append_key, build_key, create, preserve_api_credentials, remove_legacy,
|
||||
remove_legacy_from_config, revoke, revoke_from_config,
|
||||
};
|
||||
use crate::node_manager::auth::LoginResult;
|
||||
use lqos_config::{Config, MAX_LOCAL_API_KEYS};
|
||||
@@ -349,4 +357,28 @@ mod tests {
|
||||
Err("Unauthorized".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_config_updates_preserve_authoritative_api_credentials() {
|
||||
let mut current = Config::default();
|
||||
current.local_api.bearer_token = Some("legacy".to_string());
|
||||
let creation = append_key(&mut current, "Monitor", Uuid::from_u128(7), &[7; 32], 7)
|
||||
.expect("fixture key should be valid");
|
||||
let mut proposed = Config::default();
|
||||
proposed.local_api.bearer_token = Some("replacement".to_string());
|
||||
|
||||
current.long_term_stats.license_key = Some("license-secret".to_string());
|
||||
proposed.long_term_stats.license_key = Some("replacement-license".to_string());
|
||||
let merged = preserve_api_credentials(proposed, ¤t);
|
||||
assert_eq!(merged.local_api, current.local_api);
|
||||
assert_eq!(
|
||||
merged.long_term_stats.license_key,
|
||||
current.long_term_stats.license_key
|
||||
);
|
||||
assert!(
|
||||
!toml::to_string(&merged)
|
||||
.expect("config should serialize")
|
||||
.contains(&creation.api_key)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user