o_sfu/config/
diagnostics.rs1use anyhow::{Result, ensure};
2use secrecy::{ExposeSecret, SecretString};
3
4use super::env::Env;
5
6const MIN_TOKEN_BYTES: usize = 32;
7
8#[derive(Debug, Clone, Default)]
9pub struct DiagnosticsConfig {
10 pub auth_token: Option<SecretString>,
15}
16
17impl DiagnosticsConfig {
18 pub(super) fn from_env(env: &Env<'_>) -> Result<Self> {
19 let auth_token = env
20 .var("DIAGNOSTICS_AUTH_TOKEN")
21 .exclusive_file("DIAGNOSTICS_AUTH_TOKEN_FILE")
22 .check(|key, value: SecretString| {
23 let token = value.expose_secret().trim();
24 validate_token(key, token)?;
25 if token.len() == value.expose_secret().len() {
26 Ok(value)
27 } else {
28 Ok(SecretString::from(token))
29 }
30 })
31 .optional()?;
32 Ok(Self { auth_token })
33 }
34
35 pub(crate) fn validate(&self) -> Result<()> {
42 if let Some(token) = &self.auth_token {
43 validate_token("DIAGNOSTICS_AUTH_TOKEN", token.expose_secret().trim())?;
44 }
45 Ok(())
46 }
47}
48
49fn validate_token(key: &'static str, token: &str) -> Result<()> {
50 ensure!(!token.is_empty(), "{key} must not be empty");
51 ensure!(
53 token
54 .bytes()
55 .all(|byte| byte == b'\t' || (b' '..=b'~').contains(&byte)),
56 "{key} contains invalid HTTP header-value characters"
57 );
58 ensure!(
59 token.len() >= MIN_TOKEN_BYTES,
60 "{key} must contain at least {MIN_TOKEN_BYTES} bytes"
61 );
62 Ok(())
63}
64
65#[cfg(test)]
66#[path = "TESTS/diagnostics.rs"]
67mod tests;