secret_vault/simple_sources/
temp_secretgen_source.rs1use 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}