sheepd/src/sheepd_core/mqtt.rs
2025-04-30 16:28:48 +02:00

70 lines
2 KiB
Rust

use std::{os, process::Stdio};
use owl::Serialize;
use rumqttc::AsyncClient;
use sage::PersonaIdentity;
use crate::api::{ClientAction, ServerResponse, ServerResponses};
// Client MQTT
pub async fn handle_mqtt(topic: String, data: Vec<u8>) {
//println!("got real raw: {}", String::from_utf8_lossy(&data));
let pk = (
String::new(),
crate::AGENT.get().unwrap().server_sign.clone(),
);
let pk = pk.sign_key().unwrap();
let payload = crate::IDENTITY.get().unwrap().decrypt(&data, &pk).unwrap();
let action: ClientAction = serde_json::from_slice(&payload.payload).unwrap();
log::info!("Got action {action:?}");
match &action.action {
crate::api::ClientActions::OSQuery(query) => {
// TODO : run osquery
log::info!("Doing osquery with {query}");
let res = osquery(&query);
send_back(
crate::MQTT.get().unwrap(),
"respond",
ServerResponse::of(&action, ServerResponses::OSQuery(res)),
)
.await;
}
}
}
pub fn osquery(query: &str) -> String {
let cmd = std::process::Command::new("osqueryi")
.arg("--csv")
.arg(query)
.stdout(Stdio::piped())
.output()
.unwrap();
String::from_utf8(cmd.stdout).unwrap()
}
/// Send something back to the server on `topic`
pub async fn send_back<T: Serialize>(client: &AsyncClient, topic: &str, data: T) {
let data = serde_json::to_string(&data).unwrap();
let pk = crate::AGENT.get().unwrap();
let pk = (pk.server_age.clone(), String::new());
let rec = pk.enc_key().unwrap();
let machine_id = std::fs::read_to_string("/etc/machine-id")
.unwrap()
.trim()
.to_string();
let payload = crate::IDENTITY
.get()
.unwrap()
.encrypt(data.as_bytes(), &rec);
let topic = format!("{machine_id}/{topic}");
log::info!("Publish to {machine_id}{topic}");
client
.publish(topic, rumqttc::QoS::AtMostOnce, true, payload)
.await
.unwrap();
}