use std::ffi::OsString;
const CREDENTIAL_SEGMENTS: &[&str] = &[
"KEY",
"KEYS",
"APIKEY",
"TOKEN",
"TOKENS",
"SECRET",
"SECRETS",
"PASSWORD",
"PASSWD",
"PAT",
"CREDENTIAL",
"CREDENTIALS",
];
fn is_credential_name(name: &str) -> bool {
name.split(['_', '-']).any(|part| {
CREDENTIAL_SEGMENTS
.iter()
.any(|seg| part.eq_ignore_ascii_case(seg))
})
}
pub fn credential_vars(named: &[String]) -> Vec<OsString> {
let mut out: Vec<OsString> = std::env::vars_os()
.map(|(k, _)| k)
.filter(|k| is_credential_name(&k.to_string_lossy()))
.collect();
for name in named {
let name = name.trim();
if name.is_empty() {
continue;
}
let name = OsString::from(name);
if !out.contains(&name) {
out.push(name);
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn credential_names_are_recognised_by_segment() {
for name in [
"OPENAI_API_KEY",
"openai_api_key",
"HF_TOKEN",
"GITHUB_TOKEN",
"AWS_SECRET_ACCESS_KEY",
"AWS_SESSION_TOKEN",
"DB_PASSWORD",
"GH_PAT",
"GOOGLE_APPLICATION_CREDENTIALS",
"MINDFORK-BACKUP-PASSWORD",
] {
assert!(is_credential_name(name), "{name} should be removed");
}
for name in [
"TOKENIZERS_PARALLELISM",
"PATH",
"CARGO_HOME",
"JAVA_HOME",
"VIRTUAL_ENV",
"HTTPS_PROXY",
"SSH_AUTH_SOCK",
"KEYBOARD_LAYOUT",
"PATTERN",
] {
assert!(!is_credential_name(name), "{name} must stay");
}
}
#[test]
fn named_variables_are_added_once() {
unsafe {
std::env::set_var("MINDFORK_TEST_PLAIN_NAME", "x");
std::env::set_var("MINDFORK_TEST_SECRET_KEY", "x");
}
let vars = credential_vars(&[
"MINDFORK_TEST_PLAIN_NAME".into(),
"MINDFORK_TEST_SECRET_KEY".into(),
" ".into(),
]);
let count = |needle: &str| {
vars.iter()
.filter(|v| v.to_string_lossy() == needle)
.count()
};
assert_eq!(count("MINDFORK_TEST_PLAIN_NAME"), 1);
assert_eq!(count("MINDFORK_TEST_SECRET_KEY"), 1, "{vars:?}");
assert!(!vars.iter().any(|v| v.is_empty()));
unsafe {
std::env::remove_var("MINDFORK_TEST_PLAIN_NAME");
std::env::remove_var("MINDFORK_TEST_SECRET_KEY");
}
}
}