1use std::borrow::Cow;
10use std::sync::LazyLock;
11use std::sync::atomic::{AtomicBool, Ordering};
12
13pub const PREFIX: &str = "DRE_SECRET_";
14pub const MASK: &str = "*****";
15const MIN_LEN: usize = 4;
16
17static ENABLED: AtomicBool = AtomicBool::new(true);
18
19static SECRETS: LazyLock<Vec<String>> = LazyLock::new(|| {
21 let mut v: Vec<String> = std::env::vars()
22 .filter(|(k, v)| k.starts_with(PREFIX) && v.chars().count() >= MIN_LEN)
23 .map(|(_, v)| v)
24 .collect();
25 v.sort_by_key(|s| std::cmp::Reverse(s.len()));
26 v.dedup();
27 v
28});
29
30pub fn set_enabled(on: bool) {
31 ENABLED.store(on, Ordering::Relaxed);
32}
33
34pub fn mask(s: &str) -> Cow<'_, str> {
36 if !ENABLED.load(Ordering::Relaxed) || !SECRETS.iter().any(|x| s.contains(x.as_str())) {
37 return Cow::Borrowed(s);
38 }
39 let mut out = s.to_string();
40 for x in SECRETS.iter() {
41 out = out.replace(x.as_str(), MASK);
42 }
43 Cow::Owned(out)
44}