signstar_config/nethsm/
state.rs1use std::any::Any;
9
10use log::{debug, trace};
11#[cfg(doc)]
12use nethsm::NetHsm;
13use nethsm::SystemState;
14
15use crate::{
16 NetHsmBackend,
17 config::state::{KeyState, KeyStates, UserState, UserStates},
18 state::StateType,
19};
20#[cfg(doc)]
21use crate::{
22 config::state::KeyCertificateState,
23 nethsm::admin_credentials::NetHsmAdminCredentials,
24};
25use crate::{
26 config::state::SignstarConfigNetHsmState,
27 state::{StateComparisonReport, StateHandling},
28};
29
30#[derive(Debug)]
35pub struct NetHsmState {
36 pub(crate) user_states: Vec<UserState>,
38 pub(crate) key_states: Vec<KeyState>,
40}
41
42impl NetHsmState {
43 const STATE_TYPE: StateType = StateType::NetHsm;
45}
46
47impl StateHandling for NetHsmState {
48 fn state_type(&self) -> StateType {
49 Self::STATE_TYPE
50 }
51
52 fn as_any(&self) -> &dyn Any {
53 self
54 }
55
56 fn compare(&self, other: &dyn StateHandling) -> StateComparisonReport {
57 if !self.is_comparable(other) {
58 trace!(
59 "{} is not compatible with {}",
60 self.state_type(),
61 other.state_type()
62 );
63 return StateComparisonReport::Incompatible {
64 self_state: self.state_type(),
65 other_state: other.state_type(),
66 };
67 }
68
69 let (user_failures, key_failures) = {
70 let (self_user_states, other_user_states, self_key_states, other_key_states) =
71 match other.state_type() {
72 StateType::SignstarConfigNetHsm => {
73 let Some(other) =
74 other.as_any().downcast_ref::<SignstarConfigNetHsmState>()
75 else {
76 return StateComparisonReport::Incompatible {
77 self_state: self.state_type(),
78 other_state: other.state_type(),
79 };
80 };
81 (
82 UserStates {
83 state_type: self.state_type(),
84 users: &self.user_states,
85 },
86 UserStates {
87 state_type: other.state_type(),
88 users: &other.user_states,
89 },
90 KeyStates {
91 state_type: self.state_type(),
92 keys: &self.key_states,
93 },
94 KeyStates {
95 state_type: other.state_type(),
96 keys: &other.key_states,
97 },
98 )
99 }
100 StateType::NetHsm => {
101 let Some(other) = other.as_any().downcast_ref::<NetHsmState>() else {
102 return StateComparisonReport::Incompatible {
103 self_state: self.state_type(),
104 other_state: other.state_type(),
105 };
106 };
107 (
108 UserStates {
109 state_type: self.state_type(),
110 users: &self.user_states,
111 },
112 UserStates {
113 state_type: other.state_type(),
114 users: &other.user_states,
115 },
116 KeyStates {
117 state_type: self.state_type(),
118 keys: &self.key_states,
119 },
120 KeyStates {
121 state_type: other.state_type(),
122 keys: &other.key_states,
123 },
124 )
125 }
126 StateType::SignstarConfigYubiHsm2 | StateType::YubiHsm2 => {
127 return StateComparisonReport::Incompatible {
128 self_state: self.state_type(),
129 other_state: other.state_type(),
130 };
131 }
132 };
133
134 let user_failures = self_user_states.compare(&other_user_states);
135 let key_failures = self_key_states.compare(&other_key_states);
136
137 (user_failures, key_failures)
138 };
139
140 let failures = {
141 let mut failures: Vec<String> = Vec::new();
142
143 for user_failure in user_failures.iter() {
144 failures.push(user_failure.to_string());
145 }
146 for key_failure in key_failures.iter() {
147 failures.push(key_failure.to_string());
148 }
149
150 failures
151 };
152
153 if !failures.is_empty() {
154 return StateComparisonReport::Failure(failures);
155 }
156
157 StateComparisonReport::Success
158 }
159}
160
161impl<'a, 'b> TryFrom<&NetHsmBackend<'a, 'b>> for NetHsmState {
162 type Error = crate::Error;
163
164 fn try_from(value: &NetHsmBackend) -> Result<Self, Self::Error> {
183 debug!(
184 "Retrieve state of the NetHSM backend at {}",
185 value.nethsm().get_url()
186 );
187
188 let (user_states, key_states) = match value.nethsm().state()? {
189 SystemState::Unprovisioned => {
190 debug!(
191 "Unprovisioned NetHSM backend detected at {}.\nSync should be run!",
192 value.nethsm().get_url()
193 );
194
195 (Vec::new(), Vec::new())
196 }
197 SystemState::Locked => {
198 debug!(
199 "Locked NetHSM backend detected at {}",
200 value.nethsm().get_url()
201 );
202
203 value.unlock_nethsm()?;
204
205 let user_states = value.user_states()?;
206 let key_states = value.key_states()?;
207
208 (user_states, key_states)
209 }
210 SystemState::Operational => {
211 debug!(
212 "Operational NetHSM backend detected at {}",
213 value.nethsm().get_url()
214 );
215
216 let user_states = value.user_states()?;
217 let key_states = value.key_states()?;
218
219 (user_states, key_states)
220 }
221 };
222
223 Ok(Self {
224 user_states,
225 key_states,
226 })
227 }
228}