Skip to main content

haste_encryption/providers/
environment.rs

1use crate::{
2    error::EncryptionError,
3    traits::{Secret, SecretsProvider},
4};
5use base64::{Engine as _, engine::general_purpose::STANDARD};
6use haste_fhir_operation_error::OperationOutcomeError;
7use std::{future::Future, pin::Pin};
8
9/// Reads secrets directly from process environment variables. `name` is
10/// used verbatim as the environment variable name, optionally prefixed.
11pub struct EnvironmentSecretsProvider {
12    prefix: Option<String>,
13}
14
15impl EnvironmentSecretsProvider {
16    #[must_use]
17    pub fn new(prefix: Option<String>) -> Self {
18        Self { prefix }
19    }
20
21    fn env_var_name(&self, name: &str) -> String {
22        match &self.prefix {
23            Some(prefix) => format!("{prefix}{name}"),
24            None => name.to_string(),
25        }
26    }
27}
28
29impl SecretsProvider for EnvironmentSecretsProvider {
30    fn get_secret<'a>(
31        &'a self,
32        name: &'a str,
33    ) -> Pin<Box<dyn Future<Output = Result<Secret, OperationOutcomeError>> + Send + 'a>> {
34        Box::pin(async move {
35            let env_var_name = self.env_var_name(name);
36
37            let value = std::env::var(&env_var_name).map_err(|e| {
38                EncryptionError::SecretRetrievalFailed(name.to_string(), e.to_string())
39            })?;
40
41            let value = STANDARD.decode(value).map_err(|e| {
42                EncryptionError::SecretRetrievalFailed(name.to_string(), e.to_string())
43            })?;
44
45            Ok(Secret::new(value))
46        })
47    }
48}