Skip to main content

vv_agent/config/
api_keys.rs

1use base64::{engine::general_purpose, Engine as _};
2
3pub fn decode_api_key(raw_value: &str) -> String {
4    let raw = raw_value.trim();
5    if raw.is_empty() {
6        return raw.to_string();
7    }
8
9    if let Some(direct) = extract_suffix_key(raw) {
10        return direct;
11    }
12
13    if std::env::var("V_AGENT_ENABLE_BASE64_KEY_DECODE").as_deref() == Ok("1") {
14        if let Some(decoded) = maybe_base64_decode(raw) {
15            if let Some(from_decoded) = extract_suffix_key(&decoded) {
16                return from_decoded;
17            }
18            if looks_like_api_key(&decoded) {
19                return decoded;
20            }
21        }
22    }
23
24    raw.to_string()
25}
26
27fn extract_suffix_key(value: &str) -> Option<String> {
28    let (_, suffix) = value.split_once(':')?;
29    let suffix = suffix.trim();
30    looks_like_api_key(suffix).then(|| suffix.to_string())
31}
32
33fn maybe_base64_decode(value: &str) -> Option<String> {
34    let mut padded = value.to_string();
35    let remainder = padded.len() % 4;
36    if remainder != 0 {
37        padded.extend(std::iter::repeat_n('=', 4 - remainder));
38    }
39    let decoded = general_purpose::STANDARD.decode(padded).ok()?;
40    String::from_utf8(decoded).ok()
41}
42
43fn looks_like_api_key(value: &str) -> bool {
44    !value.is_empty() && value.len() >= 10 && !value.chars().any(char::is_whitespace)
45}