Compare commits
No commits in common. "46cf2f457282e0e6e5b3b8b54895917b1bbcd4d9" and "164c71ddfee36299d0a8c445f7fe41736e71d56c" have entirely different histories.
46cf2f4572
...
164c71ddfe
7 changed files with 9 additions and 113 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -3582,7 +3582,6 @@ dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-client-ip",
|
"axum-client-ip",
|
||||||
"based",
|
"based",
|
||||||
"chrono",
|
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"hex",
|
"hex",
|
||||||
"http2",
|
"http2",
|
||||||
|
@ -3597,7 +3596,6 @@ dependencies = [
|
||||||
"toml 0.8.22",
|
"toml 0.8.22",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"ulid",
|
|
||||||
"ureq",
|
"ureq",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -36,5 +36,3 @@ ureq = { version = "3.0.11", features = ["json"] }
|
||||||
rumqttc = { version = "0.24.0", features = ["url", "websocket"] }
|
rumqttc = { version = "0.24.0", features = ["url", "websocket"] }
|
||||||
sage = { git = "https://git.hydrar.de/jmarya/sage" }
|
sage = { git = "https://git.hydrar.de/jmarya/sage" }
|
||||||
dashmap = "6.1.0"
|
dashmap = "6.1.0"
|
||||||
ulid = { version = "1.2.1", features = ["serde"] }
|
|
||||||
chrono = "0.4.41"
|
|
||||||
|
|
40
src/api.rs
40
src/api.rs
|
@ -105,43 +105,3 @@ impl Result {
|
||||||
Self { ok: 0 }
|
Self { ok: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct ClientAction {
|
|
||||||
pub id: ulid::Ulid,
|
|
||||||
pub action: ClientActions,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientAction {
|
|
||||||
pub fn new(action: ClientActions) -> Self {
|
|
||||||
Self {
|
|
||||||
id: ulid::Ulid::new(),
|
|
||||||
action,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum ClientActions {
|
|
||||||
OSQuery(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct ServerResponse {
|
|
||||||
pub id: ulid::Ulid,
|
|
||||||
pub response: ServerResponses,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ServerResponse {
|
|
||||||
pub fn of(client: &ClientAction, resp: ServerResponses) -> Self {
|
|
||||||
Self {
|
|
||||||
id: client.id,
|
|
||||||
response: resp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum ServerResponses {
|
|
||||||
OSQuery(String),
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ use axum::{
|
||||||
};
|
};
|
||||||
use axum_client_ip::ClientIpSource;
|
use axum_client_ip::ClientIpSource;
|
||||||
use based::auth::User;
|
use based::auth::User;
|
||||||
use dashmap::DashMap;
|
|
||||||
use owl::{prelude::*, set_global_db};
|
use owl::{prelude::*, set_global_db};
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use std::{net::SocketAddr, path::PathBuf};
|
use std::{net::SocketAddr, path::PathBuf};
|
||||||
|
@ -22,8 +21,6 @@ use tokio::sync::OnceCell;
|
||||||
pub static IDENTITY: OnceCell<Identity> = OnceCell::const_new();
|
pub static IDENTITY: OnceCell<Identity> = OnceCell::const_new();
|
||||||
pub static CONFIG: OnceCell<Config> = OnceCell::const_new();
|
pub static CONFIG: OnceCell<Config> = OnceCell::const_new();
|
||||||
|
|
||||||
pub static ONLINE: OnceCell<DashMap<String, chrono::DateTime<chrono::Utc>>> = OnceCell::const_new();
|
|
||||||
|
|
||||||
fn generate_token() -> String {
|
fn generate_token() -> String {
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
let mut token = vec![0u8; 32];
|
let mut token = vec![0u8; 32];
|
||||||
|
@ -47,8 +44,6 @@ async fn main() {
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let _ = crate::CONFIG.set(config);
|
let _ = crate::CONFIG.set(config);
|
||||||
|
|
||||||
crate::ONLINE.set(DashMap::new()).unwrap();
|
|
||||||
|
|
||||||
let db = Database::filesystem("./herd/db");
|
let db = Database::filesystem("./herd/db");
|
||||||
set_global_db!(db);
|
set_global_db!(db);
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::Machine;
|
use crate::Machine;
|
||||||
use crate::api::{ClientAction, ClientActions, ServerResponse};
|
|
||||||
use owl::prelude::*;
|
use owl::prelude::*;
|
||||||
use owl::{Serialize, get, query};
|
use owl::{Serialize, get, query};
|
||||||
use rumqttc::AsyncClient;
|
use rumqttc::AsyncClient;
|
||||||
use sage::PersonaIdentity;
|
use sage::PersonaIdentity;
|
||||||
|
|
||||||
fn is_within_80_seconds(time: chrono::DateTime<chrono::Utc>) -> bool {
|
|
||||||
let now = chrono::Utc::now();
|
|
||||||
now.signed_duration_since(time).num_seconds() <= 80
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handle herd MQTT
|
/// Handle herd MQTT
|
||||||
pub async fn handle_mqtt(topic: String, data: Vec<u8>) {
|
pub async fn handle_mqtt(topic: String, data: Vec<u8>) {
|
||||||
log::info!("Received client request from {topic}");
|
log::info!("Received client request from {topic}");
|
||||||
|
@ -25,25 +17,11 @@ pub async fn handle_mqtt(topic: String, data: Vec<u8>) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// TODO : check for recency
|
// TODO : check for recency
|
||||||
|
println!("got raw: {}", String::from_utf8(dec.payload).unwrap());
|
||||||
|
|
||||||
match cat {
|
match cat {
|
||||||
"online" => {
|
"online" => {
|
||||||
if let Some(online) = crate::ONLINE.get().unwrap().get(client) {
|
log::info!("Device {client} reported ONLINE");
|
||||||
if !is_within_80_seconds(*online) {
|
|
||||||
log::info!("Device {client} came back ONLINE");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log::info!("Device {client} went ONLINE");
|
|
||||||
}
|
|
||||||
crate::ONLINE
|
|
||||||
.get()
|
|
||||||
.unwrap()
|
|
||||||
.insert(client.to_string(), chrono::Utc::now());
|
|
||||||
}
|
|
||||||
"respond" => {
|
|
||||||
let resp: ServerResponse = serde_json::from_slice(&dec.payload).unwrap();
|
|
||||||
|
|
||||||
log::info!("Got response {:?}", resp);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -75,10 +53,6 @@ pub async fn listen_to_device(client: &AsyncClient, machine_id: &str) {
|
||||||
.subscribe(format!("{machine_id}/online"), rumqttc::QoS::AtMostOnce)
|
.subscribe(format!("{machine_id}/online"), rumqttc::QoS::AtMostOnce)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
client
|
|
||||||
.subscribe(format!("{machine_id}/respond"), rumqttc::QoS::AtMostOnce)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subscibe to incoming messages from all registered machines
|
/// Subscibe to incoming messages from all registered machines
|
||||||
|
|
|
@ -44,8 +44,6 @@ pub async fn join_device(
|
||||||
let machine = Machine::from_join_param(payload);
|
let machine = Machine::from_join_param(payload);
|
||||||
let new_token = machine.token.clone();
|
let new_token = machine.token.clone();
|
||||||
|
|
||||||
// TODO : add device listener instantly
|
|
||||||
|
|
||||||
save!(machine);
|
save!(machine);
|
||||||
|
|
||||||
let i = crate::IDENTITY.get().unwrap();
|
let i = crate::IDENTITY.get().unwrap();
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
use std::{os, process::Stdio};
|
|
||||||
|
|
||||||
use owl::Serialize;
|
use owl::Serialize;
|
||||||
use rumqttc::AsyncClient;
|
use rumqttc::AsyncClient;
|
||||||
use sage::PersonaIdentity;
|
use sage::PersonaIdentity;
|
||||||
|
|
||||||
use crate::api::{ClientAction, ServerResponse, ServerResponses};
|
|
||||||
|
|
||||||
// Client MQTT
|
// Client MQTT
|
||||||
pub async fn handle_mqtt(topic: String, data: Vec<u8>) {
|
pub async fn handle_mqtt(topic: String, data: Vec<u8>) {
|
||||||
//println!("got real raw: {}", String::from_utf8_lossy(&data));
|
//println!("got real raw: {}", String::from_utf8_lossy(&data));
|
||||||
|
@ -15,38 +11,15 @@ pub async fn handle_mqtt(topic: String, data: Vec<u8>) {
|
||||||
);
|
);
|
||||||
let pk = pk.sign_key().unwrap();
|
let pk = pk.sign_key().unwrap();
|
||||||
let payload = crate::IDENTITY.get().unwrap().decrypt(&data, &pk).unwrap();
|
let payload = crate::IDENTITY.get().unwrap().decrypt(&data, &pk).unwrap();
|
||||||
|
println!(
|
||||||
let action: ClientAction = serde_json::from_slice(&payload.payload).unwrap();
|
"got payload {}",
|
||||||
log::info!("Got action {action:?}");
|
String::from_utf8(payload.payload).unwrap()
|
||||||
|
);
|
||||||
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`
|
/// Send something back to the server on `topic`
|
||||||
pub async fn send_back<T: Serialize>(client: &AsyncClient, topic: &str, data: T) {
|
pub async fn send_back<T: Serialize>(client: &AsyncClient, topic: &str, request: T) {
|
||||||
let data = serde_json::to_string(&data).unwrap();
|
let data = serde_json::to_string(&request).unwrap();
|
||||||
|
|
||||||
let pk = crate::AGENT.get().unwrap();
|
let pk = crate::AGENT.get().unwrap();
|
||||||
let pk = (pk.server_age.clone(), String::new());
|
let pk = (pk.server_age.clone(), String::new());
|
||||||
|
@ -62,7 +35,7 @@ pub async fn send_back<T: Serialize>(client: &AsyncClient, topic: &str, data: T)
|
||||||
.encrypt(data.as_bytes(), &rec);
|
.encrypt(data.as_bytes(), &rec);
|
||||||
let topic = format!("{machine_id}/{topic}");
|
let topic = format!("{machine_id}/{topic}");
|
||||||
|
|
||||||
log::info!("Publish to {topic}");
|
log::info!("Publish to {machine_id}{topic}");
|
||||||
client
|
client
|
||||||
.publish(topic, rumqttc::QoS::AtMostOnce, true, payload)
|
.publish(topic, rumqttc::QoS::AtMostOnce, true, payload)
|
||||||
.await
|
.await
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue