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