openzeppelin_relayer/config/config_file/signer/
vault.rs1use crate::{
13 config::ConfigFileError,
14 models::{validate_plain_or_env_value, PlainOrEnvValue},
15};
16use serde::{Deserialize, Serialize};
17use validator::Validate;
18
19use super::{validate_with_validator, SignerConfigValidate};
20
21#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Validate)]
22#[serde(deny_unknown_fields)]
23pub struct VaultSignerFileConfig {
24 #[validate(url)]
25 pub address: String,
26 pub namespace: Option<String>,
27 #[validate(custom(function = "validate_plain_or_env_value"))]
28 pub role_id: PlainOrEnvValue,
29 #[validate(custom(function = "validate_plain_or_env_value"))]
30 pub secret_id: PlainOrEnvValue,
31 #[validate(length(min = 1, message = "Vault key name cannot be empty"))]
32 pub key_name: String,
33 pub mount_point: Option<String>,
34}
35
36impl SignerConfigValidate for VaultSignerFileConfig {
37 fn validate(&self) -> Result<(), ConfigFileError> {
38 validate_with_validator(self)
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use crate::models::SecretString;
45
46 use super::*;
47 use validator::Validate;
48
49 #[test]
50 fn test_vault_signer_file_config_valid() {
51 let config = VaultSignerFileConfig {
52 address: "https://vault.example.com:8200".to_string(),
53 namespace: Some("namespace1".to_string()),
54 role_id: PlainOrEnvValue::Plain {
55 value: SecretString::new("role-123"),
56 },
57 secret_id: PlainOrEnvValue::Plain {
58 value: SecretString::new("secret-456"),
59 },
60 key_name: "my-key".to_string(),
61 mount_point: Some("transit".to_string()),
62 };
63
64 assert!(Validate::validate(&config).is_ok());
65 assert!(SignerConfigValidate::validate(&config).is_ok());
66 }
67
68 #[test]
69 fn test_vault_signer_file_config_invalid_address() {
70 let config = VaultSignerFileConfig {
71 address: "not-a-url".to_string(),
72 namespace: Some("namespace1".to_string()),
73 role_id: PlainOrEnvValue::Plain {
74 value: SecretString::new("role-123"),
75 },
76 secret_id: PlainOrEnvValue::Plain {
77 value: SecretString::new("secret-456"),
78 },
79 key_name: "my-key".to_string(),
80 mount_point: Some("transit".to_string()),
81 };
82
83 let result = SignerConfigValidate::validate(&config);
84 assert!(result.is_err());
85 if let Err(e) = result {
86 let error_message = format!("{:?}", e);
87 assert!(error_message.contains("address"));
88 }
89 }
90
91 #[test]
92 fn test_vault_signer_file_config_empty_role_id() {
93 let config = VaultSignerFileConfig {
94 address: "https://vault.example.com:8200".to_string(),
95 namespace: Some("namespace1".to_string()),
96 role_id: PlainOrEnvValue::Plain {
97 value: SecretString::new(""),
98 },
99 secret_id: PlainOrEnvValue::Plain {
100 value: SecretString::new("secret-456"),
101 },
102 key_name: "my-key".to_string(),
103 mount_point: Some("transit".to_string()),
104 };
105
106 let result = SignerConfigValidate::validate(&config);
107 assert!(result.is_err());
108
109 if let Err(e) = result {
110 let error_message = format!("{:?}", e);
111 assert!(error_message.contains("role_id"));
112 }
113 }
114
115 #[test]
116 fn test_vault_signer_file_config_empty_secret_id() {
117 let config = VaultSignerFileConfig {
118 address: "https://vault.example.com:8200".to_string(),
119 namespace: None,
120 role_id: PlainOrEnvValue::Plain {
121 value: SecretString::new("role-123"),
122 },
123 secret_id: PlainOrEnvValue::Plain {
124 value: SecretString::new(""),
125 },
126 key_name: "my-key".to_string(),
127 mount_point: None,
128 };
129
130 let result = SignerConfigValidate::validate(&config);
131 assert!(result.is_err());
132
133 if let Err(e) = result {
134 let error_message = format!("{:?}", e);
135 assert!(error_message.contains("secret_id"));
136 }
137 }
138
139 #[test]
140 fn test_vault_signer_file_config_empty_key_name() {
141 let config = VaultSignerFileConfig {
142 address: "https://vault.example.com:8200".to_string(),
143 namespace: None,
144 role_id: PlainOrEnvValue::Plain {
145 value: SecretString::new("role-123"),
146 },
147 secret_id: PlainOrEnvValue::Plain {
148 value: SecretString::new("secret-456"),
149 },
150 key_name: "".to_string(),
151 mount_point: None,
152 };
153
154 let result = SignerConfigValidate::validate(&config);
155 assert!(result.is_err());
156
157 if let Err(e) = result {
158 let error_message = format!("{:?}", e);
159 assert!(error_message.contains("key_name"));
160 assert!(error_message.contains("cannot be empty"));
161 }
162 }
163
164 #[test]
165 fn test_vault_signer_file_config_optional_fields() {
166 let config = VaultSignerFileConfig {
167 address: "https://vault.example.com:8200".to_string(),
168 namespace: None,
169 role_id: PlainOrEnvValue::Plain {
170 value: SecretString::new("role-123"),
171 },
172 secret_id: PlainOrEnvValue::Plain {
173 value: SecretString::new("secret-456"),
174 },
175 key_name: "my-key".to_string(),
176 mount_point: None,
177 };
178
179 assert!(SignerConfigValidate::validate(&config).is_ok());
180 }
181
182 #[test]
183 fn test_vault_signer_file_config_multiple_errors() {
184 let config = VaultSignerFileConfig {
186 address: "invalid-url".to_string(),
187 namespace: None,
188 role_id: PlainOrEnvValue::Plain {
189 value: SecretString::new(""),
190 },
191 secret_id: PlainOrEnvValue::Plain {
192 value: SecretString::new(""),
193 },
194 key_name: "".to_string(),
195 mount_point: None,
196 };
197
198 let result = validate_with_validator(&config);
199 assert!(result.is_err());
200
201 if let Err(e) = result {
202 if let ConfigFileError::InvalidFormat(msg) = e {
203 assert!(msg.contains("address"));
204 assert!(msg.contains("role_id"));
205 assert!(msg.contains("secret_id"));
206 assert!(msg.contains("key_name"));
207 } else {
208 panic!("Expected ConfigFileError::InvalidFormat, got {:?}", e);
209 }
210 }
211 }
212
213 #[test]
214 fn test_serde_deserialize() {
215 let json = r#"
216 {
217 "address": "https://vault.example.com:8200",
218 "namespace": "my-namespace",
219 "role_id": {
220 "type": "plain",
221 "value": "role-123"
222 },
223 "secret_id": {
224 "type": "plain",
225 "value": "secret-456"
226 },
227 "key_name": "my-key",
228 "mount_point": "transit"
229 }
230 "#;
231
232 let config: VaultSignerFileConfig = serde_json::from_str(json).unwrap();
233 assert_eq!(config.address, "https://vault.example.com:8200");
234 assert_eq!(config.namespace, Some("my-namespace".to_string()));
235 assert_eq!(
236 config.role_id.get_value().unwrap().to_str().as_str(),
237 "role-123"
238 );
239 assert_eq!(
240 config.secret_id.get_value().unwrap().to_str().as_str(),
241 "secret-456"
242 );
243 assert_eq!(config.key_name, "my-key");
244 assert_eq!(config.mount_point, Some("transit".to_string()));
245 }
246
247 #[test]
248 fn test_serde_unknown_field() {
249 let json = r#"
250 {
251 "address": "https://vault.example.com:8200",
252 "namespace": "my-namespace",
253 "role_id": {
254 "type": "plain",
255 "value": "role-123"
256 },
257 "secret_id": {
258 "type": "plain",
259 "value": "secret-456"
260 },
261 "key_name": "my-key",
262 "mount_point": "transit",
263 "unknown_field": "should cause error"
264 }
265 "#;
266
267 let result: Result<VaultSignerFileConfig, _> = serde_json::from_str(json);
268 assert!(result.is_err());
269 }
270
271 #[test]
272 fn test_serde_serialize_deserialize() {
273 let config = VaultSignerFileConfig {
274 address: "https://vault.example.com:8200".to_string(),
275 namespace: Some("namespace1".to_string()),
276 role_id: PlainOrEnvValue::Plain {
277 value: SecretString::new("role-123"),
278 },
279 secret_id: PlainOrEnvValue::Plain {
280 value: SecretString::new("secret-456"),
281 },
282 key_name: "my-key".to_string(),
283 mount_point: Some("transit".to_string()),
284 };
285
286 let serialized = serde_json::to_string(&config).unwrap();
287 let deserialized: VaultSignerFileConfig = serde_json::from_str(&serialized).unwrap();
288
289 assert_eq!(config.address, deserialized.address);
290 assert_eq!(config.key_name, deserialized.key_name);
291 assert_eq!(config.mount_point, deserialized.mount_point);
292 assert_eq!(config.namespace, deserialized.namespace);
293 assert_ne!(config.role_id, deserialized.role_id);
294 assert_ne!(config.secret_id, deserialized.secret_id);
295 }
296}