use std::fmt; use std::path::PathBuf; use serde::{Deserialize, Serialize}; /// 密钥材料的三种来源:文件、环境变量、内联(明文 PEM 或 base64)。 #[derive(Clone, Deserialize, Serialize)] #[serde(untagged)] pub enum SecretMaterial { File { file: PathBuf }, Env { env: String }, Inline(String), } impl SecretMaterial { pub fn resolve(&self) -> Result { match self { Self::File { file } => std::fs::read_to_string(file).map_err(|error| { format!("secret file {} is not readable: {error}", file.display()) }), Self::Env { env } => std::env::var(env) .map_err(|_| format!("secret environment variable {env} is not set")), Self::Inline(text) => Ok(text.trim().to_owned()), } } pub fn is_empty(&self) -> bool { match self { Self::Inline(text) => text.trim().is_empty(), _ => false, } } } impl Default for SecretMaterial { fn default() -> Self { Self::Inline(String::new()) } } impl fmt::Debug for SecretMaterial { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::File { file } => formatter .debug_struct("SecretMaterial") .field("file", file) .finish_non_exhaustive(), Self::Env { env } => formatter .debug_struct("SecretMaterial") .field("env", env) .finish_non_exhaustive(), Self::Inline(_) => formatter .debug_struct("SecretMaterial") .field("inline", &"") .finish(), } } }