1//! Credentials from the process environment, under the names an operator sets them by. 2//! 3//! Where the value ends up: in the service's environment, put there by whatever starts it 4//! (`op-env-run` on the operator's machine). Nothing here writes it anywhere. 5 6use whiskers_ports::{Lookup, SecretName, Secrets, StoreError}; 7 8/// Looks a credential up by its operator-facing name. 9type Reader = Box<dyn Fn(&str) -> Option<String> + Send + Sync>; 10 11pub struct EnvSecrets { 12 read: Reader, 13} 14 15impl EnvSecrets { 16 /// The process environment. A variable that is not valid text is treated as not set. 17 pub fn process() -> Self { 18 Self::from_fn(|name| std::env::var(name).ok()) 19 } 20 21 /// Any lookup by operator-facing name, for tests and for starting under another source. 22 pub fn from_fn(read: impl Fn(&str) -> Option<String> + Send + Sync + 'static) -> Self { 23 Self { read: Box::new(read) } 24 } 25} 26 27impl Secrets for EnvSecrets { 28 async fn get(&self, name: SecretName) -> Result<Lookup, StoreError> { 29 let found = Lookup::of((self.read)(name.operator_name()).as_deref()); 30 log::trace!("secret {name}: {}", match &found { 31 Lookup::Absent => "absent", 32 Lookup::Empty => "set but empty", 33 Lookup::Present(_) => "present", 34 }); 35 Ok(found) 36 } 37}