nethsm/base/
impl_user.rs

1//! [`NetHsm`] implementation for user and namespace handling.
2
3use log::debug;
4use nethsm_sdk_rs::{
5    apis::default_api::{
6        namespaces_get,
7        namespaces_namespace_id_delete,
8        namespaces_namespace_id_put,
9        users_get,
10        users_post,
11        users_user_id_delete,
12        users_user_id_get,
13        users_user_id_passphrase_post,
14        users_user_id_put,
15        users_user_id_tags_get,
16        users_user_id_tags_tag_delete,
17        users_user_id_tags_tag_put,
18    },
19    models::{UserData, UserPassphrasePostData, UserPostData},
20};
21
22#[cfg(doc)]
23use crate::SystemState;
24use crate::{
25    Credentials,
26    Error,
27    NamespaceId,
28    NetHsm,
29    Passphrase,
30    UserError,
31    UserId,
32    UserRole,
33    base::utils::user_or_no_user_string,
34    nethsm_sdk::NetHsmApiError,
35    user::NamespaceSupport,
36};
37
38impl NetHsm {
39    /// Adds a new namespace.
40    ///
41    /// Adds a new [namespace] with the ID `namespace_id`.
42    ///
43    /// **WARNING**: A user in the [`Administrator`][`UserRole::Administrator`] [role] must be added
44    /// for the [namespace] using [`add_user`][`NetHsm::add_user`] **before** creating the
45    /// [namespace]! Otherwise there is no user to administrate the new [namespace]!
46    ///
47    /// This call requires using [`Credentials`] of a system-wide user in the
48    /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
49    ///
50    /// # Errors
51    ///
52    /// Returns an [`Error::Api`] if adding the namespace fails:
53    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
54    /// * the namespace identified by `namespace_id` exists already
55    /// * the used [`Credentials`] are not correct
56    /// * the used [`Credentials`] are not that of a system-wide user in the
57    ///   [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
58    ///
59    /// # Examples
60    ///
61    /// ```no_run
62    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
63    ///
64    /// # fn main() -> testresult::TestResult {
65    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
66    /// let nethsm = NetHsm::new(
67    ///     Connection::new(
68    ///         "https://example.org/api/v1".try_into()?,
69    ///         ConnectionSecurity::Unsafe,
70    ///     ),
71    ///     Some(Credentials::new(
72    ///         "admin".parse()?,
73    ///         Some(Passphrase::new("passphrase".to_string())),
74    ///     )),
75    ///     None,
76    ///     None,
77    /// )?;
78    ///
79    /// // add a user in the Administrator role for a namespace (N-Administrator)
80    /// nethsm.add_user(
81    ///     "Namespace1 Admin".to_string(),
82    ///     UserRole::Administrator,
83    ///     Passphrase::new("namespace1-admin-passphrase".to_string()),
84    ///     Some("namespace1~admin1".parse()?),
85    /// )?;
86    /// // create accompanying namespace
87    /// nethsm.add_namespace(&"namespace1".parse()?)?;
88    ///
89    /// // N-Administrator can not create namespaces
90    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
91    /// assert!(nethsm.add_namespace(&"namespace2".parse()?).is_err());
92    /// # Ok(())
93    /// # }
94    /// ```
95    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
96    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
97    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
98    pub fn add_namespace(&self, namespace_id: &NamespaceId) -> Result<(), Error> {
99        debug!(
100            "Add the namespace {namespace_id} on the NetHSM at {} using {}",
101            self.url.borrow(),
102            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
103        );
104
105        self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
106        namespaces_namespace_id_put(&self.create_connection_config(), namespace_id.as_ref())
107            .map_err(|error| {
108                Error::Api(format!(
109                    "Adding namespace failed: {}",
110                    NetHsmApiError::from(error)
111                ))
112            })?;
113        Ok(())
114    }
115
116    /// Gets all available [namespaces].
117    ///
118    /// This call requires using [`Credentials`] of a system-wide user in the
119    /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
120    ///
121    /// # Errors
122    ///
123    /// Returns an [`Error::Api`] if getting the namespaces fails:
124    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
125    /// * the used [`Credentials`] are not correct
126    /// * the used [`Credentials`] are not that of a system-wide user in the
127    ///   [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
128    ///
129    /// # Examples
130    ///
131    /// ```no_run
132    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
133    ///
134    /// # fn main() -> testresult::TestResult {
135    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
136    /// let nethsm = NetHsm::new(
137    ///     Connection::new(
138    ///         "https://example.org/api/v1".try_into()?,
139    ///         ConnectionSecurity::Unsafe,
140    ///     ),
141    ///     Some(Credentials::new(
142    ///         "admin".parse()?,
143    ///         Some(Passphrase::new("passphrase".to_string())),
144    ///     )),
145    ///     None,
146    ///     None,
147    /// )?;
148    ///
149    /// // print list of all namespaces
150    /// println!("{:?}", nethsm.get_namespaces()?);
151    ///
152    /// // add a user in the Administrator role for a namespace (N-Administrator)
153    /// nethsm.add_user(
154    ///     "Namespace1 Admin".to_string(),
155    ///     UserRole::Administrator,
156    ///     Passphrase::new("namespace1-admin-passphrase".to_string()),
157    ///     Some("namespace1~admin1".parse()?),
158    /// )?;
159    /// // create accompanying namespace
160    /// nethsm.add_namespace(&"namespace1".parse()?)?;
161    ///
162    /// // N-Administrator can not get namespaces
163    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
164    /// assert!(nethsm.get_namespaces().is_err());
165    /// # Ok(())
166    /// # }
167    /// ```
168    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
169    /// [namespaces]: https://docs.nitrokey.com/nethsm/administration#namespaces
170    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
171    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
172    pub fn get_namespaces(&self) -> Result<Vec<NamespaceId>, Error> {
173        debug!(
174            "Retrieve all available namespaces from the NetHSM at {} using {}",
175            self.url.borrow(),
176            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
177        );
178
179        self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
180        let valid_namespaces = {
181            let mut invalid_namespaces = Vec::new();
182            let valid_namespaces = namespaces_get(&self.create_connection_config())
183                .map_err(|error| {
184                    Error::Api(format!(
185                        "Getting namespaces failed: {}",
186                        NetHsmApiError::from(error)
187                    ))
188                })?
189                .entity
190                .into_iter()
191                .filter_map(|x| {
192                    if let Ok(namespace) = NamespaceId::new(x.id.clone()) {
193                        Some(namespace)
194                    } else {
195                        invalid_namespaces.push(x.id);
196                        None
197                    }
198                })
199                .collect::<Vec<NamespaceId>>();
200
201            if !invalid_namespaces.is_empty() {
202                return Err(UserError::InvalidNamespaceIds {
203                    namespace_ids: invalid_namespaces,
204                }
205                .into());
206            }
207            valid_namespaces
208        };
209
210        Ok(valid_namespaces)
211    }
212
213    /// Deletes an existing [namespace].
214    ///
215    /// Deletes the [namespace] identified by `namespace_id`.
216    ///
217    /// **WARNING**: This call deletes the [namespace] and all keys in it! Make sure to create a
218    /// [`backup`][`NetHsm::backup`]!
219    ///
220    /// This call requires using [`Credentials`] of a system-wide user in the
221    /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
222    ///
223    /// # Errors
224    ///
225    /// Returns an [`Error::Api`] if deleting the namespace fails:
226    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
227    /// * the [namespace] identified by `namespace_id` does not exist
228    /// * the used [`Credentials`] are not correct
229    /// * the used [`Credentials`] are not that of a system-wide user in the
230    ///   [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
231    ///
232    /// # Examples
233    ///
234    /// ```no_run
235    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
236    ///
237    /// # fn main() -> testresult::TestResult {
238    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
239    /// let nethsm = NetHsm::new(
240    ///     Connection::new(
241    ///         "https://example.org/api/v1".try_into()?,
242    ///         ConnectionSecurity::Unsafe,
243    ///     ),
244    ///     Some(Credentials::new(
245    ///         "admin".parse()?,
246    ///         Some(Passphrase::new("passphrase".to_string())),
247    ///     )),
248    ///     None,
249    ///     None,
250    /// )?;
251    /// // add a user in the Administrator role for a namespace (N-Administrator)
252    /// nethsm.add_user(
253    ///     "Namespace1 Admin".to_string(),
254    ///     UserRole::Administrator,
255    ///     Passphrase::new("namespace1-admin-passphrase".to_string()),
256    ///     Some("namespace1~admin1".parse()?),
257    /// )?;
258    /// // create accompanying namespace
259    /// nethsm.add_namespace(&"namespace1".parse()?)?;
260    ///
261    /// // N-Administrators can not delete namespaces
262    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
263    /// assert!(nethsm.delete_namespace(&"namespace1".parse()?).is_err());
264    ///
265    /// // R-Administrators can delete namespaces
266    /// nethsm.use_credentials(&"admin".parse()?)?;
267    /// nethsm.delete_namespace(&"namespace1".parse()?)?;
268    /// # Ok(())
269    /// # }
270    /// ```
271    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
272    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
273    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
274    pub fn delete_namespace(&self, namespace_id: &NamespaceId) -> Result<(), Error> {
275        debug!(
276            "Delete the namespace {namespace_id} from the NetHSM at {} using {}",
277            self.url.borrow(),
278            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
279        );
280
281        self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
282        namespaces_namespace_id_delete(&self.create_connection_config(), namespace_id.as_ref())
283            .map_err(|error| {
284                Error::Api(format!(
285                    "Deleting namespace failed: {}",
286                    NetHsmApiError::from(error)
287                ))
288            })?;
289        Ok(())
290    }
291
292    /// [Adds a user] and returns its User ID.
293    ///
294    /// A new user is created by providing a `real_name` from which a User ID is derived (optionally
295    /// a User ID can be provided with `user_id`), a `role` which describes the user's access rights
296    /// on the NetHSM (see [`UserRole`]) and a `passphrase`.
297    ///
298    /// Internally, this function also calls [`add_credentials`][`NetHsm::add_credentials`] to
299    /// add the new user to the list of available credentials.
300    ///
301    /// This call requires using [`Credentials`] of a user in the
302    /// [`Administrator`][`UserRole::Administrator`] [role].
303    /// When adding a user to a [namespace], that does not yet exist, the caller must
304    /// be a system-wide [`Administrator`][`UserRole::Administrator`] (*R-Administrator*).
305    /// When adding a user to an already existing [namespace], the caller must be an
306    /// [`Administrator`][`UserRole::Administrator`] in that [namespace]
307    /// (*N-Administrator*).
308    ///
309    /// ## Namespaces
310    ///
311    /// New users *implicitly* inherit the [namespace] of the caller.
312    /// A [namespace] can be provided *explicitly* by prefixing the User ID with the ID of a
313    /// [namespace] and the `~` character (e.g. `namespace1~user1`).
314    /// When specifying a namespace as part of the User ID and the [namespace] exists already, the
315    /// caller must be an [`Administrator`][`UserRole::Administrator`] of that [namespace]
316    /// (*N-Administrator*).
317    /// When specifying a [namespace] as part of the User ID and the [namespace] does not yet exist,
318    /// the caller must be a system-wide [`Administrator`][`UserRole::Administrator`]
319    /// (*R-Administrator*).
320    ///
321    /// **NOTE**: Users in the [`Backup`][`UserRole::Backup`] and [`Metrics`][`UserRole::Metrics`]
322    /// [role] can not be created for a [namespace], as their underlying functionality can only be
323    /// used in a system-wide context!
324    ///
325    /// # Errors
326    ///
327    /// Returns an [`Error::Api`] if adding the user fails:
328    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
329    /// * the provided `real_name`, `passphrase` or `user_id` are not valid
330    /// * the provided `user_id` exists already
331    /// * the used [`Credentials`] are not correct
332    /// * the used [`Credentials`] are not that of a system-wide
333    ///   [`Administrator`][`UserRole::Administrator`], when adding a user to a not yet existing
334    ///   [namespace]
335    /// * the used [`Credentials`] are not that of an [`Administrator`][`UserRole::Administrator`]
336    ///   in the [namespace] the user is about to be added to
337    ///
338    /// # Examples
339    ///
340    /// ```no_run
341    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
342    ///
343    /// # fn main() -> testresult::TestResult {
344    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
345    /// let nethsm = NetHsm::new(
346    ///     Connection::new(
347    ///         "https://example.org/api/v1".try_into()?,
348    ///         ConnectionSecurity::Unsafe,
349    ///     ),
350    ///     Some(Credentials::new(
351    ///         "admin".parse()?,
352    ///         Some(Passphrase::new("passphrase".to_string())),
353    ///     )),
354    ///     None,
355    ///     None,
356    /// )?;
357    ///
358    /// // add a system-wide user in the Operator role
359    /// nethsm.add_user(
360    ///     "Operator One".to_string(),
361    ///     UserRole::Operator,
362    ///     Passphrase::new("operator1-passphrase".to_string()),
363    ///     Some("user1".parse()?),
364    /// )?;
365    ///
366    /// // this fails because the user exists already
367    /// assert!(nethsm
368    ///     .add_user(
369    ///         "Operator One".to_string(),
370    ///         UserRole::Operator,
371    ///         Passphrase::new("operator1-passphrase".to_string()),
372    ///         Some("user1".parse()?),
373    ///     )
374    ///     .is_err());
375    ///
376    /// // add a user in the Administrator role (N-Administrator) for a not yet existing namespace "namespace1"
377    /// nethsm.add_user(
378    ///     "Namespace1 Admin".to_string(),
379    ///     UserRole::Administrator,
380    ///     Passphrase::new("namespace1-admin-passphrase".to_string()),
381    ///     Some("namespace1~admin1".parse()?),
382    /// )?;
383    ///
384    /// # Ok(())
385    /// # }
386    /// ```
387    /// [Adds a user]: https://docs.nitrokey.com/nethsm/administration#add-user
388    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
389    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
390    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
391    pub fn add_user(
392        &self,
393        real_name: String,
394        role: UserRole,
395        passphrase: Passphrase,
396        user_id: Option<UserId>,
397    ) -> Result<UserId, Error> {
398        debug!(
399            "Add the user \"{real_name}\"{} in the role {role} to the NetHSM at {} using {}",
400            if let Some(user_id) = user_id.as_ref() {
401                format!(" (\"{user_id}\")")
402            } else {
403                "".to_string()
404            },
405            self.url.borrow(),
406            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
407        );
408
409        self.validate_namespace_access(NamespaceSupport::Supported, user_id.as_ref(), Some(&role))?;
410        let user_id = if let Some(user_id) = user_id {
411            users_user_id_put(
412                &self.create_connection_config(),
413                &user_id.to_string(),
414                UserPostData::new(real_name, role.into(), passphrase.expose_owned()),
415            )
416            .map_err(|error| {
417                Error::Api(format!(
418                    "Adding user failed: {}",
419                    NetHsmApiError::from(error)
420                ))
421            })?;
422            user_id
423        } else {
424            UserId::new(
425                users_post(
426                    &self.create_connection_config(),
427                    UserPostData::new(real_name, role.into(), passphrase.expose_owned()),
428                )
429                .map_err(|error| {
430                    Error::Api(format!(
431                        "Adding user failed: {}",
432                        NetHsmApiError::from(error)
433                    ))
434                })?
435                .entity
436                .id,
437            )?
438        };
439
440        // add to list of users
441        self.add_credentials(Credentials::new(user_id.clone(), Some(passphrase)));
442
443        Ok(user_id)
444    }
445
446    /// Deletes an existing user.
447    ///
448    /// [Deletes a user] identified by `user_id`.
449    ///
450    /// Internally, this function also calls [`remove_credentials`][`NetHsm::remove_credentials`] to
451    /// remove the user from the list of available credentials.
452    ///
453    /// This call requires using [`Credentials`] of a user in the
454    /// [`Administrator`][`UserRole::Administrator`] [role].
455    ///
456    /// ## Namespaces
457    ///
458    /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
459    ///   [namespace]) can only delete users in their own [namespace].
460    /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) can
461    ///   only delete system-wide users, but not those in a [namespace]. To allow *R-Administrators*
462    ///   to delete users in a [namespace], the given [namespace] has to be deleted first using
463    ///   [`delete_namespace`][`NetHsm::delete_namespace`].
464    ///
465    /// # Errors
466    ///
467    /// Returns an [`Error::Api`] if deleting a user fails:
468    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
469    /// * the user identified by `user_id` does not exist
470    /// * the used [`Credentials`] are not correct
471    /// * the used [`Credentials`] are not that of a user in the
472    ///   [`Administrator`][`UserRole::Administrator`] role
473    /// * the targeted user is in an existing [namespace], but the caller is an *R-Administrator* or
474    ///   an *N-Administrator* in a different [namespace]
475    /// * the targeted user is a system-wide user, but the caller is not an *R-Administrator*
476    /// * the user attempts to delete itself
477    ///
478    /// # Examples
479    ///
480    /// ```no_run
481    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
482    ///
483    /// # fn main() -> testresult::TestResult {
484    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
485    /// let nethsm = NetHsm::new(
486    ///     Connection::new(
487    ///         "https://example.org/api/v1".try_into()?,
488    ///         ConnectionSecurity::Unsafe,
489    ///     ),
490    ///     Some(Credentials::new(
491    ///         "admin".parse()?,
492    ///         Some(Passphrase::new("passphrase".to_string())),
493    ///     )),
494    ///     None,
495    ///     None,
496    /// )?;
497    ///
498    /// // add a system-wide user in the Operator role
499    /// nethsm.add_user(
500    ///     "Operator One".to_string(),
501    ///     UserRole::Operator,
502    ///     Passphrase::new("operator1-passphrase".to_string()),
503    ///     Some("user1".parse()?),
504    /// )?;
505    ///
506    /// // add a user in the Administrator role for a namespace (N-Administrator)
507    /// nethsm.add_user(
508    ///     "Namespace1 Admin".to_string(),
509    ///     UserRole::Administrator,
510    ///     Passphrase::new("namespce1-admin-passphrase".to_string()),
511    ///     Some("namespace1~admin1".parse()?),
512    /// )?;
513    /// // add the accompanying namespace
514    /// nethsm.add_namespace(&"namespace1".parse()?)?;
515    ///
516    /// // R-Administrators can not delete N-Administrators, as long as their namespace exists
517    /// assert!(nethsm.delete_user(&"namespace1~admin1".parse()?).is_err());
518    /// // however, after deleting the namespace, this becomes possible
519    /// nethsm.delete_namespace(&"namespace1".parse()?)?;
520    /// nethsm.delete_user(&"namespace1~admin1".parse()?)?;
521    ///
522    /// // R-Administrators can delete system-wide users
523    /// nethsm.delete_user(&"user1".parse()?)?;
524    /// # Ok(())
525    /// # }
526    /// ```
527    /// [Deletes a user]: https://docs.nitrokey.com/nethsm/administration#delete-user
528    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
529    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
530    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
531    pub fn delete_user(&self, user_id: &UserId) -> Result<(), Error> {
532        debug!(
533            "Delete the user \"{user_id}\" from the NetHSM at {} using {}",
534            self.url.borrow(),
535            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
536        );
537
538        self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
539        users_user_id_delete(&self.create_connection_config(), &user_id.to_string()).map_err(
540            |error| {
541                Error::Api(format!(
542                    "Deleting user failed: {}",
543                    NetHsmApiError::from(error)
544                ))
545            },
546        )?;
547
548        // remove from list of credentials
549        self.remove_credentials(user_id);
550
551        Ok(())
552    }
553
554    /// Gets a [list of all User IDs].
555    ///
556    /// This call requires using [`Credentials`] of a user in the
557    /// [`Administrator`][`UserRole::Administrator`] [role].
558    ///
559    /// ## Namespaces
560    ///
561    /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
562    ///   [namespace]) can only list users in their own [namespace].
563    /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) can
564    ///   list all users on the system.
565    ///
566    /// # Errors
567    ///
568    /// Returns an [`Error::Api`] if retrieving the list of all User IDs fails:
569    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
570    /// * the used [`Credentials`] are not correct
571    /// * the used [`Credentials`] are not that of a user in the
572    ///   [`Administrator`][`UserRole::Administrator`] role
573    ///
574    /// # Examples
575    ///
576    /// ```no_run
577    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
578    ///
579    /// # fn main() -> testresult::TestResult {
580    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
581    /// let nethsm = NetHsm::new(
582    ///     Connection::new(
583    ///         "https://example.org/api/v1".try_into()?,
584    ///         ConnectionSecurity::Unsafe,
585    ///     ),
586    ///     Some(Credentials::new(
587    ///         "admin".parse()?,
588    ///         Some(Passphrase::new("passphrase".to_string())),
589    ///     )),
590    ///     None,
591    ///     None,
592    /// )?;
593    ///
594    /// // add a user in the Administrator role for a namespace (N-Administrator)
595    /// nethsm.add_user(
596    ///     "Namespace1 Admin".to_string(),
597    ///     UserRole::Administrator,
598    ///     Passphrase::new("namespce1-admin-passphrase".to_string()),
599    ///     Some("namespace1~admin1".parse()?),
600    /// )?;
601    /// // add the accompanying namespace
602    /// nethsm.add_namespace(&"namespace1".parse()?)?;
603    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
604    /// // the N-Administrator only sees itself
605    /// assert_eq!(nethsm.get_users()?.len(), 1);
606    ///
607    /// // use the credentials of the R-Administrator
608    /// nethsm.use_credentials(&"admin".parse()?)?;
609    /// // the R-Administrator sees at least itself and the previously created N-Administrator
610    /// assert!(nethsm.get_users()?.len() >= 2);
611    /// # Ok(())
612    /// # }
613    /// ```
614    /// [list of all User IDs]: https://docs.nitrokey.com/nethsm/administration#list-users
615    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
616    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
617    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
618    pub fn get_users(&self) -> Result<Vec<UserId>, Error> {
619        debug!(
620            "Get the users of the NetHSM at {} using {}",
621            self.url.borrow(),
622            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
623        );
624
625        self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
626        let valid_users = {
627            let mut invalid_users = Vec::new();
628            let valid_users = users_get(&self.create_connection_config())
629                .map_err(|error| {
630                    Error::Api(format!(
631                        "Getting users failed: {}",
632                        NetHsmApiError::from(error)
633                    ))
634                })?
635                .entity
636                .into_iter()
637                .filter_map(|x| {
638                    if let Ok(user) = UserId::new(x.user.clone()) {
639                        Some(user)
640                    } else {
641                        invalid_users.push(x.user);
642                        None
643                    }
644                })
645                .collect::<Vec<UserId>>();
646
647            if !invalid_users.is_empty() {
648                return Err(UserError::InvalidUserIds {
649                    user_ids: invalid_users,
650                }
651                .into());
652            }
653
654            valid_users
655        };
656
657        Ok(valid_users)
658    }
659
660    /// Gets [information of a user].
661    ///
662    /// This call requires using [`Credentials`] of a user in the
663    /// [`Administrator`][`UserRole::Administrator`] [role].
664    ///
665    /// ## Namespaces
666    ///
667    /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
668    ///   [namespace]) can only access information about users in their own [namespace].
669    /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) can
670    ///   access information about all users on the system.
671    ///
672    /// # Errors
673    ///
674    /// Returns an [`Error::Api`] if retrieving information of the user fails:
675    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
676    /// * the user identified by `user_id` does not exist
677    /// * the used [`Credentials`] are not correct
678    /// * the used [`Credentials`] are not that of a user in the
679    ///   [`Administrator`][`UserRole::Administrator`] role
680    /// * the used [`Credentials`] do not provide access to information about a user in the targeted
681    ///   [namespace] (*N-Administrator* of a different [namespace])
682    ///
683    /// # Examples
684    ///
685    /// ```no_run
686    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
687    ///
688    /// # fn main() -> testresult::TestResult {
689    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
690    /// let nethsm = NetHsm::new(
691    ///     Connection::new(
692    ///         "https://example.org/api/v1".try_into()?,
693    ///         ConnectionSecurity::Unsafe,
694    ///     ),
695    ///     Some(Credentials::new(
696    ///         "admin".parse()?,
697    ///         Some(Passphrase::new("passphrase".to_string())),
698    ///     )),
699    ///     None,
700    ///     None,
701    /// )?;
702    ///
703    /// // add a user in the Administrator role for a namespace (N-Administrator)
704    /// nethsm.add_user(
705    ///     "Namespace1 Admin".to_string(),
706    ///     UserRole::Administrator,
707    ///     Passphrase::new("namespce1-admin-passphrase".to_string()),
708    ///     Some("namespace1~admin1".parse()?),
709    /// )?;
710    /// // add the accompanying namespace
711    /// nethsm.add_namespace(&"namespace1".parse()?)?;
712    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
713    /// // the N-Administrator sees itself
714    /// println!("{:?}", nethsm.get_user(&"namespace1~admin1".parse()?)?);
715    /// // the N-Administrator can not see the R-Administrator
716    /// assert!(nethsm.get_user(&"admin".parse()?).is_err());
717    ///
718    /// nethsm.use_credentials(&"admin".parse()?)?;
719    /// // the R-Administrator sees itself
720    /// println!("{:?}", nethsm.get_user(&"admin".parse()?)?);
721    /// // the R-Administrator sees the N-Administrator
722    /// println!("{:?}", nethsm.get_user(&"namespace1~admin1".parse()?)?);
723    /// // this fails if the user does not exist
724    /// assert!(nethsm.get_user(&"user1".parse()?).is_err());
725    /// # Ok(())
726    /// # }
727    /// ```
728    /// [information of a user]: https://docs.nitrokey.com/nethsm/administration#list-users
729    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
730    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
731    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
732    pub fn get_user(&self, user_id: &UserId) -> Result<UserData, Error> {
733        debug!(
734            "Get the information of the user \"{user_id}\" on the NetHSM at {} using {}",
735            self.url.borrow(),
736            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
737        );
738
739        self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
740        Ok(
741            users_user_id_get(&self.create_connection_config(), &user_id.to_string())
742                .map_err(|error| {
743                    Error::Api(format!(
744                        "Getting user failed: {}",
745                        NetHsmApiError::from(error)
746                    ))
747                })?
748                .entity,
749        )
750    }
751
752    /// Sets the [passphrase for a user] on the NetHSM.
753    ///
754    /// ## Namespaces
755    ///
756    /// *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
757    /// [namespace]) are only able to set the passphrases for users in their own [namespace].
758    /// *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are only
759    /// able to set the passphrases for system-wide users.
760    ///
761    /// Internally, this function also calls [`add_credentials`][`NetHsm::add_credentials`] to add
762    /// the updated user [`Credentials`] to the list of available ones.
763    /// If the calling user is in the [`Administrator`][`UserRole::Administrator`] [role] and
764    /// changes their own passphrase, additionally
765    /// [`use_credentials`][`NetHsm::use_credentials`] is called to use the updated passphrase
766    /// after changing it.
767    ///
768    /// This call requires using [`Credentials`] of a user in the
769    /// [`Administrator`][`UserRole::Administrator`] [role].
770    ///
771    /// # Errors
772    ///
773    /// Returns an [`Error::Api`] if setting the passphrase for the user fails:
774    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
775    /// * the user identified by `user_id` does not exist
776    /// * the used [`Credentials`] are not correct
777    /// * the used [`Credentials`] are not that of a user in the
778    ///   [`Administrator`][`UserRole::Administrator`] [role]
779    /// * the targeted user is in a [namespace], but the caller is not an
780    ///   [`Administrator`][`UserRole::Administrator`] of that [namespace] (*N-Administrator*)
781    /// * the targeted user is a system-wide user, but the caller is not a system-wide
782    ///   [`Administrator`][`UserRole::Administrator`] (*R-Administrator*)
783    ///
784    /// # Examples
785    ///
786    /// ```no_run
787    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
788    ///
789    /// # fn main() -> testresult::TestResult {
790    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
791    /// let nethsm = NetHsm::new(
792    ///     Connection::new(
793    ///         "https://example.org/api/v1".try_into()?,
794    ///         ConnectionSecurity::Unsafe,
795    ///     ),
796    ///     Some(Credentials::new(
797    ///         "admin".parse()?,
798    ///         Some(Passphrase::new("passphrase".to_string())),
799    ///     )),
800    ///     None,
801    ///     None,
802    /// )?;
803    /// // add a user in the Administrator role for a namespace (N-Administrator)
804    /// nethsm.add_user(
805    ///     "Namespace1 Admin".to_string(),
806    ///     UserRole::Administrator,
807    ///     Passphrase::new("namespce1-admin-passphrase".to_string()),
808    ///     Some("namespace1~admin1".parse()?),
809    /// )?;
810    /// // add the accompanying namespace
811    /// nethsm.add_namespace(&"namespace1".parse()?)?;
812    ///
813    /// // the R-Administrator can set its own passphrase
814    /// nethsm.set_user_passphrase(
815    ///     "admin".parse()?,
816    ///     Passphrase::new("new-admin-passphrase".to_string()),
817    /// )?;
818    /// // the R-Administrator can not set the N-Administrator's passphrase
819    /// assert!(
820    ///     nethsm
821    ///         .set_user_passphrase(
822    ///             "namespace1~admin".parse()?,
823    ///             Passphrase::new("new-admin-passphrase".to_string()),
824    ///         )
825    ///         .is_err()
826    /// );
827    ///
828    /// // the N-Administrator can set its own passphrase
829    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
830    /// nethsm.set_user_passphrase(
831    ///     "namespace1~admin1".parse()?,
832    ///     Passphrase::new("new-admin-passphrase".to_string()),
833    /// )?;
834    /// // the N-Administrator can not set the R-Administrator's passphrase
835    /// assert!(
836    ///     nethsm
837    ///         .set_user_passphrase(
838    ///             "admin".parse()?,
839    ///             Passphrase::new("new-admin-passphrase".to_string())
840    ///         )
841    ///         .is_err()
842    /// );
843    /// # Ok(())
844    /// # }
845    /// ```
846    /// [passphrase for a user]: https://docs.nitrokey.com/nethsm/administration#user-passphrase
847    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
848    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
849    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
850    pub fn set_user_passphrase(
851        &self,
852        user_id: UserId,
853        passphrase: Passphrase,
854    ) -> Result<(), Error> {
855        debug!(
856            "Set the passphrase of the user \"{user_id}\" on the NetHSM at {} using {}",
857            self.url.borrow(),
858            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
859        );
860
861        self.validate_namespace_access(NamespaceSupport::Supported, Some(&user_id), None)?;
862        users_user_id_passphrase_post(
863            &self.create_connection_config(),
864            &user_id.to_string(),
865            UserPassphrasePostData::new(passphrase.expose_owned()),
866        )
867        .map_err(|error| {
868            Error::Api(format!(
869                "Setting user passphrase failed: {}",
870                NetHsmApiError::from(error)
871            ))
872        })?;
873
874        // add to list of available credentials
875        self.add_credentials(Credentials::new(user_id, Some(passphrase)));
876
877        Ok(())
878    }
879
880    /// [Adds a tag] to a user in the [`Operator`][`UserRole::Operator`] [role].
881    ///
882    /// A `tag` provides the user identified by `user_id` with access to keys in their [namespace],
883    /// that are tagged with that same `tag`.
884    ///
885    /// **NOTE**: The tag for the key in the same [namespace] must be added beforehand, by calling
886    /// [`add_key_tag`][`NetHsm::add_key_tag`].
887    ///
888    /// This call requires using [`Credentials`] of a user in the
889    /// [`Administrator`][`UserRole::Administrator`] [role].
890    ///
891    /// ## Namespaces
892    ///
893    /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
894    ///   [namespace]) are only able to add tags for users in their own [namespace].
895    /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
896    ///   only able to add tags for system-wide users.
897    ///
898    /// # Errors
899    ///
900    /// Returns an [`Error::Api`] if adding the tag for the user fails:
901    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
902    /// * the user identified by `user_id` does not exist
903    /// * the user identified by `user_id` is not in the [`Operator`][`UserRole::Operator`] [role]
904    /// * the used [`Credentials`] are not correct
905    /// * the used [`Credentials`] are not that of a user in the
906    ///   [`Administrator`][`UserRole::Administrator`] [role]
907    /// * the caller does not have access to the target user's [namespace]
908    ///
909    /// # Examples
910    ///
911    /// ```no_run
912    /// use nethsm::{
913    ///     Connection,
914    ///     ConnectionSecurity,
915    ///     Credentials,
916    ///     KeyMechanism,
917    ///     KeyType,
918    ///     NetHsm,
919    ///     Passphrase,
920    ///     UserRole,
921    /// };
922    ///
923    /// # fn main() -> testresult::TestResult {
924    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
925    /// let nethsm = NetHsm::new(
926    ///     Connection::new(
927    ///         "https://example.org/api/v1".try_into()?,
928    ///         ConnectionSecurity::Unsafe,
929    ///     ),
930    ///     Some(Credentials::new(
931    ///         "admin".parse()?,
932    ///         Some(Passphrase::new("passphrase".to_string())),
933    ///     )),
934    ///     None,
935    ///     None,
936    /// )?;
937    /// // add a user in the Administrator role for a namespace (N-Administrator)
938    /// nethsm.add_user(
939    ///     "Namespace1 Admin".to_string(),
940    ///     UserRole::Administrator,
941    ///     Passphrase::new("namespce1-admin-passphrase".to_string()),
942    ///     Some("namespace1~admin1".parse()?),
943    /// )?;
944    /// // add a user in the Operator role for a namespace
945    /// nethsm.add_user(
946    ///     "Namespace1 Operator".to_string(),
947    ///     UserRole::Operator,
948    ///     Passphrase::new("namespce1-operator-passphrase".to_string()),
949    ///     Some("namespace1~operator1".parse()?),
950    /// )?;
951    /// // add the accompanying namespace
952    /// nethsm.add_namespace(&"namespace1".parse()?)?;
953    /// // add a system-wide user in the Operator role
954    /// nethsm.add_user(
955    ///     "Operator One".to_string(),
956    ///     UserRole::Operator,
957    ///     Passphrase::new("operator1-passphrase".to_string()),
958    ///     Some("user1".parse()?),
959    /// )?;
960    /// // generate system-wide key with tag
961    /// nethsm.generate_key(
962    ///     KeyType::Curve25519,
963    ///     vec![KeyMechanism::EdDsaSignature],
964    ///     None,
965    ///     Some("signing1".parse()?),
966    ///     Some(vec!["tag1".to_string()]),
967    /// )?;
968    ///
969    /// // R-Administrators can add tags for system-wide users
970    /// nethsm.add_user_tag(&"user1".parse()?, "tag1")?;
971    /// // R-Administrators can not add tags for namespace users
972    /// assert!(
973    ///     nethsm
974    ///         .add_user_tag(&"namespace1~user1".parse()?, "tag1")
975    ///         .is_err()
976    /// );
977    ///
978    /// // user tags in namespaces
979    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
980    /// // generate key in namespace1 with tag
981    /// nethsm.generate_key(
982    ///     KeyType::Curve25519,
983    ///     vec![KeyMechanism::EdDsaSignature],
984    ///     None,
985    ///     Some("signing2".parse()?),
986    ///     Some(vec!["tag2".to_string()]),
987    /// )?;
988    /// // N-Administrators can not add tags to system-wide users
989    /// assert!(nethsm.add_user_tag(&"user1".parse()?, "tag2").is_err());
990    /// // N-Administrators can add tags to users in their own namespace
991    /// nethsm.add_user_tag(&"namespace1~user1".parse()?, "tag2")?;
992    /// # Ok(())
993    /// # }
994    /// ```
995    /// [Adds a tag]: https://docs.nitrokey.com/nethsm/administration#tags-for-users
996    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
997    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
998    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
999    pub fn add_user_tag(&self, user_id: &UserId, tag: &str) -> Result<(), Error> {
1000        debug!(
1001            "Add the tag \"{tag}\" for the user \"{user_id}\" on the NetHSM at {} using {}",
1002            self.url.borrow(),
1003            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1004        );
1005
1006        self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
1007        users_user_id_tags_tag_put(&self.create_connection_config(), &user_id.to_string(), tag)
1008            .map_err(|error| {
1009                Error::Api(format!(
1010                    "Adding tag for user failed: {}",
1011                    NetHsmApiError::from(error)
1012                ))
1013            })?;
1014        Ok(())
1015    }
1016
1017    /// [Deletes a tag] from a user in the [`Operator`][`UserRole::Operator`] [role].
1018    ///
1019    /// Removes a `tag` from a target user identified by `user_id`, which removes its access to any
1020    /// key in their [namespace], that carries the same `tag`.
1021    ///
1022    /// This call requires using [`Credentials`] of a user in the
1023    /// [`Administrator`][`UserRole::Administrator`] [role].
1024    ///
1025    /// ## Namespaces
1026    ///
1027    /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
1028    ///   [namespace]) are only able to delete tags for users in their own [namespace].
1029    /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
1030    ///   only able to delete tags for system-wide users.
1031    ///
1032    /// # Errors
1033    ///
1034    /// Returns an [`Error::Api`] if deleting the tag from the user fails:
1035    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1036    /// * the user identified by `user_id` does not exist
1037    /// * the user identified by `user_id` is not in the [`Operator`][`UserRole::Operator`] [role]
1038    /// * the `tag` is not added to user identified by `user_id`
1039    /// * the used [`Credentials`] are not correct
1040    /// * the used [`Credentials`] are not that of a user in the
1041    ///   [`Administrator`][`UserRole::Administrator`] [role]
1042    /// * the caller does not have access to the target user's [namespace]
1043    ///
1044    /// # Examples
1045    ///
1046    /// ```no_run
1047    /// use nethsm::{
1048    ///     Connection,
1049    ///     ConnectionSecurity,
1050    ///     Credentials,
1051    ///     KeyMechanism,
1052    ///     KeyType,
1053    ///     NetHsm,
1054    ///     Passphrase,
1055    ///     UserRole,
1056    /// };
1057    ///
1058    /// # fn main() -> testresult::TestResult {
1059    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1060    /// let nethsm = NetHsm::new(
1061    ///     Connection::new(
1062    ///         "https://example.org/api/v1".try_into()?,
1063    ///         ConnectionSecurity::Unsafe,
1064    ///     ),
1065    ///     Some(Credentials::new(
1066    ///         "admin".parse()?,
1067    ///         Some(Passphrase::new("passphrase".to_string())),
1068    ///     )),
1069    ///     None,
1070    ///     None,
1071    /// )?;
1072    /// // add a user in the Administrator role for a namespace (N-Administrator)
1073    /// nethsm.add_user(
1074    ///     "Namespace1 Admin".to_string(),
1075    ///     UserRole::Administrator,
1076    ///     Passphrase::new("namespce1-admin-passphrase".to_string()),
1077    ///     Some("namespace1~admin1".parse()?),
1078    /// )?;
1079    /// // add a user in the Operator role for a namespace
1080    /// nethsm.add_user(
1081    ///     "Namespace1 Operator".to_string(),
1082    ///     UserRole::Operator,
1083    ///     Passphrase::new("namespce1-operator-passphrase".to_string()),
1084    ///     Some("namespace1~operator1".parse()?),
1085    /// )?;
1086    /// // add the accompanying namespace
1087    /// nethsm.add_namespace(&"namespace1".parse()?)?;
1088    /// // add a system-wide user in the Operator role
1089    /// nethsm.add_user(
1090    ///     "Operator One".to_string(),
1091    ///     UserRole::Operator,
1092    ///     Passphrase::new("operator1-passphrase".to_string()),
1093    ///     Some("user1".parse()?),
1094    /// )?;
1095    /// // generate system-wide key with tag
1096    /// nethsm.generate_key(
1097    ///     KeyType::Curve25519,
1098    ///     vec![KeyMechanism::EdDsaSignature],
1099    ///     None,
1100    ///     Some("signing1".parse()?),
1101    ///     Some(vec!["tag1".to_string()]),
1102    /// )?;
1103    /// // add tag for system-wide user
1104    /// nethsm.add_user_tag(&"user1".parse()?, "tag1")?;
1105    ///
1106    /// // N-Administrators can not delete tags from system-wide Operator users
1107    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1108    /// assert!(nethsm.delete_user_tag(&"user1".parse()?, "tag2").is_err());
1109    ///
1110    /// // R-Administrators can delete tags from system-wide Operator users
1111    /// nethsm.use_credentials(&"admin".parse()?)?;
1112    /// nethsm.delete_user_tag(&"user1".parse()?, "tag1")?;
1113    /// # Ok(())
1114    /// # }
1115    /// ```
1116    /// [Deletes a tag]: https://docs.nitrokey.com/nethsm/administration#tags-for-users
1117    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
1118    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1119    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1120    pub fn delete_user_tag(&self, user_id: &UserId, tag: &str) -> Result<(), Error> {
1121        debug!(
1122            "Delete the tag \"{tag}\" from the user \"{user_id}\" on the NetHSM at {} using {}",
1123            self.url.borrow(),
1124            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1125        );
1126
1127        self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
1128        users_user_id_tags_tag_delete(&self.create_connection_config(), &user_id.to_string(), tag)
1129            .map_err(|error| {
1130                Error::Api(format!(
1131                    "Deleting tag for user failed: {}",
1132                    NetHsmApiError::from(error)
1133                ))
1134            })?;
1135        Ok(())
1136    }
1137
1138    /// [Gets all tags] of a user in the [`Operator`][`UserRole::Operator`] [role].
1139    ///
1140    /// This call requires using [`Credentials`] of a user in the
1141    /// [`Administrator`][`UserRole::Administrator`] [role].
1142    ///
1143    /// ## Namespaces
1144    ///
1145    /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
1146    ///   [namespace]) are only able to get tags of users in their own [namespace].
1147    /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
1148    ///   able to get tags of system-wide and all [namespace] users.
1149    ///
1150    /// # Errors
1151    ///
1152    /// Returns an [`Error::Api`] if getting the tags for the user fails:
1153    /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1154    /// * the user identified by `user_id` does not exist
1155    /// * the user identified by `user_id` is not in the [`Operator`][`UserRole::Operator`] [role]
1156    /// * the used [`Credentials`] are not correct
1157    /// * the used [`Credentials`] are not that of a user in the
1158    ///   [`Administrator`][`UserRole::Administrator`] [role]
1159    /// * the caller does not have access to the target user's [namespace]
1160    ///
1161    /// # Examples
1162    ///
1163    /// ```no_run
1164    /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1165    ///
1166    /// # fn main() -> testresult::TestResult {
1167    /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1168    /// let nethsm = NetHsm::new(
1169    ///     Connection::new(
1170    ///         "https://example.org/api/v1".try_into()?,
1171    ///         ConnectionSecurity::Unsafe,
1172    ///     ),
1173    ///     Some(Credentials::new(
1174    ///         "admin".parse()?,
1175    ///         Some(Passphrase::new("passphrase".to_string())),
1176    ///     )),
1177    ///     None,
1178    ///     None,
1179    /// )?;
1180    /// // add a user in the Administrator role for a namespace (N-Administrator)
1181    /// nethsm.add_user(
1182    ///     "Namespace1 Admin".to_string(),
1183    ///     UserRole::Administrator,
1184    ///     Passphrase::new("namespce1-admin-passphrase".to_string()),
1185    ///     Some("namespace1~admin1".parse()?),
1186    /// )?;
1187    /// // add the accompanying namespace
1188    /// nethsm.add_namespace(&"namespace1".parse()?)?;
1189    /// // add a system-wide user in the Operator role
1190    /// nethsm.add_user(
1191    ///     "Operator One".to_string(),
1192    ///     UserRole::Operator,
1193    ///     Passphrase::new("operator1-passphrase".to_string()),
1194    ///     Some("user1".parse()?),
1195    /// )?;
1196    ///
1197    /// // R-Administrators can access tags of all users
1198    /// assert!(nethsm.get_user_tags(&"user1".parse()?)?.is_empty());
1199    /// // add a tag for the user
1200    /// nethsm.add_user_tag(&"user1".parse()?, "tag1")?;
1201    /// assert_eq!(nethsm.get_user_tags(&"user1".parse()?)?.len(), 1);
1202    ///
1203    /// // N-Administrators can not access tags of system-wide users
1204    /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1205    /// assert!(nethsm.get_user_tags(&"user1".parse()?).is_err());
1206    /// # Ok(())
1207    /// # }
1208    /// ```
1209    /// [Gets all tags]: https://docs.nitrokey.com/nethsm/administration#tags-for-users
1210    /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
1211    /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1212    /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1213    pub fn get_user_tags(&self, user_id: &UserId) -> Result<Vec<String>, Error> {
1214        debug!(
1215            "Get the tags of the user \"{user_id}\" on the NetHSM at {} using {}",
1216            self.url.borrow(),
1217            user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1218        );
1219
1220        self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
1221        Ok(
1222            users_user_id_tags_get(&self.create_connection_config(), &user_id.to_string())
1223                .map_err(|error| {
1224                    Error::Api(format!(
1225                        "Getting tags of user failed: {}",
1226                        NetHsmApiError::from(error)
1227                    ))
1228                })?
1229                .entity,
1230        )
1231    }
1232}