1use crate::{
14 models::{
15 signer::{
16 AwsKmsSignerConfig, GoogleCloudKmsSignerConfig, GoogleCloudKmsSignerKeyConfig,
17 GoogleCloudKmsSignerServiceAccountConfig, LocalSignerConfig, Signer, SignerConfig,
18 SignerValidationError, TurnkeySignerConfig, VaultSignerConfig,
19 VaultTransitSignerConfig,
20 },
21 SecretString,
22 },
23 utils::{
24 deserialize_secret_string, deserialize_secret_vec, serialize_secret_string,
25 serialize_secret_vec,
26 },
27};
28use secrets::SecretVec;
29use serde::{Deserialize, Serialize};
30#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct SignerRepoModel {
33 pub id: String,
34 pub config: SignerConfigStorage,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub enum SignerConfigStorage {
39 Local(LocalSignerConfigStorage),
40 Vault(VaultSignerConfigStorage),
41 VaultTransit(VaultTransitSignerConfigStorage),
42 AwsKms(AwsKmsSignerConfigStorage),
43 Turnkey(TurnkeySignerConfigStorage),
44 GoogleCloudKms(GoogleCloudKmsSignerConfigStorage),
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct LocalSignerConfigStorage {
50 #[serde(
51 serialize_with = "serialize_secret_vec",
52 deserialize_with = "deserialize_secret_vec"
53 )]
54 pub raw_key: SecretVec<u8>,
55}
56
57impl From<LocalSignerConfig> for LocalSignerConfigStorage {
58 fn from(config: LocalSignerConfig) -> Self {
59 Self {
60 raw_key: config.raw_key,
61 }
62 }
63}
64
65impl From<LocalSignerConfigStorage> for LocalSignerConfig {
66 fn from(storage: LocalSignerConfigStorage) -> Self {
67 Self {
68 raw_key: storage.raw_key,
69 }
70 }
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct AwsKmsSignerConfigStorage {
76 pub region: Option<String>,
77 pub key_id: String,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct VaultSignerConfigStorage {
82 pub address: String,
83 pub namespace: Option<String>,
84 #[serde(
85 serialize_with = "serialize_secret_string",
86 deserialize_with = "deserialize_secret_string"
87 )]
88 pub role_id: SecretString,
89 #[serde(
90 serialize_with = "serialize_secret_string",
91 deserialize_with = "deserialize_secret_string"
92 )]
93 pub secret_id: SecretString,
94 pub key_name: String,
95 pub mount_point: Option<String>,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct VaultTransitSignerConfigStorage {
100 pub key_name: String,
101 pub address: String,
102 pub namespace: Option<String>,
103 #[serde(
104 serialize_with = "serialize_secret_string",
105 deserialize_with = "deserialize_secret_string"
106 )]
107 pub role_id: SecretString,
108 #[serde(
109 serialize_with = "serialize_secret_string",
110 deserialize_with = "deserialize_secret_string"
111 )]
112 pub secret_id: SecretString,
113 pub pubkey: String,
114 pub mount_point: Option<String>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct TurnkeySignerConfigStorage {
119 pub api_public_key: String,
120 #[serde(
121 serialize_with = "serialize_secret_string",
122 deserialize_with = "deserialize_secret_string"
123 )]
124 pub api_private_key: SecretString,
125 pub organization_id: String,
126 pub private_key_id: String,
127 pub public_key: String,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct GoogleCloudKmsSignerServiceAccountConfigStorage {
132 #[serde(
133 serialize_with = "serialize_secret_string",
134 deserialize_with = "deserialize_secret_string"
135 )]
136 pub private_key: SecretString,
137 #[serde(
138 serialize_with = "serialize_secret_string",
139 deserialize_with = "deserialize_secret_string"
140 )]
141 pub private_key_id: SecretString,
142 pub project_id: String,
143 #[serde(
144 serialize_with = "serialize_secret_string",
145 deserialize_with = "deserialize_secret_string"
146 )]
147 pub client_email: SecretString,
148 pub client_id: String,
149 pub auth_uri: String,
150 pub token_uri: String,
151 pub auth_provider_x509_cert_url: String,
152 pub client_x509_cert_url: String,
153 pub universe_domain: String,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct GoogleCloudKmsSignerKeyConfigStorage {
158 pub location: String,
159 pub key_ring_id: String,
160 pub key_id: String,
161 pub key_version: u32,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct GoogleCloudKmsSignerConfigStorage {
166 pub service_account: GoogleCloudKmsSignerServiceAccountConfigStorage,
167 pub key: GoogleCloudKmsSignerKeyConfigStorage,
168}
169
170impl From<Signer> for SignerRepoModel {
172 fn from(signer: Signer) -> Self {
173 Self {
174 id: signer.id,
175 config: signer.config.into(),
176 }
177 }
178}
179
180impl From<SignerRepoModel> for Signer {
182 fn from(repo_model: SignerRepoModel) -> Self {
183 Self {
184 id: repo_model.id,
185 config: repo_model.config.into(),
186 }
187 }
188}
189
190impl From<AwsKmsSignerConfig> for AwsKmsSignerConfigStorage {
191 fn from(config: AwsKmsSignerConfig) -> Self {
192 Self {
193 region: config.region,
194 key_id: config.key_id,
195 }
196 }
197}
198
199impl From<AwsKmsSignerConfigStorage> for AwsKmsSignerConfig {
200 fn from(storage: AwsKmsSignerConfigStorage) -> Self {
201 Self {
202 region: storage.region,
203 key_id: storage.key_id,
204 }
205 }
206}
207
208impl From<VaultSignerConfig> for VaultSignerConfigStorage {
209 fn from(config: VaultSignerConfig) -> Self {
210 Self {
211 address: config.address,
212 namespace: config.namespace,
213 role_id: config.role_id,
214 secret_id: config.secret_id,
215 key_name: config.key_name,
216 mount_point: config.mount_point,
217 }
218 }
219}
220
221impl From<VaultSignerConfigStorage> for VaultSignerConfig {
222 fn from(storage: VaultSignerConfigStorage) -> Self {
223 Self {
224 address: storage.address,
225 namespace: storage.namespace,
226 role_id: storage.role_id,
227 secret_id: storage.secret_id,
228 key_name: storage.key_name,
229 mount_point: storage.mount_point,
230 }
231 }
232}
233
234impl From<VaultTransitSignerConfig> for VaultTransitSignerConfigStorage {
235 fn from(config: VaultTransitSignerConfig) -> Self {
236 Self {
237 key_name: config.key_name,
238 address: config.address,
239 namespace: config.namespace,
240 role_id: config.role_id,
241 secret_id: config.secret_id,
242 pubkey: config.pubkey,
243 mount_point: config.mount_point,
244 }
245 }
246}
247
248impl From<VaultTransitSignerConfigStorage> for VaultTransitSignerConfig {
249 fn from(storage: VaultTransitSignerConfigStorage) -> Self {
250 Self {
251 key_name: storage.key_name,
252 address: storage.address,
253 namespace: storage.namespace,
254 role_id: storage.role_id,
255 secret_id: storage.secret_id,
256 pubkey: storage.pubkey,
257 mount_point: storage.mount_point,
258 }
259 }
260}
261
262impl From<TurnkeySignerConfig> for TurnkeySignerConfigStorage {
263 fn from(config: TurnkeySignerConfig) -> Self {
264 Self {
265 api_public_key: config.api_public_key,
266 api_private_key: config.api_private_key,
267 organization_id: config.organization_id,
268 private_key_id: config.private_key_id,
269 public_key: config.public_key,
270 }
271 }
272}
273
274impl From<TurnkeySignerConfigStorage> for TurnkeySignerConfig {
275 fn from(storage: TurnkeySignerConfigStorage) -> Self {
276 Self {
277 api_public_key: storage.api_public_key,
278 api_private_key: storage.api_private_key,
279 organization_id: storage.organization_id,
280 private_key_id: storage.private_key_id,
281 public_key: storage.public_key,
282 }
283 }
284}
285
286impl From<GoogleCloudKmsSignerConfig> for GoogleCloudKmsSignerConfigStorage {
287 fn from(config: GoogleCloudKmsSignerConfig) -> Self {
288 Self {
289 service_account: config.service_account.into(),
290 key: config.key.into(),
291 }
292 }
293}
294
295impl From<GoogleCloudKmsSignerConfigStorage> for GoogleCloudKmsSignerConfig {
296 fn from(storage: GoogleCloudKmsSignerConfigStorage) -> Self {
297 Self {
298 service_account: storage.service_account.into(),
299 key: storage.key.into(),
300 }
301 }
302}
303
304impl From<GoogleCloudKmsSignerServiceAccountConfig>
305 for GoogleCloudKmsSignerServiceAccountConfigStorage
306{
307 fn from(config: GoogleCloudKmsSignerServiceAccountConfig) -> Self {
308 Self {
309 private_key: config.private_key,
310 private_key_id: config.private_key_id,
311 project_id: config.project_id,
312 client_email: config.client_email,
313 client_id: config.client_id,
314 auth_uri: config.auth_uri,
315 token_uri: config.token_uri,
316 auth_provider_x509_cert_url: config.auth_provider_x509_cert_url,
317 client_x509_cert_url: config.client_x509_cert_url,
318 universe_domain: config.universe_domain,
319 }
320 }
321}
322
323impl From<GoogleCloudKmsSignerServiceAccountConfigStorage>
324 for GoogleCloudKmsSignerServiceAccountConfig
325{
326 fn from(storage: GoogleCloudKmsSignerServiceAccountConfigStorage) -> Self {
327 Self {
328 private_key: storage.private_key,
329 private_key_id: storage.private_key_id,
330 project_id: storage.project_id,
331 client_email: storage.client_email,
332 client_id: storage.client_id,
333 auth_uri: storage.auth_uri,
334 token_uri: storage.token_uri,
335 auth_provider_x509_cert_url: storage.auth_provider_x509_cert_url,
336 client_x509_cert_url: storage.client_x509_cert_url,
337 universe_domain: storage.universe_domain,
338 }
339 }
340}
341
342impl From<GoogleCloudKmsSignerKeyConfig> for GoogleCloudKmsSignerKeyConfigStorage {
343 fn from(config: GoogleCloudKmsSignerKeyConfig) -> Self {
344 Self {
345 location: config.location,
346 key_ring_id: config.key_ring_id,
347 key_id: config.key_id,
348 key_version: config.key_version,
349 }
350 }
351}
352
353impl From<GoogleCloudKmsSignerKeyConfigStorage> for GoogleCloudKmsSignerKeyConfig {
354 fn from(storage: GoogleCloudKmsSignerKeyConfigStorage) -> Self {
355 Self {
356 location: storage.location,
357 key_ring_id: storage.key_ring_id,
358 key_id: storage.key_id,
359 key_version: storage.key_version,
360 }
361 }
362}
363
364impl SignerRepoModel {
365 pub fn validate(&self) -> Result<(), SignerValidationError> {
367 let core_signer = Signer::from(self.clone());
368 core_signer.validate()
369 }
370}
371
372impl From<SignerConfig> for SignerConfigStorage {
373 fn from(config: SignerConfig) -> Self {
374 match config {
375 SignerConfig::Local(local) => SignerConfigStorage::Local(local.into()),
376 SignerConfig::Vault(vault) => SignerConfigStorage::Vault(vault.into()),
377 SignerConfig::VaultTransit(vault_transit) => {
378 SignerConfigStorage::VaultTransit(vault_transit.into())
379 }
380 SignerConfig::AwsKms(aws_kms) => SignerConfigStorage::AwsKms(aws_kms.into()),
381 SignerConfig::Turnkey(turnkey) => SignerConfigStorage::Turnkey(turnkey.into()),
382 SignerConfig::GoogleCloudKms(gcp) => SignerConfigStorage::GoogleCloudKms(gcp.into()),
383 }
384 }
385}
386
387impl From<SignerConfigStorage> for SignerConfig {
388 fn from(storage: SignerConfigStorage) -> Self {
389 match storage {
390 SignerConfigStorage::Local(local) => SignerConfig::Local(local.into()),
391 SignerConfigStorage::Vault(vault) => SignerConfig::Vault(vault.into()),
392 SignerConfigStorage::VaultTransit(vault_transit) => {
393 SignerConfig::VaultTransit(vault_transit.into())
394 }
395 SignerConfigStorage::AwsKms(aws_kms) => SignerConfig::AwsKms(aws_kms.into()),
396 SignerConfigStorage::Turnkey(turnkey) => SignerConfig::Turnkey(turnkey.into()),
397 SignerConfigStorage::GoogleCloudKms(gcp) => SignerConfig::GoogleCloudKms(gcp.into()),
398 }
399 }
400}
401
402impl SignerConfigStorage {
403 pub fn get_local(&self) -> Option<&LocalSignerConfigStorage> {
405 match self {
406 Self::Local(config) => Some(config),
407 _ => None,
408 }
409 }
410
411 pub fn get_vault_transit(&self) -> Option<&VaultTransitSignerConfigStorage> {
413 match self {
414 Self::VaultTransit(config) => Some(config),
415 _ => None,
416 }
417 }
418
419 pub fn get_vault(&self) -> Option<&VaultSignerConfigStorage> {
421 match self {
422 Self::Vault(config) => Some(config),
423 _ => None,
424 }
425 }
426
427 pub fn get_turnkey(&self) -> Option<&TurnkeySignerConfigStorage> {
429 match self {
430 Self::Turnkey(config) => Some(config),
431 _ => None,
432 }
433 }
434
435 pub fn get_google_cloud_kms(&self) -> Option<&GoogleCloudKmsSignerConfigStorage> {
437 match self {
438 Self::GoogleCloudKms(config) => Some(config),
439 _ => None,
440 }
441 }
442
443 pub fn get_aws_kms(&self) -> Option<&AwsKmsSignerConfigStorage> {
445 match self {
446 Self::AwsKms(config) => Some(config),
447 _ => None,
448 }
449 }
450}
451
452#[cfg(test)]
453mod tests {
454 use super::*;
455 use crate::models::signer::{LocalSignerConfig, SignerConfig};
456 use secrets::SecretVec;
457
458 #[test]
459 fn test_from_core_signer() {
460 let config = LocalSignerConfig {
461 raw_key: SecretVec::new(32, |v| v.fill(1)),
462 };
463
464 let core =
465 crate::models::signer::Signer::new("test-id".to_string(), SignerConfig::Local(config));
466
467 let repo_model = SignerRepoModel::from(core);
468 assert_eq!(repo_model.id, "test-id");
469 assert!(matches!(repo_model.config, SignerConfigStorage::Local(_)));
470 }
471
472 #[test]
473 fn test_to_core_signer() {
474 use crate::models::signer::AwsKmsSignerConfigStorage;
475
476 let domain_config = AwsKmsSignerConfigStorage {
477 region: Some("us-east-1".to_string()),
478 key_id: "test-key".to_string(),
479 };
480
481 let repo_model = SignerRepoModel {
482 id: "test-id".to_string(),
483 config: SignerConfigStorage::AwsKms(domain_config),
484 };
485
486 let core = Signer::from(repo_model);
487 assert_eq!(core.id, "test-id");
488 assert_eq!(
489 core.signer_type(),
490 crate::models::signer::SignerType::AwsKms
491 );
492 }
493
494 #[test]
495 fn test_validation() {
496 use secrets::SecretVec;
497
498 let domain_config = LocalSignerConfig {
499 raw_key: SecretVec::new(32, |v| v.fill(1)),
500 };
501 let storage_config = LocalSignerConfigStorage::from(domain_config);
503
504 let repo_model = SignerRepoModel {
505 id: "test-id".to_string(),
506 config: SignerConfigStorage::Local(storage_config),
507 };
508
509 assert!(repo_model.validate().is_ok());
510 }
511
512 #[test]
513 fn test_local_config_storage_conversion() {
514 let domain_config = LocalSignerConfig {
515 raw_key: SecretVec::new(4, |v| v.copy_from_slice(&[1, 2, 3, 4])),
516 };
517
518 let storage_config = LocalSignerConfigStorage::from(domain_config.clone());
519 let converted_back = LocalSignerConfig::from(storage_config);
520
521 let original_data = domain_config.raw_key.borrow();
523 let converted_data = converted_back.raw_key.borrow();
524 assert_eq!(*original_data, *converted_data);
525 }
526}