secret_vault/simple_sources/
temp_secretgen_source.rs

1use crate::errors::*;
2use crate::*;
3use async_trait::*;
4use ring::rand::{SecureRandom, SystemRandom};
5use rsb_derive::*;
6use secret_vault_value::SecretValue;
7use std::collections::HashMap;
8use tracing::*;
9
10#[derive(Debug, Clone, Eq, PartialEq, Builder)]
11pub struct TempSecretOptions {
12    pub key_len: usize,
13
14    #[default = "false"]
15    pub regenerate_on_refresh: bool,
16
17    #[default = "true"]
18    pub printable: bool,
19}
20
21#[derive(Debug, Clone)]
22pub struct TempSecretGenSourceOptions {
23    registered_secrets: HashMap<SecretVaultKey, TempSecretOptions>,
24}
25
26impl TempSecretGenSourceOptions {
27    pub fn new() -> Self {
28        Self {
29            registered_secrets: HashMap::new(),
30        }
31    }
32
33    pub fn add_secret_generator(
34        mut self,
35        key: &SecretVaultKey,
36        options: TempSecretOptions,
37    ) -> Self {
38        self.registered_secrets.insert(key.clone(), options);
39        self
40    }
41}
42
43#[derive(Debug)]
44pub struct TempSecretGenSource {
45    options: TempSecretGenSourceOptions,
46    secure_rand: SystemRandom,
47    generated_secrets: HashMap<SecretVaultKey, SecretValue>,
48}
49
50impl TempSecretGenSource {
51    pub fn with_options(options: TempSecretGenSourceOptions) -> SecretVaultResult<Self> {
52        let secure_rand = SystemRandom::new();
53
54        let secrets_to_pregen: Vec<(&SecretVaultKey, &TempSecretOptions)> = options
55            .registered_secrets
56            .iter()
57            .filter(|(_, options)| !options.regenerate_on_refresh)
58            .collect();
59
60        let mut generated_secrets = HashMap::new();
61
62        for (key, options) in secrets_to_pregen {
63            debug!("Pre-generating a new secret value for {:?}", key);
64            generated_secrets.insert(
65                key.clone(),
66                generate_secret_value(&secure_rand, options.key_len, options.printable)?,
67            );
68        }
69
70        Ok(Self {
71            options,
72            secure_rand,
73            generated_secrets,
74        })
75    }
76}
77
78pub fn generate_secret_value(
79    secure_rand: &ring::rand::SystemRandom,
80    key_len: usize,
81    printable: bool,
82) -> SecretVaultResult<SecretValue> {
83    let effective_key_len = if printable { key_len / 2 } else { key_len };
84
85    let mut rand_key_data: Vec<u8> = vec![0; effective_key_len];
86    secure_rand.fill(&mut rand_key_data).map_err(|e| {
87        SecretVaultError::SecretsSourceError(
88            SecretsSourceError::new(
89                SecretVaultErrorPublicGenericDetails::new(format!(
90                    "Unable to initialise random key: {e:?}"
91                )),
92                format!("Unable to initialise random key: {e}"),
93            )
94            .with_root_cause(Box::new(e)),
95        )
96    })?;
97
98    if printable {
99        Ok(SecretValue::from(hex::encode(rand_key_data)))
100    } else {
101        Ok(SecretValue::from(rand_key_data))
102    }
103}
104
105#[async_trait]
106impl SecretsSource for TempSecretGenSource {
107    fn name(&self) -> String {
108        "TempSecretGenSource".to_string()
109    }
110
111    async fn get_secrets(
112        &self,
113        references: &[SecretVaultRef],
114    ) -> SecretVaultResult<HashMap<SecretVaultRef, Secret>> {
115        let mut result_map: HashMap<SecretVaultRef, Secret> = HashMap::new();
116
117        for secret_ref in references {
118            match self.options.registered_secrets.get(&secret_ref.key) {
119                Some(secret_options) => {
120                    let secret_value = match self.generated_secrets.get(&secret_ref.key) {
121                        Some(secret_value) => secret_value.clone(),
122                        None => {
123                            debug!("Generating a new secret value for {:?}", secret_ref.key);
124                            generate_secret_value(
125                                &self.secure_rand,
126                                secret_options.key_len,
127                                secret_options.printable,
128                            )?
129                        }
130                    };
131
132                    result_map.insert(
133                        secret_ref.clone(),
134                        Secret::new(secret_value, SecretMetadata::create_from_ref(secret_ref)),
135                    );
136                }
137                None if secret_ref.required => {
138                    return Err(SecretVaultError::DataNotFoundError(
139                        SecretVaultDataNotFoundError::new(
140                            SecretVaultErrorPublicGenericDetails::new("SECRET_NOT_FOUND".into()),
141                            format!(
142                                "Secret is required but not found in registered secrets {:?}",
143                                &secret_ref.key
144                            ),
145                        ),
146                    ))
147                }
148                None => {
149                    debug!("Secret or secret version {:?} doesn't exist and since it is not required it is skipped",secret_ref.key);
150                }
151            }
152        }
153
154        Ok(result_map)
155    }
156}