signstar_config/
error.rs

1//! Common, top-level error type for all components of signstar-config.
2
3use std::{
4    path::PathBuf,
5    process::{ExitCode, ExitStatus},
6    string::FromUtf8Error,
7};
8
9/// An error that may occur when using Signstar config.
10#[derive(Debug, thiserror::Error)]
11pub enum Error {
12    /// An error specific to administrative secret handling.
13    #[error("Error with administrative secret handling:\n{0}")]
14    AdminSecretHandling(#[from] crate::admin_credentials::Error),
15
16    /// An error specific to Signstar config handling.
17    /// Applying permissions to a file or directory failed.
18    #[error("Unable to apply permissions from mode {mode} to {path}:\n{source}")]
19    ApplyPermissions {
20        /// The path to a file for which permissions can not be applied.
21        path: PathBuf,
22        /// The file mode that should be applied for `path`.
23        mode: u32,
24        /// The source error.
25        source: std::io::Error,
26    },
27
28    /// The ownership of a path can not be changed.
29    #[error("Changing ownership of {path} to user {user} failed:\n{source}")]
30    Chown {
31        /// The path to a file for which ownership can not be changed.
32        path: PathBuf,
33        /// The system user that should be the new owner of `path`.
34        user: String,
35        /// The source error.
36        source: std::io::Error,
37    },
38
39    /// Unable to attach to stdin of a command.
40    #[error("Unable to attach to stdin of command \"{command}\"")]
41    CommandAttachToStdin {
42        /// The command for which attaching to stdin failed.
43        command: String,
44    },
45
46    /// A command exited unsuccessfully.
47    #[error("The command \"{command}\" could not be started in the background:\n{source}")]
48    CommandBackground {
49        /// The command that could not be started in the background.
50        command: String,
51        /// The source error.
52        source: std::io::Error,
53    },
54
55    /// A command could not be executed.
56    #[error("The command \"{command}\" could not be executed:\n{source}")]
57    CommandExec {
58        /// The command that could not be executed.
59        command: String,
60        /// The source error.
61        source: std::io::Error,
62    },
63
64    /// A command exited unsuccessfully.
65    #[error(
66        "The command \"{command}\" exited with non-zero status code \"{exit_status}\":\nstderr:\n{stderr}"
67    )]
68    CommandNonZero {
69        /// The command that exited with a non-zero exit code.
70        command: String,
71        /// The exit status of `command`.
72        exit_status: ExitStatus,
73        /// The stderr of `command`.
74        stderr: String,
75    },
76
77    /// Unable to write to stdin of a command.
78    #[error("Unable to write to stdin of command \"{command}\"")]
79    CommandWriteToStdin {
80        /// The command for which writing to stdin failed.
81        command: String,
82        /// The source error.
83        source: std::io::Error,
84    },
85
86    /// Configuration errors.
87    #[error("Signstar config error:\n{0}")]
88    Config(#[from] crate::config::Error),
89
90    /// A NetHSM error.
91    #[error("NetHSM error:\n{0}")]
92    NetHsm(#[from] nethsm::Error),
93
94    /// A NetHSM backend error
95    ///
96    /// This variant is used when actions for a NetHSM backend fail.
97    #[error("NetHSM backend error:\n{0}")]
98    NetHsmBackend(#[from] crate::NetHsmBackendError),
99
100    /// An error specific to non-administrative secret handling.
101    #[error("Error with non-administrative secret handling:\n{0}")]
102    NonAdminSecretHandling(#[from] crate::non_admin_credentials::Error),
103
104    /// Low-level administrative credentials handling in signstar-common failed.
105    #[error("Handling of administrative credentials failed:\n{0}")]
106    SignstarCommonAdminCreds(#[from] signstar_common::admin_credentials::Error),
107
108    /// Joining a thread returned an error.
109    #[error("Thread error while {context}")]
110    Thread {
111        /// The context in which the failed thread ran.
112        ///
113        /// Should complete the sentence "Thread error while ".
114        context: String,
115    },
116
117    /// A UTF-8 error occurred when trying to convert a byte vector to a string.
118    #[error("Converting contents of {path} to string failed while {context}:\n{source}")]
119    Utf8String {
120        /// The path to a file for which conversion to UTF-8 string failed.
121        path: PathBuf,
122        /// The context in which the error occurred.
123        ///
124        /// Should complete the sentence "Converting contents of `path` to string failed while "
125        context: String,
126        /// The source error.
127        source: FromUtf8Error,
128    },
129
130    /// A utility function returned an error.
131    #[error("Utility function error: {0}")]
132    Utils(#[from] crate::utils::Error),
133}
134
135/// Mapping for relevant [`Error`] variants to an [`ExitCode`].
136#[derive(Clone, Copy, Debug, Eq, num_enum::IntoPrimitive, Ord, PartialEq, PartialOrd)]
137#[repr(u8)]
138pub enum ErrorExitCode {
139    /// Mapping for [`crate::admin_credentials::Error::AdministratorMissing`] wrapped in
140    /// [`Error::AdminSecretHandling`].
141    AdminCredentialsAdministratorMissing = 100,
142
143    /// Mapping for [`crate::admin_credentials::Error::AdministratorNoDefault`] wrapped in
144    /// [`Error::AdminSecretHandling`].
145    AdminCredentialsAdministratorNoDefault = 101,
146
147    /// Mapping for [`crate::admin_credentials::Error::ConfigFromToml`] wrapped in
148    /// [`Error::AdminSecretHandling`].
149    AdminCredentialsConfigFromToml = 102,
150
151    /// Mapping for [`crate::admin_credentials::Error::ConfigLoad`] wrapped in
152    /// [`Error::AdminSecretHandling`].
153    AdminCredentialsConfigLoad = 103,
154
155    /// Mapping for [`crate::admin_credentials::Error::ConfigStore`] wrapped in
156    /// [`Error::AdminSecretHandling`].
157    AdminCredentialsConfigStore = 104,
158
159    /// Mapping for [`crate::admin_credentials::Error::ConfigToToml`] wrapped in
160    /// [`Error::AdminSecretHandling`].
161    AdminCredentialsConfigToToml = 105,
162
163    /// Mapping for [`crate::admin_credentials::Error::CredsFileCreate`] wrapped in
164    /// [`Error::AdminSecretHandling`].
165    AdminCredentialsCredsFileCreate = 106,
166
167    /// Mapping for [`crate::admin_credentials::Error::CredsFileMissing`] wrapped in
168    /// [`Error::AdminSecretHandling`].
169    AdminCredentialsCredsFileMissing = 107,
170
171    /// Mapping for [`crate::admin_credentials::Error::CredsFileNotAFile`] wrapped in
172    /// [`Error::AdminSecretHandling`].
173    AdminCredentialsCredsFileNotAFile = 108,
174
175    /// Mapping for [`crate::admin_credentials::Error::CredsFileWrite`] wrapped in
176    /// [`Error::AdminSecretHandling`].
177    AdminCredentialsCredsFileWrite = 109,
178
179    /// Mapping for [`crate::admin_credentials::Error::PassphraseTooShort`] wrapped in
180    /// [`Error::AdminSecretHandling`].
181    AdminCredentialsPassphraseTooShort = 110,
182
183    /// Mapping for [`Error::ApplyPermissions`].
184    ApplyPermissions = 10,
185
186    /// Mapping for [`Error::Chown`].
187    Chown = 11,
188
189    /// Mapping for [`Error::CommandAttachToStdin`].
190    CommandAttachToStdin = 12,
191
192    /// Mapping for [`Error::CommandBackground`].
193    CommandBackground = 13,
194
195    /// Mapping for [`Error::CommandExec`].
196    CommandExec = 14,
197
198    /// Mapping for [`Error::CommandNonZero`].
199    CommandNonZero = 15,
200
201    /// Mapping for [`Error::CommandWriteToStdin`].
202    CommandWriteToStdin = 16,
203
204    /// Mapping for [`crate::config::Error::ConfigMissing`] wrapped in [`Error::Config`].
205    ConfigConfigMissing = 120,
206
207    /// Mapping for [`crate::config::Error::NetHsmConfig`] wrapped in [`Error::Config`].
208    ConfigNetHsmConfig = 121,
209
210    /// Mapping for [`crate::Error::NetHsm`].
211    NetHsm = 17,
212
213    /// Mapping for [`crate::Error::NetHsmBackend`].
214    NetHsmBackend = 18,
215
216    /// Mapping for [`crate::non_admin_credentials::Error::CredentialsLoading`] wrapped in
217    /// [`Error::NonAdminSecretHandling`].
218    NonAdminCredentialsCredentialsLoading = 140,
219
220    /// Mapping for [`crate::non_admin_credentials::Error::CredentialsMissing`] wrapped in
221    /// [`Error::NonAdminSecretHandling`].
222    NonAdminCredentialsCredentialsMissing = 141,
223
224    /// Mapping for [`crate::non_admin_credentials::Error::NoSystemUser`] wrapped in
225    /// [`Error::NonAdminSecretHandling`].
226    NonAdminCredentialsNoSystemUser = 142,
227
228    /// Mapping for [`crate::non_admin_credentials::Error::NotSigningUser`] wrapped in
229    /// [`Error::NonAdminSecretHandling`].
230    NonAdminCredentialsNotSigningUser = 143,
231
232    /// Mapping for [`crate::non_admin_credentials::Error::SecretsDirCreate`] wrapped in
233    /// [`Error::NonAdminSecretHandling`].
234    NonAdminCredentialsSecretsDirCreate = 144,
235
236    /// Mapping for [`crate::non_admin_credentials::Error::SecretsFileCreate`] wrapped in
237    /// [`Error::NonAdminSecretHandling`].
238    NonAdminCredentialsSecretsFileCreate = 145,
239
240    /// Mapping for [`crate::non_admin_credentials::Error::SecretsFileMetadata`] wrapped in
241    /// [`Error::NonAdminSecretHandling`].
242    NonAdminCredentialsSecretsFileMetadata = 146,
243
244    /// Mapping for [`crate::non_admin_credentials::Error::SecretsFileMissing`] wrapped in
245    /// [`Error::NonAdminSecretHandling`].
246    NonAdminCredentialsSecretsFileMissing = 147,
247
248    /// Mapping for [`crate::non_admin_credentials::Error::SecretsFileNotAFile`] wrapped in
249    /// [`Error::NonAdminSecretHandling`].
250    NonAdminCredentialsSecretsFileNotAFile = 148,
251
252    /// Mapping for [`crate::non_admin_credentials::Error::SecretsFilePermissions`] wrapped in
253    /// [`Error::NonAdminSecretHandling`].
254    NonAdminCredentialsSecretsFilePermissions = 149,
255
256    /// Mapping for [`crate::non_admin_credentials::Error::SecretsFileRead`] wrapped in
257    /// [`Error::NonAdminSecretHandling`].
258    NonAdminCredentialsSecretsFileRead = 150,
259
260    /// Mapping for [`crate::non_admin_credentials::Error::SecretsFileWrite`] wrapped in
261    /// [`Error::NonAdminSecretHandling`].
262    NonAdminCredentialsSecretsFileWrite = 151,
263
264    /// Mapping for [`signstar_common::admin_credentials::Error::ApplyPermissions`] wrapped in
265    /// [`Error::SignstarCommonAdminCreds`].
266    SignstarCommonAdminCredsApplyPermissions = 170,
267
268    /// Mapping for [`signstar_common::admin_credentials::Error::CreateDirectory`] wrapped in
269    /// [`Error::SignstarCommonAdminCreds`].
270    SignstarCommonAdminCredsCreateDirectory = 171,
271
272    /// Mapping for [`signstar_common::admin_credentials::Error::DirChangeOwner`] wrapped in
273    /// [`Error::SignstarCommonAdminCreds`].
274    SignstarCommonAdminCredsDirChangeOwner = 172,
275
276    /// Mapping for [`Error::Thread`].
277    Thread = 19,
278
279    /// Mapping for [`Error::Utf8String`].
280    Utf8String = 20,
281
282    /// Mapping for [`crate::utils::Error::ExecutableNotFound`] wrapped in [`Error::Utils`].
283    UtilsExecutableNotFound = 190,
284
285    /// Mapping for [`crate::utils::Error::MappingSystemUserGet`] wrapped in [`Error::Utils`].
286    UtilsMappingSystemUserGet = 191,
287
288    /// Mapping for [`crate::utils::Error::SystemUserData`] wrapped in [`Error::Utils`].
289    UtilsSystemUserData = 192,
290
291    /// Mapping for [`crate::utils::Error::SystemUserLookup`] wrapped in [`Error::Utils`].
292    UtilsSystemUserLookup = 193,
293
294    /// Mapping for [`crate::utils::Error::SystemUserMismatch`] wrapped in [`Error::Utils`].
295    UtilsSystemUserMismatch = 194,
296
297    /// Mapping for [`crate::utils::Error::SystemUserNotRoot`] wrapped in [`Error::Utils`].
298    UtilsSystemUserNotRoot = 195,
299
300    /// Mapping for [`crate::utils::Error::SystemUserRoot`] wrapped in [`Error::Utils`].
301    UtilsSystemUserRoot = 196,
302}
303
304impl From<Error> for ErrorExitCode {
305    fn from(value: Error) -> Self {
306        match value {
307            // admin credentials related errors and their exit codes
308            Error::AdminSecretHandling(error) => match error {
309                crate::admin_credentials::Error::AdministratorMissing => {
310                    Self::AdminCredentialsAdministratorMissing
311                }
312                crate::admin_credentials::Error::AdministratorNoDefault => {
313                    Self::AdminCredentialsAdministratorNoDefault
314                }
315                crate::admin_credentials::Error::ConfigFromToml { .. } => {
316                    Self::AdminCredentialsConfigFromToml
317                }
318                crate::admin_credentials::Error::ConfigLoad { .. } => {
319                    Self::AdminCredentialsConfigLoad
320                }
321                crate::admin_credentials::Error::ConfigStore { .. } => {
322                    Self::AdminCredentialsConfigStore
323                }
324                crate::admin_credentials::Error::ConfigToToml(_) => {
325                    Self::AdminCredentialsConfigToToml
326                }
327                crate::admin_credentials::Error::CredsFileCreate { .. } => {
328                    Self::AdminCredentialsCredsFileCreate
329                }
330                crate::admin_credentials::Error::CredsFileMissing { .. } => {
331                    Self::AdminCredentialsCredsFileMissing
332                }
333                crate::admin_credentials::Error::CredsFileNotAFile { .. } => {
334                    Self::AdminCredentialsCredsFileNotAFile
335                }
336                crate::admin_credentials::Error::CredsFileWrite { .. } => {
337                    Self::AdminCredentialsCredsFileWrite
338                }
339                crate::admin_credentials::Error::PassphraseTooShort { .. } => {
340                    Self::AdminCredentialsPassphraseTooShort
341                }
342            },
343            // config related errors
344            Error::Config(error) => match error {
345                crate::config::Error::ConfigMissing => Self::ConfigConfigMissing,
346                crate::config::Error::NetHsmConfig(_) => Self::ConfigNetHsmConfig,
347            },
348            // NetHSM related errors
349            Error::NetHsm(_) => Self::NetHsm,
350            // NetHSM backend related errors
351            Error::NetHsmBackend(_) => Self::NetHsmBackend,
352            // non-admin credentials related errors and their exit codes
353            Error::NonAdminSecretHandling(error) => match error {
354                crate::non_admin_credentials::Error::CredentialsLoading { .. } => {
355                    Self::NonAdminCredentialsCredentialsLoading
356                }
357                crate::non_admin_credentials::Error::CredentialsMissing { .. } => {
358                    Self::NonAdminCredentialsCredentialsMissing
359                }
360                crate::non_admin_credentials::Error::NoSystemUser => {
361                    Self::NonAdminCredentialsNoSystemUser
362                }
363                crate::non_admin_credentials::Error::NotSigningUser => {
364                    Self::NonAdminCredentialsNotSigningUser
365                }
366                crate::non_admin_credentials::Error::SecretsDirCreate { .. } => {
367                    Self::NonAdminCredentialsSecretsDirCreate
368                }
369                crate::non_admin_credentials::Error::SecretsFileCreate { .. } => {
370                    Self::NonAdminCredentialsSecretsFileCreate
371                }
372                crate::non_admin_credentials::Error::SecretsFileMetadata { .. } => {
373                    Self::NonAdminCredentialsSecretsFileMetadata
374                }
375                crate::non_admin_credentials::Error::SecretsFileMissing { .. } => {
376                    Self::NonAdminCredentialsSecretsFileMissing
377                }
378                crate::non_admin_credentials::Error::SecretsFileNotAFile { .. } => {
379                    Self::NonAdminCredentialsSecretsFileNotAFile
380                }
381                crate::non_admin_credentials::Error::SecretsFilePermissions { .. } => {
382                    Self::NonAdminCredentialsSecretsFilePermissions
383                }
384                crate::non_admin_credentials::Error::SecretsFileRead { .. } => {
385                    Self::NonAdminCredentialsSecretsFileRead
386                }
387                crate::non_admin_credentials::Error::SecretsFileWrite { .. } => {
388                    Self::NonAdminCredentialsSecretsFileWrite
389                }
390            },
391            // signstar-common admin credentials related errors
392            Error::SignstarCommonAdminCreds(error) => match error {
393                signstar_common::admin_credentials::Error::ApplyPermissions { .. } => {
394                    Self::SignstarCommonAdminCredsApplyPermissions
395                }
396                signstar_common::admin_credentials::Error::CreateDirectory { .. } => {
397                    Self::SignstarCommonAdminCredsCreateDirectory
398                }
399                signstar_common::admin_credentials::Error::DirChangeOwner { .. } => {
400                    Self::SignstarCommonAdminCredsDirChangeOwner
401                }
402            },
403            // utils related errors
404            Error::Utils(error) => match error {
405                crate::utils::Error::ExecutableNotFound { .. } => Self::UtilsExecutableNotFound,
406                crate::utils::Error::MappingSystemUserGet(_) => Self::UtilsMappingSystemUserGet,
407                crate::utils::Error::SystemUserData { .. } => Self::UtilsSystemUserData,
408                crate::utils::Error::SystemUserLookup { .. } => Self::UtilsSystemUserLookup,
409                crate::utils::Error::SystemUserMismatch { .. } => Self::UtilsSystemUserMismatch,
410                crate::utils::Error::SystemUserNotRoot { .. } => Self::UtilsSystemUserNotRoot,
411                crate::utils::Error::SystemUserRoot => Self::UtilsSystemUserRoot,
412            },
413            // top-level errors and their exit codes
414            Error::ApplyPermissions { .. } => Self::ApplyPermissions,
415            Error::CommandAttachToStdin { .. } => Self::CommandAttachToStdin,
416            Error::Chown { .. } => Self::Chown,
417            Error::CommandBackground { .. } => Self::CommandBackground,
418            Error::CommandExec { .. } => Self::CommandExec,
419            Error::CommandNonZero { .. } => Self::CommandNonZero,
420            Error::Thread { .. } => Self::Thread,
421            Error::Utf8String { .. } => Self::Utf8String,
422            Error::CommandWriteToStdin { .. } => Self::CommandWriteToStdin,
423        }
424    }
425}
426
427impl From<ErrorExitCode> for ExitCode {
428    fn from(value: ErrorExitCode) -> Self {
429        Self::from(std::convert::Into::<u8>::into(value))
430    }
431}
432
433impl From<ErrorExitCode> for i32 {
434    fn from(value: ErrorExitCode) -> Self {
435        Self::from(std::convert::Into::<u8>::into(value))
436    }
437}