coven_keys/keys/
master_key_staging.rs1use std::sync::{Arc, Mutex};
2
3use crate::encryption::MasterKeyring;
4
5use super::{KeyError, MasterKeyCustody, MasterKeyError};
6
7enum StagedMasterKeyState {
8 Proposed(MasterKeyring),
9 Committed,
10 RolledBack,
11}
12
13pub struct StagedMasterKeyCustody {
15 destination: Arc<dyn MasterKeyCustody>,
16 state: Mutex<StagedMasterKeyState>,
17}
18
19impl StagedMasterKeyCustody {
20 pub fn new(
21 destination: Arc<dyn MasterKeyCustody>,
22 proposed: MasterKeyring,
23 ) -> Result<Arc<Self>, MasterKeyError> {
24 if destination.unlock()?.is_some() {
25 return Err(MasterKeyError::AlreadyEstablished);
26 }
27 Ok(Arc::new(Self {
28 destination,
29 state: Mutex::new(StagedMasterKeyState::Proposed(proposed)),
30 }))
31 }
32
33 pub fn commit(&self) -> Result<(), KeyError> {
34 let mut state = self.state.lock().expect("lock staged master key");
35 match &*state {
36 StagedMasterKeyState::Proposed(keyring) => {
37 self.destination.persist(keyring)?;
38 *state = StagedMasterKeyState::Committed;
39 Ok(())
40 }
41 StagedMasterKeyState::Committed => Ok(()),
42 StagedMasterKeyState::RolledBack => Err(KeyError::MasterKeySetupRolledBack {
43 operation: "commit",
44 }),
45 }
46 }
47
48 pub fn rollback(&self) -> Result<(), KeyError> {
49 let mut state = self.state.lock().expect("lock staged master key");
50 match &*state {
51 StagedMasterKeyState::Proposed(_) => {
52 *state = StagedMasterKeyState::RolledBack;
53 Ok(())
54 }
55 StagedMasterKeyState::Committed => {
56 self.destination.forget()?;
57 *state = StagedMasterKeyState::RolledBack;
58 Ok(())
59 }
60 StagedMasterKeyState::RolledBack => Ok(()),
61 }
62 }
63}
64
65impl MasterKeyCustody for StagedMasterKeyCustody {
66 fn unlock(&self) -> Result<Option<MasterKeyring>, KeyError> {
67 let state = self.state.lock().expect("lock staged master key");
68 match &*state {
69 StagedMasterKeyState::Proposed(keyring) => Ok(Some(keyring.clone())),
70 StagedMasterKeyState::Committed => self.destination.unlock(),
71 StagedMasterKeyState::RolledBack => Err(KeyError::MasterKeySetupRolledBack {
72 operation: "unlock",
73 }),
74 }
75 }
76
77 fn persist(&self, keyring: &MasterKeyring) -> Result<(), KeyError> {
78 let mut state = self.state.lock().expect("lock staged master key");
79 match &mut *state {
80 StagedMasterKeyState::Proposed(proposed) => {
81 *proposed = keyring.clone();
82 Ok(())
83 }
84 StagedMasterKeyState::Committed => self.destination.persist(keyring),
85 StagedMasterKeyState::RolledBack => Err(KeyError::MasterKeySetupRolledBack {
86 operation: "persist",
87 }),
88 }
89 }
90
91 fn forget(&self) -> Result<(), KeyError> {
92 self.rollback()
93 }
94}
95
96#[cfg(test)]
97#[path = "master_key_staging_tests.rs"]
98mod tests;