92 lines
2.9 KiB
Rust
92 lines
2.9 KiB
Rust
use std::process::Stdio;
|
|
|
|
use owl::Serialize;
|
|
use rumqttc::AsyncClient;
|
|
use sage::PersonaIdentity;
|
|
|
|
use crate::api::{ClientAction, ServerResponse, ServerResponses, ShellResponse};
|
|
|
|
// 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;
|
|
}
|
|
crate::api::ClientActions::Shell(cmd, cwd) => {
|
|
log::info!("Received shell command: {cmd} in {cwd}");
|
|
let res = std::process::Command::new("sh")
|
|
.arg("-c")
|
|
.arg(cmd)
|
|
.current_dir(cwd)
|
|
.output()
|
|
.unwrap();
|
|
send_back(
|
|
crate::MQTT.get().unwrap(),
|
|
"respond",
|
|
ServerResponse::of(
|
|
&action,
|
|
ServerResponses::Shell(ShellResponse {
|
|
stdout: String::from_utf8_lossy(&res.stdout).to_string(),
|
|
stderr: String::from_utf8_lossy(&res.stderr).to_string(),
|
|
status: res.status.code().unwrap(),
|
|
}),
|
|
),
|
|
)
|
|
.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 {topic}");
|
|
client
|
|
.publish(topic, rumqttc::QoS::AtMostOnce, true, payload)
|
|
.await
|
|
.unwrap();
|
|
}
|