diff --git a/trifid-api/src/routes/v1/dnclient.rs b/trifid-api/src/routes/v1/dnclient.rs index 3581fcd..8ed8cfc 100644 --- a/trifid-api/src/routes/v1/dnclient.rs +++ b/trifid-api/src/routes/v1/dnclient.rs @@ -13,13 +13,14 @@ use log::{error, warn}; use std::clone::Clone; use std::time::{SystemTime, UNIX_EPOCH}; use sea_orm::{ActiveModelTrait, EntityTrait}; -use trifid_pki::cert::{deserialize_ed25519_public, deserialize_x25519_public}; +use trifid_pki::cert::{deserialize_ed25519_public, deserialize_nebula_certificate_from_pem, deserialize_x25519_public}; use trifid_api_entities::entity::{host, keystore_entry, keystore_host}; use crate::error::APIErrorsResponse; use sea_orm::{ColumnTrait, QueryFilter, IntoActiveModel}; use sea_orm::ActiveValue::Set; use crate::AppState; +use crate::config::NebulaConfig; use crate::tokens::random_id; #[post("/v1/dnclient")] @@ -217,9 +218,42 @@ pub async fn dnclient( }; let current_cfg = keystore_data.config; - let generated_config_string = serde_yaml::to_string(&cfg).unwrap(); + let current_cfg: NebulaConfig = match serde_yaml::from_str(¤t_cfg) { + Ok(cfg) => cfg, + Err(e) => { + error!("error loading old configuration: {}", e); + return HttpResponse::InternalServerError().json(EnrollResponse::Error { + errors: vec![APIError { + code: "ERR_CFG_GENERATION_ERROR".to_string(), + message: "There was an error generating the host configuration.".to_string(), + path: None, + }], + }); + } + }; - let config_update_avail = current_cfg != generated_config_string || req.counter < keystore_header.counter as u32; + let mut config_is_different = current_cfg == cfg; + + if config_is_different { + // check if it is a certificate issue + let c0 = current_cfg.clone(); + let mut c1 = cfg.clone(); + c1.pki.cert = c0.pki.cert.clone(); + if c0 == c1 { + // its just the cert. deserialize both and check if any details have changed + let cert0 = deserialize_nebula_certificate_from_pem(c0.pki.cert.as_bytes()).expect("generated an invalid certificate"); + let mut cert1 = deserialize_nebula_certificate_from_pem(c1.pki.cert.as_bytes()).expect("generated an invalid certificate"); + cert1.details.not_before = cert0.details.not_before; + cert1.details.not_after = cert0.details.not_after; + if cert0.serialize_to_pem().expect("generated invalid cert") == cert1.serialize_to_pem().expect("generated invalid cert") { + // fake news! its fine actually + config_is_different = false; + } + // if anything else changed, we still want to issue the update + } + } + + let config_update_avail = config_is_different || req.counter < keystore_header.counter as u32; host_am.last_out_of_date = Set(config_update_avail); host_am.last_seen_at = Set(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64);