use clap::ValueEnum;
use crate::model::{KbEntry, KnowledgeBase};
use crate::parser::Command;
const EMBEDDED_LINUX: &str = include_str!("../data/knowledge.json");
const EMBEDDED_WINDOWS: &str = include_str!("../data/knowledge-windows.json");
const EMBEDDED_MACOS: &str = include_str!("../data/knowledge-macos.json");
#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
pub enum Platform {
#[value(name = "linux-auditd", alias = "linux")]
LinuxAuditd,
#[value(name = "windows-sysmon", alias = "windows")]
WindowsSysmon,
#[value(name = "macos-es", alias = "macos")]
MacosEs,
}
impl Platform {
pub fn sigma_product(self) -> &'static str {
match self {
Platform::LinuxAuditd => "linux",
Platform::WindowsSysmon => "windows",
Platform::MacosEs => "macos",
}
}
}
pub fn load(platform: Platform) -> Result<KnowledgeBase, serde_json::Error> {
let raw = match platform {
Platform::LinuxAuditd => EMBEDDED_LINUX,
Platform::WindowsSysmon => EMBEDDED_WINDOWS,
Platform::MacosEs => EMBEDDED_MACOS,
};
serde_json::from_str(raw)
}
pub fn command_entry_matches(entry: &KbEntry, cmd: &Command) -> bool {
let Some(want) = &entry.command else {
return false;
};
if cmd.program.to_lowercase() != want.to_lowercase() {
return false;
}
if let Some(sub) = &entry.args_contains
&& !cmd.args_joined().contains(&sub.to_lowercase())
{
return false;
}
if let Some(rc) = &entry.raw_contains
&& !cmd.raw.to_lowercase().contains(&rc.to_lowercase())
{
return false;
}
true
}
pub fn raw_entry_matches(entry: &KbEntry, raw_line: &str) -> bool {
if entry.command.is_some() {
return false;
}
match &entry.raw_contains {
Some(rc) => raw_line.to_lowercase().contains(&rc.to_lowercase()),
None => false,
}
}