1use crate::{
3 secret::{Secret, SecretMeta, SecretRow},
4 EncryptedEntry, Error, SharedAccess, Summary, Vault, VaultMeta,
5};
6use async_trait::async_trait;
7use sos_core::{
8 crypto::{AccessKey, AeadPack, KeyDerivation, PrivateKey},
9 decode, encode,
10 events::{ReadEvent, WriteEvent},
11 AuthenticationError, SecretId, VaultCommit, VaultEntry, VaultFlags,
12 VaultId,
13};
14use sos_vfs as vfs;
15use std::path::Path;
16
17pub type VaultMirror<E> =
18 Box<dyn EncryptedEntry<Error = E> + Send + Sync + 'static>;
19
20#[async_trait]
22pub trait SecretAccess {
23 type Error: std::error::Error
25 + std::fmt::Debug
26 + From<crate::Error>
27 + From<sos_core::Error>
28 + From<std::io::Error>
29 + Send
30 + Sync
31 + 'static;
32
33 fn is_mirror(&self) -> bool;
36
37 fn vault(&self) -> &Vault;
39
40 async fn replace_vault(
49 &mut self,
50 vault: Vault,
51 mirror_changes: bool,
52 ) -> Result<(), Self::Error>;
53
54 async fn reload_vault<P: AsRef<Path> + Send>(
64 &mut self,
65 path: P,
66 ) -> Result<(), Self::Error>;
67
68 fn summary(&self) -> &Summary;
70
71 fn id(&self) -> &VaultId;
73
74 fn name(&self) -> &str;
76
77 async fn set_vault_name(
79 &mut self,
80 name: String,
81 ) -> Result<WriteEvent, Self::Error>;
82
83 async fn set_vault_flags(
85 &mut self,
86 flags: VaultFlags,
87 ) -> Result<WriteEvent, Self::Error>;
88
89 async fn vault_meta(&self) -> Result<VaultMeta, Self::Error>;
92
93 async fn set_vault_meta(
95 &mut self,
96 meta_data: &VaultMeta,
97 ) -> Result<WriteEvent, Self::Error>;
98
99 async fn create_secret(
101 &mut self,
102 secret_data: &SecretRow,
103 ) -> Result<WriteEvent, Self::Error>;
104
105 #[doc(hidden)]
106 async fn decrypt_meta(
107 &self,
108 meta_aead: &AeadPack,
109 ) -> Result<VaultMeta, Self::Error>;
110
111 #[doc(hidden)]
112 async fn decrypt_secret(
113 &self,
114 vault_commit: &VaultCommit,
115 private_key: Option<&PrivateKey>,
116 ) -> Result<(SecretMeta, Secret), Self::Error>;
117
118 async fn raw_secret(
120 &self,
121 id: &SecretId,
122 ) -> Result<Option<(VaultCommit, ReadEvent)>, Self::Error>;
123
124 async fn read_secret(
126 &self,
127 id: &SecretId,
128 ) -> Result<Option<(SecretMeta, Secret, ReadEvent)>, Self::Error>;
129
130 async fn update_secret(
132 &mut self,
133 id: &SecretId,
134 secret_meta: SecretMeta,
135 secret: Secret,
136 ) -> Result<Option<WriteEvent>, Self::Error>;
137
138 async fn delete_secret(
140 &mut self,
141 id: &SecretId,
142 ) -> Result<Option<WriteEvent>, Self::Error>;
143
144 async fn verify(&self, key: &AccessKey) -> Result<(), Self::Error>;
146
147 async fn unlock(
152 &mut self,
153 key: &AccessKey,
154 ) -> Result<VaultMeta, Self::Error>;
155
156 fn lock(&mut self);
160}
161
162pub struct AccessPoint<E>
178where
179 E: std::error::Error
180 + std::fmt::Debug
181 + From<crate::Error>
182 + From<sos_core::Error>
183 + From<std::io::Error>
184 + Send
185 + Sync
186 + 'static,
187{
188 private_key: Option<PrivateKey>,
190 vault: Vault,
192 mirror: Option<VaultMirror<E>>,
194}
195
196impl<E> AccessPoint<E>
197where
198 E: std::error::Error
199 + std::fmt::Debug
200 + From<crate::Error>
201 + From<sos_core::Error>
202 + From<std::io::Error>
203 + Send
204 + Sync
205 + 'static,
206{
207 pub fn new(vault: Vault) -> Self {
209 Self {
210 vault,
211 private_key: None,
212 mirror: None,
213 }
214 }
215
216 pub fn new_mirror(vault: Vault, mirror: VaultMirror<E>) -> Self {
219 Self {
220 vault,
221 private_key: None,
222 mirror: Some(mirror),
223 }
224 }
225
226 async fn enforce_shared_readonly(
229 &self,
230 key: &PrivateKey,
231 ) -> Result<(), E> {
232 if let SharedAccess::ReadOnly(aead) = self.vault.shared_access() {
233 self.vault
234 .decrypt(key, aead)
235 .await
236 .map_err(|_| Error::PermissionDenied)?;
237 }
238 Ok(())
239 }
240}
241
242#[async_trait]
243impl<E> SecretAccess for AccessPoint<E>
244where
245 E: std::error::Error
246 + std::fmt::Debug
247 + From<crate::Error>
248 + From<sos_core::Error>
249 + From<std::io::Error>
250 + Send
251 + Sync
252 + 'static,
253{
254 type Error = E;
255
256 fn is_mirror(&self) -> bool {
257 self.mirror.is_some()
258 }
259
260 fn vault(&self) -> &Vault {
261 &self.vault
262 }
263
264 async fn replace_vault(
265 &mut self,
266 vault: Vault,
267 mirror_changes: bool,
268 ) -> Result<(), E> {
269 if let (true, Some(mirror)) = (mirror_changes, &mut self.mirror) {
270 mirror.replace_vault(&vault).await?;
271 }
272 self.vault = vault;
273 Ok(())
274 }
275
276 async fn reload_vault<P: AsRef<Path> + Send>(
277 &mut self,
278 path: P,
279 ) -> Result<(), E> {
280 let buffer = vfs::read(path.as_ref()).await?;
281 let vault: Vault = decode(&buffer).await?;
282 if let Some(mirror) = &mut self.mirror {
283 mirror.replace_vault(&vault).await?;
284 }
285 self.vault = vault;
286 Ok(())
287 }
288
289 fn summary(&self) -> &Summary {
290 self.vault.summary()
291 }
292
293 fn id(&self) -> &VaultId {
294 self.vault.id()
295 }
296
297 fn name(&self) -> &str {
298 self.vault.name()
299 }
300
301 async fn set_vault_name(
302 &mut self,
303 name: String,
304 ) -> Result<WriteEvent, E> {
305 if let Some(mirror) = self.mirror.as_mut() {
306 mirror.set_vault_name(name.clone()).await?;
307 }
308 Ok(self.vault.set_vault_name(name).await?)
309 }
310
311 async fn set_vault_flags(
312 &mut self,
313 flags: VaultFlags,
314 ) -> Result<WriteEvent, E> {
315 if let Some(mirror) = self.mirror.as_mut() {
316 mirror.set_vault_flags(flags.clone()).await?;
317 }
318 Ok(self.vault.set_vault_flags(flags).await?)
319 }
320
321 async fn vault_meta(&self) -> Result<VaultMeta, E> {
322 if let Some(meta_aead) = self.vault.header().meta() {
323 Ok(self.decrypt_meta(meta_aead).await?)
324 } else {
325 Err(Error::VaultNotInit.into())
326 }
327 }
328
329 async fn set_vault_meta(
330 &mut self,
331 meta_data: &VaultMeta,
332 ) -> Result<WriteEvent, E> {
333 let private_key =
334 self.private_key.as_ref().ok_or(Error::VaultLocked)?;
335 let meta_blob = encode(meta_data).await?;
336 let meta_aead = self.vault.encrypt(private_key, &meta_blob).await?;
337 if let Some(mirror) = self.mirror.as_mut() {
338 mirror.set_vault_meta(meta_aead.clone()).await?;
339 }
340 Ok(self.vault.set_vault_meta(meta_aead).await?)
341 }
342
343 async fn decrypt_meta(
344 &self,
345 meta_aead: &AeadPack,
346 ) -> Result<VaultMeta, E> {
347 let private_key =
348 self.private_key.as_ref().ok_or(Error::VaultLocked)?;
349 let meta_blob =
350 self.vault.decrypt(private_key, meta_aead).await.map_err(
351 |_| {
352 sos_core::Error::from(
353 AuthenticationError::PasswordVerification,
354 )
355 },
356 )?;
357 Ok(decode(&meta_blob).await?)
358 }
359
360 async fn decrypt_secret(
361 &self,
362 vault_commit: &VaultCommit,
363 private_key: Option<&PrivateKey>,
364 ) -> Result<(SecretMeta, Secret), E> {
365 let private_key = private_key
366 .or(self.private_key.as_ref())
367 .ok_or(Error::VaultLocked)?;
368
369 let VaultCommit(_commit, VaultEntry(meta_aead, secret_aead)) =
370 vault_commit;
371 let meta_blob = self.vault.decrypt(private_key, meta_aead).await?;
372 let secret_meta: SecretMeta = decode(&meta_blob).await?;
373
374 let secret_blob =
375 self.vault.decrypt(private_key, secret_aead).await?;
376 let secret: Secret = decode(&secret_blob).await?;
377 Ok((secret_meta, secret))
378 }
379
380 async fn create_secret(
381 &mut self,
382 secret_data: &SecretRow,
383 ) -> Result<WriteEvent, E> {
384 let private_key =
385 self.private_key.as_ref().ok_or(Error::VaultLocked)?;
386
387 self.enforce_shared_readonly(private_key).await?;
388
389 let id = *secret_data.id();
390 let meta_blob = encode(secret_data.meta()).await?;
391 let meta_aead = self.vault.encrypt(private_key, &meta_blob).await?;
392
393 let secret_blob = encode(secret_data.secret()).await?;
394 let secret_aead =
395 self.vault.encrypt(private_key, &secret_blob).await?;
396 let commit = Vault::commit_hash(&meta_aead, &secret_aead).await?;
397
398 if let Some(mirror) = self.mirror.as_mut() {
399 mirror
400 .insert_secret(
401 id,
402 commit,
403 VaultEntry(meta_aead.clone(), secret_aead.clone()),
404 )
405 .await?;
406 }
407
408 let result = self
409 .vault
410 .insert_secret(id, commit, VaultEntry(meta_aead, secret_aead))
411 .await?;
412
413 Ok(result)
414 }
415
416 async fn raw_secret(
417 &self,
418 id: &SecretId,
419 ) -> Result<Option<(VaultCommit, ReadEvent)>, E> {
420 let value = self.vault.read_secret(id).await?;
421 let value = if let Some((commit, event)) = value {
422 Some((commit.into_owned(), event))
423 } else {
424 None
425 };
426 Ok(value)
427 }
428
429 async fn read_secret(
430 &self,
431 id: &SecretId,
432 ) -> Result<Option<(SecretMeta, Secret, ReadEvent)>, E> {
433 self.private_key.as_ref().ok_or(Error::VaultLocked)?;
434
435 if let Some((value, event)) = self.raw_secret(id).await? {
436 let (meta, secret) = self
437 .decrypt_secret(&value, self.private_key.as_ref())
438 .await?;
439 Ok(Some((meta, secret, event)))
440 } else {
441 Ok(None)
442 }
443 }
444
445 async fn update_secret(
446 &mut self,
447 id: &SecretId,
448 secret_meta: SecretMeta,
449 secret: Secret,
450 ) -> Result<Option<WriteEvent>, E> {
451 let private_key =
452 self.private_key.as_ref().ok_or(Error::VaultLocked)?;
453
454 self.enforce_shared_readonly(private_key).await?;
455
456 let meta_blob = encode(&secret_meta).await?;
457 let meta_aead = self.vault.encrypt(private_key, &meta_blob).await?;
458
459 let secret_blob = encode(&secret).await?;
460 let secret_aead =
461 self.vault.encrypt(private_key, &secret_blob).await?;
462 let commit = Vault::commit_hash(&meta_aead, &secret_aead).await?;
463
464 if let Some(mirror) = self.mirror.as_mut() {
465 mirror
466 .update_secret(
467 id,
468 commit,
469 VaultEntry(meta_aead.clone(), secret_aead.clone()),
470 )
471 .await?;
472 }
473
474 Ok(self
475 .vault
476 .update_secret(id, commit, VaultEntry(meta_aead, secret_aead))
477 .await?)
478 }
479
480 async fn delete_secret(
481 &mut self,
482 id: &SecretId,
483 ) -> Result<Option<WriteEvent>, E> {
484 let private_key =
485 self.private_key.as_ref().ok_or(Error::VaultLocked)?;
486 self.enforce_shared_readonly(private_key).await?;
487 if let Some(mirror) = self.mirror.as_mut() {
488 mirror.delete_secret(id).await?;
489 }
490 Ok(self.vault.delete_secret(id).await?)
491 }
492
493 async fn verify(&self, key: &AccessKey) -> Result<(), E> {
494 Ok(self.vault.verify(key).await?)
495 }
496
497 async fn unlock(&mut self, key: &AccessKey) -> Result<VaultMeta, E> {
498 if let Some(salt) = self.vault.salt() {
499 match key {
500 AccessKey::Password(passphrase) => {
501 let salt = KeyDerivation::parse_salt(salt)?;
502 let deriver = self.vault.deriver();
503 let private_key = deriver.derive(
504 passphrase,
505 &salt,
506 self.vault.seed(),
507 )?;
508 self.private_key =
509 Some(PrivateKey::Symmetric(private_key));
510 self.vault_meta().await
511 }
512 AccessKey::Identity(id) => {
513 self.private_key =
514 Some(PrivateKey::Asymmetric(id.clone()));
515 self.vault_meta().await
516 }
517 }
518 } else {
519 Err(Error::VaultNotInit.into())
520 }
521 }
522
523 fn lock(&mut self) {
524 tracing::debug!(folder = %self.id(), "drop_private_key");
525 self.private_key = None;
526 }
527}
528
529impl<E> From<Vault> for AccessPoint<E>
530where
531 E: std::error::Error
532 + std::fmt::Debug
533 + From<crate::Error>
534 + From<sos_core::Error>
535 + From<std::io::Error>
536 + Send
537 + Sync
538 + 'static,
539{
540 fn from(value: Vault) -> Self {
541 AccessPoint::<E>::new(value)
542 }
543}
544
545impl<E> From<AccessPoint<E>> for Vault
546where
547 E: std::error::Error
548 + std::fmt::Debug
549 + From<crate::Error>
550 + From<sos_core::Error>
551 + From<std::io::Error>
552 + Send
553 + Sync
554 + 'static,
555{
556 fn from(value: AccessPoint<E>) -> Self {
557 value.vault
558 }
559}