Files

76 lines
3.0 KiB
Rust

use regex::Regex;
use std::sync::OnceLock;
pub struct DataSanitizer;
static RE_HOME_PATH: OnceLock<Regex> = OnceLock::new();
static RE_USR_HOME_PATH: OnceLock<Regex> = OnceLock::new();
static RE_IPV4: OnceLock<Regex> = OnceLock::new();
static RE_MAC_ADDR: OnceLock<Regex> = OnceLock::new();
static RE_AUTH_TOKEN: OnceLock<Regex> = OnceLock::new();
static RE_UUID: OnceLock<Regex> = OnceLock::new();
impl DataSanitizer {
/// Очищает системные логи от персональных данных:
/// - Домашние пути (/home/<user>/ и /usr/home/<user>/ на BSD -> /home/[USER]/)
/// - IPv4 адреса (192.168.x.x, внешние IP)
/// - MAC-адреса
/// - Токены/секреты/пароли
/// - Аппаратные UUID
pub fn sanitize(raw: &str) -> String {
let home_re = RE_HOME_PATH.get_or_init(|| {
Regex::new(r"/home/[a-zA-Z0-9_\-]+").expect("Invalid home regex")
});
let usr_home_re = RE_USR_HOME_PATH.get_or_init(|| {
Regex::new(r"/usr/home/[a-zA-Z0-9_\-]+").expect("Invalid BSD usr home regex")
});
let ipv4_re = RE_IPV4.get_or_init(|| {
Regex::new(r"\b(?:\d{1,3}\.){3}\d{1,3}\b").expect("Invalid IPv4 regex")
});
let mac_re = RE_MAC_ADDR.get_or_init(|| {
Regex::new(r"(?i)\b([0-9a-f]{2}[:-]){5}([0-9a-f]{2})\b").expect("Invalid MAC regex")
});
let auth_re = RE_AUTH_TOKEN.get_or_init(|| {
Regex::new(r"(?i)(bearer|token|password|secret|api[_-]?key)[=:\s]+[A-Za-z0-9_\-\.\/]{8,}").expect("Invalid secret regex")
});
let uuid_re = RE_UUID.get_or_init(|| {
Regex::new(r"\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b").expect("Invalid UUID regex")
});
let mut clean = home_re.replace_all(raw, "/home/[USER]").to_string();
clean = usr_home_re.replace_all(&clean, "/home/[USER]").to_string();
clean = auth_re.replace_all(&clean, "$1=[REDACTED_SECRET]").to_string();
clean = mac_re.replace_all(&clean, "[MAC_ADDR]").to_string();
clean = uuid_re.replace_all(&clean, "[UUID]").to_string();
clean = ipv4_re.replace_all(&clean, |caps: &regex::Captures| {
let ip = &caps[0];
if ip.starts_with("127.") {
ip.to_string()
} else {
"[IP_ADDR]".to_string()
}
}).to_string();
clean
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sanitizer() {
let text = "Error for /usr/home/bsduser/file.txt and /home/linuxuser/app.rs at 10.0.0.4 with token=xyzSecret12345";
let clean = DataSanitizer::sanitize(text);
assert!(!clean.contains("bsduser"));
assert!(!clean.contains("linuxuser"));
assert!(!clean.contains("10.0.0.4"));
assert!(!clean.contains("xyzSecret12345"));
assert!(clean.contains("/home/[USER]"));
assert!(clean.contains("[IP_ADDR]"));
assert!(clean.contains("[REDACTED_SECRET]"));
}
}