76 lines
3.0 KiB
Rust
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: ®ex::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]"));
|
|
}
|
|
}
|