use crate::model::KnowledgeBase;
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)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
pub enum Platform {
#[cfg_attr(feature = "clap", value(name = "linux-auditd", alias = "linux"))]
LinuxAuditd,
#[cfg_attr(feature = "clap", value(name = "windows-sysmon", alias = "windows"))]
WindowsSysmon,
#[cfg_attr(feature = "clap", 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",
}
}
}
#[derive(Debug)]
pub enum KbError {
Parse(serde_json::Error),
Invalid(String),
}
impl std::fmt::Display for KbError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
KbError::Parse(e) => write!(f, "malformed knowledge base: {e}"),
KbError::Invalid(m) => write!(f, "invalid knowledge base: {m}"),
}
}
}
impl std::error::Error for KbError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
KbError::Parse(e) => Some(e),
KbError::Invalid(_) => None,
}
}
}
impl From<serde_json::Error> for KbError {
fn from(e: serde_json::Error) -> Self {
KbError::Parse(e)
}
}
pub fn load(platform: Platform) -> Result<KnowledgeBase, KbError> {
let raw = match platform {
Platform::LinuxAuditd => EMBEDDED_LINUX,
Platform::WindowsSysmon => EMBEDDED_WINDOWS,
Platform::MacosEs => EMBEDDED_MACOS,
};
let kb: KnowledgeBase = serde_json::from_str(raw)?;
kb.validate().map_err(KbError::Invalid)?;
Ok(kb)
}