Skip to main content

signstar_config/config/file/
impl_all.rs

1//! Impls for [`UserBackendConnection`] and [`Config`] when using all HSM backends.
2//!
3//! # Note
4//!
5//! This module with `impl` blocks is only used, if all HSM backend features are used:
6//!
7//! - `nethsm`: for NetHSM backends
8//! - `yubihsm2`: for YubiHSM2 backends
9
10use std::collections::HashSet;
11
12use signstar_crypto::{
13    AdministrativeSecretHandling,
14    NonAdministrativeSecretHandling,
15    traits::UserWithPassphrase,
16};
17
18use crate::{
19    AuthorizedKeyEntry,
20    SystemUserId,
21    config::{
22        Config,
23        ConfigAuthorizedKeyEntries,
24        ConfigBuilder,
25        ConfigSystemUserIds,
26        MappingBackendUserSecrets,
27        MappingSystemUserId,
28        SystemConfig,
29        UserBackendConnection,
30        UserBackendConnectionFilter,
31        traits::NonAdminBackendUserIdFilter,
32    },
33    nethsm::NetHsmUserMapping,
34    yubihsm2::YubiHsm2UserMapping,
35};
36
37impl UserBackendConnection {
38    /// Returns the administrative secret handling of this [`UserBackendConnection`].
39    pub fn admin_secret_handling(&self) -> AdministrativeSecretHandling {
40        match self {
41            Self::NetHsm {
42                admin_secret_handling,
43                ..
44            } => *admin_secret_handling,
45            Self::YubiHsm2 {
46                admin_secret_handling,
47                ..
48            } => *admin_secret_handling,
49        }
50    }
51
52    /// Returns the non-administrative secret handling of this [`UserBackendConnection`].
53    pub fn non_admin_secret_handling(&self) -> NonAdministrativeSecretHandling {
54        match self {
55            Self::NetHsm {
56                non_admin_secret_handling,
57                ..
58            } => *non_admin_secret_handling,
59            Self::YubiHsm2 {
60                non_admin_secret_handling,
61                ..
62            } => *non_admin_secret_handling,
63        }
64    }
65
66    /// Creates on-disk secrets for non-administrative backend users of the mapping.
67    ///
68    /// # Note
69    ///
70    /// Delegates to [`MappingBackendUserSecrets::create_non_admin_backend_user_secrets`].
71    ///
72    /// # Errors
73    ///
74    /// Returns an error if [`MappingBackendUserSecrets::create_non_admin_backend_user_secrets`]
75    /// fails.
76    pub fn create_non_admin_backend_user_secrets(
77        &self,
78    ) -> Result<Option<Vec<Box<dyn UserWithPassphrase>>>, crate::Error> {
79        match self {
80            Self::NetHsm {
81                non_admin_secret_handling,
82                mapping,
83                ..
84            } => mapping.create_non_admin_backend_user_secrets(*non_admin_secret_handling),
85            Self::YubiHsm2 {
86                non_admin_secret_handling,
87                mapping,
88                ..
89            } => mapping.create_non_admin_backend_user_secrets(*non_admin_secret_handling),
90        }
91    }
92
93    /// Loads secrets for each backend user matching a `filter`.
94    ///
95    /// # Note
96    ///
97    /// Delegates to [`MappingBackendUserSecrets::load_non_admin_backend_user_secrets`].
98    ///
99    /// # Errors
100    ///
101    /// Returns an error if [`MappingBackendUserSecrets::load_non_admin_backend_user_secrets`]
102    /// fails.
103    pub fn load_non_admin_backend_user_secrets(
104        &self,
105        filter: NonAdminBackendUserIdFilter,
106    ) -> Result<Option<Vec<Box<dyn UserWithPassphrase>>>, crate::Error> {
107        match self {
108            Self::NetHsm {
109                non_admin_secret_handling,
110                mapping,
111                ..
112            } => mapping.load_non_admin_backend_user_secrets(*non_admin_secret_handling, filter),
113            Self::YubiHsm2 {
114                non_admin_secret_handling,
115                mapping,
116                ..
117            } => mapping.load_non_admin_backend_user_secrets(*non_admin_secret_handling, filter),
118        }
119    }
120}
121
122impl Config {
123    /// Returns the optional [`UserBackendConnection`] matching a [`SystemUserId`].
124    pub fn user_backend_connection(&self, user: &SystemUserId) -> Option<UserBackendConnection> {
125        if let Some(nethsm_config) = self.nethsm.as_ref()
126            && let Some(mapping) = nethsm_config
127                .mappings()
128                .iter()
129                .find(|mapping| mapping.system_user_id().is_some_and(|id| id == user))
130        {
131            return Some(UserBackendConnection::NetHsm {
132                admin_secret_handling: *self.system.admin_secret_handling(),
133                non_admin_secret_handling: *self.system.non_admin_secret_handling(),
134                connections: nethsm_config.connections().clone(),
135                mapping: mapping.clone(),
136            });
137        }
138
139        if let Some(yubihsm2_config) = self.yubihsm2.as_ref()
140            && let Some(mapping) = yubihsm2_config
141                .mappings()
142                .iter()
143                .find(|mapping| mapping.system_user_id().is_some_and(|id| id == user))
144        {
145            return Some(UserBackendConnection::YubiHsm2 {
146                admin_secret_handling: *self.system.admin_secret_handling(),
147                non_admin_secret_handling: *self.system.non_admin_secret_handling(),
148                connections: yubihsm2_config.connections().clone(),
149                mapping: mapping.clone(),
150            });
151        }
152
153        None
154    }
155
156    /// Returns a list of [`UserBackendConnection`] objects matching a `filter`.
157    ///
158    /// Using the [`UserBackendConnectionFilter`] `filter` it is possible to only return
159    /// administrative or non-administrative, or all [`UserBackendConnection`] objects..
160    pub fn user_backend_connections(
161        &self,
162        filter: UserBackendConnectionFilter,
163    ) -> Vec<UserBackendConnection> {
164        let mut user_backend_connections = Vec::new();
165
166        if let Some(nethsm_config) = &self.nethsm {
167            let mappings = match filter {
168                UserBackendConnectionFilter::All => {
169                    nethsm_config.mappings().iter().collect::<Vec<_>>()
170                }
171                UserBackendConnectionFilter::Admin => nethsm_config
172                    .mappings()
173                    .iter()
174                    .filter(|mapping| matches!(mapping, NetHsmUserMapping::Admin(_)))
175                    .collect::<Vec<_>>(),
176                UserBackendConnectionFilter::NonAdmin => nethsm_config
177                    .mappings()
178                    .iter()
179                    .filter(|mapping| !matches!(mapping, NetHsmUserMapping::Admin(_)))
180                    .collect::<Vec<_>>(),
181            };
182            for mapping in mappings {
183                user_backend_connections.push(UserBackendConnection::NetHsm {
184                    admin_secret_handling: *self.system.admin_secret_handling(),
185                    non_admin_secret_handling: *self.system.non_admin_secret_handling(),
186                    connections: nethsm_config.connections().clone(),
187                    mapping: mapping.clone(),
188                });
189            }
190        }
191
192        if let Some(yubihsm2_config) = &self.yubihsm2 {
193            let mappings = match filter {
194                UserBackendConnectionFilter::All => {
195                    yubihsm2_config.mappings().iter().collect::<Vec<_>>()
196                }
197                UserBackendConnectionFilter::Admin => yubihsm2_config
198                    .mappings()
199                    .iter()
200                    .filter(|mapping| matches!(mapping, YubiHsm2UserMapping::Admin { .. }))
201                    .collect::<Vec<_>>(),
202                UserBackendConnectionFilter::NonAdmin => yubihsm2_config
203                    .mappings()
204                    .iter()
205                    .filter(|mapping| !matches!(mapping, YubiHsm2UserMapping::Admin { .. }))
206                    .collect::<Vec<_>>(),
207            };
208            for mapping in mappings {
209                user_backend_connections.push(UserBackendConnection::YubiHsm2 {
210                    admin_secret_handling: *self.system.admin_secret_handling(),
211                    non_admin_secret_handling: *self.system.non_admin_secret_handling(),
212                    connections: yubihsm2_config.connections().clone(),
213                    mapping: mapping.clone(),
214                });
215            }
216        }
217
218        user_backend_connections
219    }
220}
221
222impl ConfigAuthorizedKeyEntries for Config {
223    fn authorized_key_entries(&self) -> HashSet<&AuthorizedKeyEntry> {
224        let mut output = self.system.authorized_key_entries();
225        if let Some(nethsm) = &self.nethsm {
226            output.extend(nethsm.authorized_key_entries());
227        }
228        if let Some(yubihsm2) = &self.yubihsm2 {
229            output.extend(yubihsm2.authorized_key_entries());
230        }
231
232        output
233    }
234}
235
236impl ConfigSystemUserIds for Config {
237    fn system_user_ids(&self) -> HashSet<&SystemUserId> {
238        let mut output = self.system.system_user_ids();
239        if let Some(nethsm) = &self.nethsm {
240            output.extend(nethsm.system_user_ids());
241        }
242        if let Some(yubihsm2) = &self.yubihsm2 {
243            output.extend(yubihsm2.system_user_ids());
244        }
245
246        output
247    }
248}
249
250impl ConfigBuilder {
251    /// Creates a new [`ConfigBuilder`].
252    pub fn new(system: SystemConfig) -> Self {
253        Self(Config {
254            system,
255            nethsm: None,
256            yubihsm2: None,
257        })
258    }
259}