signstar_config/
non_admin_credentials.rs1use std::{
3 fmt::{Debug, Display},
4 path::PathBuf,
5};
6
7#[cfg(doc)]
8use nethsm::NetHsm;
9use nethsm::{FullCredentials, UserId};
10use signstar_common::common::SECRET_FILE_MODE;
11
12use crate::{
13 ExtendedUserMapping,
14 SignstarConfig,
15 SystemUserId,
16 UserMapping,
17 utils::get_current_system_user,
18};
19
20#[derive(Debug, thiserror::Error)]
22pub enum Error {
23 #[error("Errors occurred when loading credentials for system user {system_user}:\n{errors}")]
25 CredentialsLoading {
26 system_user: SystemUserId,
28 errors: CredentialsLoadingErrors,
30 },
31
32 #[error("There are no credentials for system user {system_user}")]
34 CredentialsMissing {
35 system_user: SystemUserId,
37 },
38
39 #[error("There is no system user in the mapping.")]
41 NoSystemUser,
42
43 #[error("The user is not an operator user in the NetHSM backend used for signing.")]
45 NotSigningUser,
46
47 #[error("Passphrase directory {path} for user {system_user} can not be created:\n{source}")]
49 SecretsDirCreate {
50 path: PathBuf,
52 system_user: SystemUserId,
54 source: std::io::Error,
56 },
57
58 #[error("The secrets file {path} can not be created for user {system_user}:\n{source}")]
60 SecretsFileCreate {
61 path: PathBuf,
63 system_user: SystemUserId,
65 source: std::io::Error,
67 },
68
69 #[error("File metadata of secrets file {path} cannot be retrieved")]
71 SecretsFileMetadata {
72 path: PathBuf,
74 source: std::io::Error,
76 },
77
78 #[error("Secrets file not found: {path}")]
80 SecretsFileMissing {
81 path: PathBuf,
83 },
84
85 #[error("Secrets file is not a file: {path}")]
87 SecretsFileNotAFile {
88 path: PathBuf,
90 },
91
92 #[error("Secrets file {path} has permissions {mode}, but {SECRET_FILE_MODE} is required")]
94 SecretsFilePermissions {
95 path: PathBuf,
97 mode: u32,
99 },
100
101 #[error("Failed reading secrets file {path}:\n{source}")]
103 SecretsFileRead {
104 path: PathBuf,
106 source: std::io::Error,
108 },
109
110 #[error("The secrets file {path} can not be written to for user {system_user}: {source}")]
112 SecretsFileWrite {
113 path: PathBuf,
115 system_user: SystemUserId,
117 source: std::io::Error,
119 },
120}
121
122#[derive(Debug)]
127pub struct CredentialsLoadingError {
128 user_id: UserId,
129 error: crate::Error,
130}
131
132impl CredentialsLoadingError {
133 pub fn new(user_id: UserId, error: crate::Error) -> Self {
135 Self { user_id, error }
136 }
137
138 pub fn get_user_id(&self) -> &UserId {
140 &self.user_id
141 }
142
143 pub fn get_error(&self) -> &crate::Error {
145 &self.error
146 }
147}
148
149impl Display for CredentialsLoadingError {
150 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151 write!(f, "{}: {}", self.user_id, self.error)
152 }
153}
154
155#[derive(Debug)]
157pub struct CredentialsLoadingErrors {
158 errors: Vec<CredentialsLoadingError>,
159}
160
161impl CredentialsLoadingErrors {
162 pub fn new(errors: Vec<CredentialsLoadingError>) -> Self {
164 Self { errors }
165 }
166
167 pub fn get_errors(&self) -> &[CredentialsLoadingError] {
169 &self.errors
170 }
171}
172
173impl Display for CredentialsLoadingErrors {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 write!(
176 f,
177 "{}",
178 self.errors
179 .iter()
180 .map(|error| error.to_string())
181 .collect::<Vec<String>>()
182 .join("\n")
183 )
184 }
185}
186
187#[derive(Debug)]
192pub struct CredentialsLoading {
193 mapping: ExtendedUserMapping,
194 credentials: Vec<FullCredentials>,
195 errors: CredentialsLoadingErrors,
196}
197
198impl CredentialsLoading {
199 pub fn new(
201 mapping: ExtendedUserMapping,
202 credentials: Vec<FullCredentials>,
203 errors: CredentialsLoadingErrors,
204 ) -> Self {
205 Self {
206 mapping,
207 credentials,
208 errors,
209 }
210 }
211
212 pub fn from_system_user() -> Result<Self, crate::Error> {
229 let user = get_current_system_user()?;
230
231 let system_config = SignstarConfig::new_from_file(None)?;
232
233 let Some(mapping) = system_config.get_extended_mapping_for_user(&user.name) else {
234 return Err(
235 crate::ConfigError::NoMatchingMappingForSystemUser { name: user.name }.into(),
236 );
237 };
238
239 let credentials_loading = mapping.load_credentials()?;
241
242 Ok(credentials_loading)
243 }
244
245 pub fn get_mapping(&self) -> &ExtendedUserMapping {
247 &self.mapping
248 }
249
250 pub fn get_credentials(&self) -> &[FullCredentials] {
252 &self.credentials
253 }
254
255 pub fn get_system_user_id(&self) -> Result<&SystemUserId, crate::Error> {
261 match self.mapping.get_user_mapping().get_system_user() {
262 Some(system_user) => Ok(system_user),
263 None => Err(crate::Error::NonAdminSecretHandling(Error::NoSystemUser)),
264 }
265 }
266
267 pub fn has_userid_errors(&self) -> bool {
271 !self.errors.get_errors().is_empty()
272 }
273
274 pub fn get_userid_errors(self) -> CredentialsLoadingErrors {
276 self.errors
277 }
278
279 pub fn has_signing_user(&self) -> bool {
281 matches!(
282 self.mapping.get_user_mapping(),
283 UserMapping::SystemNetHsmOperatorSigning {
284 nethsm_user: _,
285 nethsm_key_setup: _,
286 ssh_authorized_key: _,
287 system_user: _,
288 tag: _,
289 }
290 )
291 }
292
293 pub fn credentials_for_signing_user(self) -> Result<FullCredentials, crate::Error> {
302 if !self.has_signing_user() {
303 return Err(crate::Error::NonAdminSecretHandling(Error::NotSigningUser));
304 }
305
306 if !self.errors.get_errors().is_empty() {
307 return Err(crate::Error::NonAdminSecretHandling(
308 Error::CredentialsLoading {
309 system_user: self.get_system_user_id()?.clone(),
310 errors: self.errors,
311 },
312 ));
313 }
314
315 if let Some(credentials) = self.credentials.first() {
316 Ok(credentials.clone())
317 } else {
318 return Err(crate::Error::NonAdminSecretHandling(
319 Error::CredentialsMissing {
320 system_user: self.get_system_user_id()?.clone(),
321 },
322 ));
323 }
324 }
325}