nethsm/base/impl_system.rs
1//! [`NetHsm`] implementation for system functionality.
2
3use std::net::Ipv4Addr;
4
5use base64ct::{Base64, Encoding};
6use chrono::{DateTime, Utc};
7use log::debug;
8use nethsm_sdk_rs::{
9 apis::default_api::{
10 config_backup_passphrase_put,
11 config_logging_get,
12 config_logging_put,
13 config_network_get,
14 config_network_put,
15 config_time_get,
16 config_time_put,
17 config_tls_cert_pem_get,
18 config_tls_cert_pem_put,
19 config_tls_csr_pem_post,
20 config_tls_generate_post,
21 config_tls_public_pem_get,
22 config_unattended_boot_get,
23 config_unattended_boot_put,
24 config_unlock_passphrase_put,
25 lock_post,
26 metrics_get,
27 provision_post,
28 random_post,
29 system_backup_post,
30 system_cancel_update_post,
31 system_commit_update_post,
32 system_factory_reset_post,
33 system_info_get,
34 system_reboot_post,
35 system_restore_post,
36 system_shutdown_post,
37 system_update_post,
38 unlock_post,
39 },
40 models::{
41 BackupPassphraseConfig,
42 DistinguishedName,
43 LoggingConfig,
44 NetworkConfig,
45 ProvisionRequestData,
46 RandomRequestData,
47 SystemInfo,
48 SystemUpdateData,
49 TimeConfig,
50 TlsKeyGenerateRequestData,
51 UnlockPassphraseConfig,
52 UnlockRequestData,
53 },
54};
55use serde_json::Value;
56
57use crate::{
58 BootMode,
59 Error,
60 LogLevel,
61 NetHsm,
62 Passphrase,
63 TlsKeyType,
64 base::utils::user_or_no_user_string,
65 nethsm_sdk::NetHsmApiError,
66 tls_key_type_matches_length,
67 user::NamespaceSupport,
68};
69#[cfg(doc)]
70use crate::{Credentials, SystemState, UserRole};
71
72impl NetHsm {
73 /// Provisions a NetHSM.
74 ///
75 /// [Provisioning] is the initial setup step for a NetHSM.
76 /// It sets the `unlock_passphrase`, which is used to [`unlock`][`NetHsm::unlock`] a device in
77 /// [`Locked`][`SystemState::Locked`] [state], the initial `admin_passphrase` for the
78 /// default [`Administrator`][`UserRole::Administrator`] account ("admin") and the
79 /// `system_time`. The unlock passphrase can later on be changed using
80 /// [`set_unlock_passphrase`][`NetHsm::set_unlock_passphrase`] and the admin passphrase using
81 /// [`set_user_passphrase`][`NetHsm::set_user_passphrase`].
82 ///
83 /// For this call no [`Credentials`] are required and if any are configured, they are ignored.
84 ///
85 /// # Errors
86 ///
87 /// Returns an [`Error::Api`] if provisioning fails:
88 /// * the NetHSM is not in [`Unprovisioned`][`SystemState::Unprovisioned`] [state]
89 /// * the provided data is malformed
90 ///
91 /// # Examples
92 ///
93 /// ```no_run
94 /// use chrono::Utc;
95 /// use nethsm::{Connection, ConnectionSecurity, NetHsm, Passphrase};
96 ///
97 /// # fn main() -> testresult::TestResult {
98 /// // no initial credentials are required
99 /// let nethsm = NetHsm::new(
100 /// Connection::new(
101 /// "https://example.org/api/v1".try_into()?,
102 /// ConnectionSecurity::Unsafe,
103 /// ),
104 /// None,
105 /// None,
106 /// None,
107 /// )?;
108 ///
109 /// // provision the NetHSM
110 /// nethsm.provision(
111 /// Passphrase::new("unlock-the-device".to_string()),
112 /// Passphrase::new("admin-passphrase".to_string()),
113 /// Utc::now(),
114 /// )?;
115 /// # Ok(())
116 /// # }
117 /// ```
118 /// [Provisioning]: https://docs.nitrokey.com/nethsm/getting-started#provisioning
119 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
120 pub fn provision(
121 &self,
122 unlock_passphrase: Passphrase,
123 admin_passphrase: Passphrase,
124 system_time: DateTime<Utc>,
125 ) -> Result<(), Error> {
126 debug!("Provision the NetHSM at {}", self.url.borrow());
127
128 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
129 provision_post(
130 &self.create_connection_config(),
131 ProvisionRequestData::new(
132 unlock_passphrase.expose_owned(),
133 admin_passphrase.expose_owned(),
134 system_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
135 ),
136 )
137 .map_err(|error| {
138 Error::Api(format!(
139 "Provisioning failed: {}",
140 NetHsmApiError::from(error)
141 ))
142 })?;
143 Ok(())
144 }
145
146 /// Returns metrics for the NetHSM.
147 ///
148 /// Returns a [`Value`][`serde_json::Value`] which provides [metrics] for the NetHSM.
149 ///
150 /// This call requires using [`Credentials`] of a user in the [`Metrics`][`UserRole::Metrics`]
151 /// [role].
152 ///
153 /// # Errors
154 ///
155 /// Returns an [`Error::Api`] if the NetHSM [metrics] can not be retrieved:
156 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
157 /// * the used [`Credentials`] are not correct
158 /// * the used [`Credentials`] are not that of a user in the [`Metrics`][`UserRole::Metrics`]
159 /// [role]
160 ///
161 /// # Examples
162 ///
163 /// ```no_run
164 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
165 ///
166 /// # fn main() -> testresult::TestResult {
167 /// // create a connection with a system-wide user in the Metrics role
168 /// let nethsm = NetHsm::new(
169 /// Connection::new(
170 /// "https://example.org/api/v1".try_into()?,
171 /// ConnectionSecurity::Unsafe,
172 /// ),
173 /// Some(Credentials::new(
174 /// "metrics".parse()?,
175 /// Some(Passphrase::new("metrics-passphrase".to_string())),
176 /// )),
177 /// None,
178 /// None,
179 /// )?;
180 ///
181 /// // retrieve the metrics
182 /// println!("{:?}", nethsm.metrics()?);
183 /// # Ok(())
184 /// # }
185 /// ```
186 /// [metrics]: https://docs.nitrokey.com/nethsm/administration#metrics
187 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
188 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
189 pub fn metrics(&self) -> Result<Value, Error> {
190 debug!(
191 "Retrieve metrics of the NetHSM at {} using {}",
192 self.url.borrow(),
193 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
194 );
195
196 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
197 let metrics = metrics_get(&self.create_connection_config()).map_err(|error| {
198 Error::Api(format!(
199 "Retrieving metrics failed: {}",
200 NetHsmApiError::from(error)
201 ))
202 })?;
203 Ok(metrics.entity)
204 }
205
206 /// Sets the [unlock passphrase].
207 ///
208 /// Changes the [unlock passphrase] from `current_passphrase` to `new_passphrase`.
209 ///
210 /// This call requires using [`Credentials`] of a system-wide user in the
211 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
212 ///
213 /// # Errors
214 ///
215 /// Returns an [`Error::Api`] if the [unlock passphrase] can not be changed:
216 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
217 /// * the provided `current_passphrase` is not correct
218 /// * the used [`Credentials`] are not correct
219 /// * the used [`Credentials`] are not that of a system-wide user in the
220 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
221 ///
222 /// # Examples
223 ///
224 /// ```no_run
225 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
226 ///
227 /// # fn main() -> testresult::TestResult {
228 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
229 /// let nethsm = NetHsm::new(
230 /// Connection::new(
231 /// "https://example.org/api/v1".try_into()?,
232 /// ConnectionSecurity::Unsafe,
233 /// ),
234 /// Some(Credentials::new(
235 /// "admin".parse()?,
236 /// Some(Passphrase::new("passphrase".to_string())),
237 /// )),
238 /// None,
239 /// None,
240 /// )?;
241 /// // add a user in the Administrator role for a namespace (N-Administrator)
242 /// nethsm.add_user(
243 /// "Namespace1 Admin".to_string(),
244 /// UserRole::Administrator,
245 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
246 /// Some("namespace1~admin1".parse()?),
247 /// )?;
248 /// // create accompanying namespace
249 /// nethsm.add_namespace(&"namespace1".parse()?)?;
250 ///
251 /// // R-Administrators can set the unlock passphrase
252 /// nethsm.set_unlock_passphrase(
253 /// Passphrase::new("current-unlock-passphrase".to_string()),
254 /// Passphrase::new("new-unlock-passphrase".to_string()),
255 /// )?;
256 ///
257 /// // N-Administrators can not set the unlock passphrase
258 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
259 /// assert!(
260 /// nethsm
261 /// .set_unlock_passphrase(
262 /// Passphrase::new("current-unlock-passphrase".to_string()),
263 /// Passphrase::new("new-unlock-passphrase".to_string()),
264 /// )
265 /// .is_err()
266 /// );
267 /// # Ok(())
268 /// # }
269 /// ```
270 /// [unlock passphrase]: https://docs.nitrokey.com/nethsm/administration#unlock-passphrase
271 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
272 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
273 pub fn set_unlock_passphrase(
274 &self,
275 current_passphrase: Passphrase,
276 new_passphrase: Passphrase,
277 ) -> Result<(), Error> {
278 debug!(
279 "Set unlock passphrase for the NetHSM at {} using {}",
280 self.url.borrow(),
281 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
282 );
283
284 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
285 config_unlock_passphrase_put(
286 &self.create_connection_config(),
287 UnlockPassphraseConfig::new(
288 new_passphrase.expose_owned(),
289 current_passphrase.expose_owned(),
290 ),
291 )
292 .map_err(|error| {
293 Error::Api(format!(
294 "Changing unlock passphrase failed: {}",
295 NetHsmApiError::from(error)
296 ))
297 })?;
298 Ok(())
299 }
300
301 /// Returns the [boot mode].
302 ///
303 /// Returns a variant of [`BootMode`] which represents the NetHSM's [boot mode].
304 ///
305 /// This call requires using [`Credentials`] of a system-wide user in the
306 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
307 ///
308 /// # Errors
309 ///
310 /// Returns an [`Error::Api`] if the boot mode can not be retrieved:
311 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
312 /// * the used [`Credentials`] are not correct
313 /// * the used [`Credentials`] are not that of a system-wide user in the
314 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
315 ///
316 /// # Examples
317 ///
318 /// ```no_run
319 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
320 ///
321 /// # fn main() -> testresult::TestResult {
322 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
323 /// let nethsm = NetHsm::new(
324 /// Connection::new(
325 /// "https://example.org/api/v1".try_into()?,
326 /// ConnectionSecurity::Unsafe,
327 /// ),
328 /// Some(Credentials::new(
329 /// "admin".parse()?,
330 /// Some(Passphrase::new("passphrase".to_string())),
331 /// )),
332 /// None,
333 /// None,
334 /// )?;
335 /// // add a user in the Administrator role for a namespace (N-Administrator)
336 /// nethsm.add_user(
337 /// "Namespace1 Admin".to_string(),
338 /// UserRole::Administrator,
339 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
340 /// Some("namespace1~admin1".parse()?),
341 /// )?;
342 /// // create accompanying namespace
343 /// nethsm.add_namespace(&"namespace1".parse()?)?;
344 ///
345 /// // R-Administrators can retrieve the boot mode
346 /// println!("{:?}", nethsm.get_boot_mode()?);
347 ///
348 /// // N-Administrators can not retrieve the boot mode
349 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
350 /// assert!(nethsm.get_boot_mode().is_err());
351 /// # Ok(())
352 /// # }
353 /// ```
354 /// [boot mode]: https://docs.nitrokey.com/nethsm/administration#boot-mode
355 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
356 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
357 pub fn get_boot_mode(&self) -> Result<BootMode, Error> {
358 debug!(
359 "Get the boot mode of the NetHSM at {} using {}",
360 self.url.borrow(),
361 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
362 );
363
364 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
365 Ok(BootMode::from(
366 config_unattended_boot_get(&self.create_connection_config())
367 .map_err(|error| {
368 Error::Api(format!(
369 "Retrieving boot mode failed: {}",
370 NetHsmApiError::from(error)
371 ))
372 })?
373 .entity,
374 ))
375 }
376
377 /// Sets the [boot mode].
378 ///
379 /// Sets the NetHSM's [boot mode] based on a [`BootMode`] variant.
380 ///
381 /// This call requires using [`Credentials`] of a system-wide user in the
382 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
383 ///
384 /// # Errors
385 ///
386 /// Returns an [`Error::Api`] if the boot mode can not be set:
387 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
388 /// * the used [`Credentials`] are not correct
389 /// * the used [`Credentials`] are not that of a system-wide user in the
390 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
391 ///
392 /// # Examples
393 ///
394 /// ```no_run
395 /// use nethsm::{
396 /// BootMode,
397 /// Connection,
398 /// ConnectionSecurity,
399 /// Credentials,
400 /// NetHsm,
401 /// Passphrase,
402 /// UserRole,
403 /// };
404 ///
405 /// # fn main() -> testresult::TestResult {
406 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
407 /// let nethsm = NetHsm::new(
408 /// Connection::new(
409 /// "https://example.org/api/v1".try_into()?,
410 /// ConnectionSecurity::Unsafe,
411 /// ),
412 /// Some(Credentials::new(
413 /// "admin".parse()?,
414 /// Some(Passphrase::new("passphrase".to_string())),
415 /// )),
416 /// None,
417 /// None,
418 /// )?;
419 /// // add a user in the Administrator role for a namespace (N-Administrator)
420 /// nethsm.add_user(
421 /// "Namespace1 Admin".to_string(),
422 /// UserRole::Administrator,
423 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
424 /// Some("namespace1~admin1".parse()?),
425 /// )?;
426 /// // create accompanying namespace
427 /// nethsm.add_namespace(&"namespace1".parse()?)?;
428 ///
429 /// // R-Administrators can set the boot mode
430 /// // set the boot mode to unattended
431 /// nethsm.set_boot_mode(BootMode::Unattended)?;
432 /// // set the boot mode to attended
433 /// nethsm.set_boot_mode(BootMode::Attended)?;
434 ///
435 /// // N-Administrators can not set the boot mode
436 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
437 /// assert!(nethsm.set_boot_mode(BootMode::Attended).is_err());
438 /// # Ok(())
439 /// # }
440 /// ```
441 /// [boot mode]: https://docs.nitrokey.com/nethsm/administration#boot-mode
442 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
443 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
444 pub fn set_boot_mode(&self, boot_mode: BootMode) -> Result<(), Error> {
445 debug!(
446 "Set the boot mode for the NetHSM at {} to {boot_mode} using {}",
447 self.url.borrow(),
448 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
449 );
450
451 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
452 config_unattended_boot_put(&self.create_connection_config(), boot_mode.into()).map_err(
453 |error| {
454 Error::Api(format!(
455 "Setting boot mode failed: {}",
456 NetHsmApiError::from(error)
457 ))
458 },
459 )?;
460 Ok(())
461 }
462
463 /// Returns the TLS public key of the API.
464 ///
465 /// Returns the NetHSM's public key part of its [TLS certificate] which is used for
466 /// communication with the API.
467 ///
468 /// This call requires using [`Credentials`] of a system-wide user in the
469 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
470 ///
471 /// # Errors
472 ///
473 /// Returns an [`Error::Api`] if the NetHSM's TLS public key can not be retrieved:
474 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
475 /// * the used [`Credentials`] are not correct
476 /// * the used [`Credentials`] are not that of a system-wide user in the
477 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
478 ///
479 /// # Examples
480 ///
481 /// ```no_run
482 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
483 ///
484 /// # fn main() -> testresult::TestResult {
485 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
486 /// let nethsm = NetHsm::new(
487 /// Connection::new(
488 /// "https://example.org/api/v1".try_into()?,
489 /// ConnectionSecurity::Unsafe,
490 /// ),
491 /// Some(Credentials::new(
492 /// "admin".parse()?,
493 /// Some(Passphrase::new("passphrase".to_string())),
494 /// )),
495 /// None,
496 /// None,
497 /// )?;
498 /// // add a user in the Administrator role for a namespace (N-Administrator)
499 /// nethsm.add_user(
500 /// "Namespace1 Admin".to_string(),
501 /// UserRole::Administrator,
502 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
503 /// Some("namespace1~admin1".parse()?),
504 /// )?;
505 /// // create accompanying namespace
506 /// nethsm.add_namespace(&"namespace1".parse()?)?;
507 ///
508 /// // R-Administrators can get the TLS public key
509 /// println!("{}", nethsm.get_tls_public_key()?);
510 ///
511 /// // N-Administrators can not get the TLS public key
512 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
513 /// assert!(nethsm.get_tls_public_key().is_err());
514 /// # Ok(())
515 /// # }
516 /// ```
517 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
518 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
519 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
520 pub fn get_tls_public_key(&self) -> Result<String, Error> {
521 debug!(
522 "Retrieve the TLS public key for the NetHSM at {} using {}",
523 self.url.borrow(),
524 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
525 );
526
527 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
528 Ok(config_tls_public_pem_get(&self.create_connection_config())
529 .map_err(|error| {
530 Error::Api(format!(
531 "Retrieving API TLS public key failed: {}",
532 NetHsmApiError::from(error)
533 ))
534 })?
535 .entity)
536 }
537
538 /// Returns the TLS certificate of the API.
539 ///
540 /// Returns the NetHSM's [TLS certificate] which is used for communication with the API.
541 ///
542 /// This call requires using [`Credentials`] of a system-wide user in the
543 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
544 ///
545 /// # Errors
546 ///
547 /// Returns an [`Error::Api`] if the NetHSM's TLS certificate can not be retrieved:
548 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
549 /// * the used [`Credentials`] are not correct
550 /// * the used [`Credentials`] are not that of a system-wide user in the
551 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
552 ///
553 /// # Examples
554 ///
555 /// ```no_run
556 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
557 ///
558 /// # fn main() -> testresult::TestResult {
559 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
560 /// let nethsm = NetHsm::new(
561 /// Connection::new(
562 /// "https://example.org/api/v1".try_into()?,
563 /// ConnectionSecurity::Unsafe,
564 /// ),
565 /// Some(Credentials::new(
566 /// "admin".parse()?,
567 /// Some(Passphrase::new("passphrase".to_string())),
568 /// )),
569 /// None,
570 /// None,
571 /// )?;
572 /// // add a user in the Administrator role for a namespace (N-Administrator)
573 /// nethsm.add_user(
574 /// "Namespace1 Admin".to_string(),
575 /// UserRole::Administrator,
576 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
577 /// Some("namespace1~admin1".parse()?),
578 /// )?;
579 /// // create accompanying namespace
580 /// nethsm.add_namespace(&"namespace1".parse()?)?;
581 ///
582 /// // R-Administrators can get the TLS certificate
583 /// println!("{}", nethsm.get_tls_cert()?);
584 ///
585 /// // N-Administrators can not get the TLS certificate
586 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
587 /// assert!(nethsm.get_tls_cert().is_err());
588 /// # Ok(())
589 /// # }
590 /// ```
591 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
592 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
593 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
594 pub fn get_tls_cert(&self) -> Result<String, Error> {
595 debug!(
596 "Retrieve the TLS certificate for the NetHSM at {} using {}",
597 self.url.borrow(),
598 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
599 );
600
601 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
602 Ok(config_tls_cert_pem_get(&self.create_connection_config())
603 .map_err(|error| {
604 Error::Api(format!(
605 "Retrieving API TLS certificate failed: {}",
606 NetHsmApiError::from(error)
607 ))
608 })?
609 .entity)
610 }
611
612 /// Returns a Certificate Signing Request ([CSR]) for the API's [TLS certificate].
613 ///
614 /// Based on [`DistinguishedName`] data returns a [CSR] in [PKCS#10] format for the NetHSM's
615 /// [TLS certificate].
616 ///
617 /// This call requires using [`Credentials`] of a system-wide user in the
618 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
619 ///
620 /// # Errors
621 ///
622 /// Returns an [`Error::Api`] if the [CSR] can not be retrieved:
623 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
624 /// * the used [`Credentials`] are not correct
625 /// * the used [`Credentials`] are not that of a system-wide user in the
626 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
627 ///
628 /// # Examples
629 ///
630 /// ```no_run
631 /// use nethsm::{
632 /// Connection,
633 /// ConnectionSecurity,
634 /// Credentials,
635 /// DistinguishedName,
636 /// NetHsm,
637 /// Passphrase,
638 /// UserRole,
639 /// };
640 ///
641 /// # fn main() -> testresult::TestResult {
642 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
643 /// let nethsm = NetHsm::new(
644 /// Connection::new(
645 /// "https://example.org/api/v1".try_into()?,
646 /// ConnectionSecurity::Unsafe,
647 /// ),
648 /// Some(Credentials::new(
649 /// "admin".parse()?,
650 /// Some(Passphrase::new("passphrase".to_string())),
651 /// )),
652 /// None,
653 /// None,
654 /// )?;
655 /// // add a user in the Administrator role for a namespace (N-Administrator)
656 /// nethsm.add_user(
657 /// "Namespace1 Admin".to_string(),
658 /// UserRole::Administrator,
659 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
660 /// Some("namespace1~admin1".parse()?),
661 /// )?;
662 /// // create accompanying namespace
663 /// nethsm.add_namespace(&"namespace1".parse()?)?;
664 ///
665 /// // R-Administrators can get a CSR for the TLS certificate
666 /// println!(
667 /// "{}",
668 /// nethsm.get_tls_csr(DistinguishedName {
669 /// country_name: Some("DE".to_string()),
670 /// state_or_province_name: Some("Berlin".to_string()),
671 /// locality_name: Some("Berlin".to_string()),
672 /// organization_name: Some("Foobar Inc".to_string()),
673 /// organizational_unit_name: Some("Department of Foo".to_string()),
674 /// common_name: "Foobar Inc".to_string(),
675 /// email_address: Some("foobar@mcfooface.com".to_string()),
676 /// })?
677 /// );
678 ///
679 /// // N-Administrators can not get a CSR for the TLS certificate
680 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
681 /// assert!(
682 /// nethsm
683 /// .get_tls_csr(DistinguishedName {
684 /// country_name: Some("DE".to_string()),
685 /// state_or_province_name: Some("Berlin".to_string()),
686 /// locality_name: Some("Berlin".to_string()),
687 /// organization_name: Some("Foobar Inc".to_string()),
688 /// organizational_unit_name: Some("Department of Foo".to_string()),
689 /// common_name: "Foobar Inc".to_string(),
690 /// email_address: Some("foobar@mcfooface.com".to_string()),
691 /// })
692 /// .is_err()
693 /// );
694 /// # Ok(())
695 /// # }
696 /// ```
697 /// [CSR]: https://en.wikipedia.org/wiki/Certificate_signing_request
698 /// [PKCS#10]: https://en.wikipedia.org/wiki/Certificate_signing_request#Structure_of_a_PKCS_#10_CSR
699 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
700 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
701 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
702 pub fn get_tls_csr(&self, distinguished_name: DistinguishedName) -> Result<String, Error> {
703 debug!(
704 "Retrieve a Certificate Signing Request (for {}) for the TLS certificate of the NetHSM at {} using {}",
705 distinguished_name.common_name,
706 self.url.borrow(),
707 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
708 );
709
710 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
711 Ok(
712 config_tls_csr_pem_post(&self.create_connection_config(), distinguished_name)
713 .map_err(|error| {
714 Error::Api(format!(
715 "Retrieving CSR for TLS certificate failed: {}",
716 NetHsmApiError::from(error),
717 ))
718 })?
719 .entity,
720 )
721 }
722
723 /// Generates a new [TLS certificate] for the API.
724 ///
725 /// Generates a new [TLS certificate] (used for communication with the API) based on
726 /// `tls_key_type` and `length`.
727 ///
728 /// This call requires using [`Credentials`] of a system-wide user in the
729 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
730 ///
731 /// # Errors
732 ///
733 /// Returns an [`Error::Api`] if the new [TLS certificate] can not be generated:
734 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
735 /// * the `tls_key_type` and `length` combination is not valid
736 /// * the used [`Credentials`] are not correct
737 /// * the used [`Credentials`] are not that of a system-wide user in the
738 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
739 ///
740 /// # Examples
741 ///
742 /// ```no_run
743 /// use nethsm::{
744 /// Connection,
745 /// ConnectionSecurity,
746 /// Credentials,
747 /// NetHsm,
748 /// Passphrase,
749 /// TlsKeyType,
750 /// UserRole,
751 /// };
752 ///
753 /// # fn main() -> testresult::TestResult {
754 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
755 /// let nethsm = NetHsm::new(
756 /// Connection::new(
757 /// "https://example.org/api/v1".try_into()?,
758 /// ConnectionSecurity::Unsafe,
759 /// ),
760 /// Some(Credentials::new(
761 /// "admin".parse()?,
762 /// Some(Passphrase::new("passphrase".to_string())),
763 /// )),
764 /// None,
765 /// None,
766 /// )?;
767 /// // add a user in the Administrator role for a namespace (N-Administrator)
768 /// nethsm.add_user(
769 /// "Namespace1 Admin".to_string(),
770 /// UserRole::Administrator,
771 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
772 /// Some("namespace1~admin1".parse()?),
773 /// )?;
774 /// // create accompanying namespace
775 /// nethsm.add_namespace(&"namespace1".parse()?)?;
776 ///
777 /// // R-Administrators can generate a new TLS certificate
778 /// nethsm.generate_tls_cert(TlsKeyType::Rsa, Some(4096))?;
779 ///
780 /// // N-Administrators can not generate a new TLS certificate
781 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
782 /// assert!(
783 /// nethsm
784 /// .generate_tls_cert(TlsKeyType::Rsa, Some(4096))
785 /// .is_err()
786 /// );
787 /// # Ok(())
788 /// # }
789 /// ```
790 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
791 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
792 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
793 pub fn generate_tls_cert(
794 &self,
795 tls_key_type: TlsKeyType,
796 length: Option<u32>,
797 ) -> Result<(), Error> {
798 debug!(
799 "Generate a TLS certificate ({tls_key_type}{}) on the NetHSM at {} using {}",
800 if let Some(length) = length {
801 format!(" {length} bit long")
802 } else {
803 "{}".to_string()
804 },
805 self.url.borrow(),
806 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
807 );
808
809 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
810 // ensure the tls_key_type - length combination is valid
811 tls_key_type_matches_length(tls_key_type, length)?;
812 config_tls_generate_post(
813 &self.create_connection_config(),
814 TlsKeyGenerateRequestData {
815 r#type: tls_key_type.into(),
816 length: length.map(|length| length as i32),
817 },
818 )
819 .map_err(|error| {
820 Error::Api(format!(
821 "Generating API TLS certificate failed: {}",
822 NetHsmApiError::from(error)
823 ))
824 })?;
825 Ok(())
826 }
827
828 /// Sets a new [TLS certificate] for the API.
829 ///
830 /// Accepts a Base64 encoded [DER] certificate provided using `certificate` which is added as
831 /// new [TLS certificate] for communication with the API.
832 ///
833 /// This call requires using [`Credentials`] of a system-wide user in the
834 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
835 ///
836 /// # Errors
837 ///
838 /// Returns an [`Error::Api`] if setting a new TLS certificate fails:
839 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
840 /// * the provided `certificate` is not valid
841 /// * the used [`Credentials`] are not correct
842 /// * the used [`Credentials`] are not that of a system-wide user in the
843 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
844 ///
845 /// # Examples
846 ///
847 /// ```no_run
848 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
849 ///
850 /// # fn main() -> testresult::TestResult {
851 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
852 /// let nethsm = NetHsm::new(
853 /// Connection::new(
854 /// "https://example.org/api/v1".try_into()?,
855 /// ConnectionSecurity::Unsafe,
856 /// ),
857 /// Some(Credentials::new(
858 /// "admin".parse()?,
859 /// Some(Passphrase::new("passphrase".to_string())),
860 /// )),
861 /// None,
862 /// None,
863 /// )?;
864 /// // add a user in the Administrator role for a namespace (N-Administrator)
865 /// nethsm.add_user(
866 /// "Namespace1 Admin".to_string(),
867 /// UserRole::Administrator,
868 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
869 /// Some("namespace1~admin1".parse()?),
870 /// )?;
871 /// // create accompanying namespace
872 /// nethsm.add_namespace(&"namespace1".parse()?)?;
873 ///
874 /// let cert = r#"-----BEGIN CERTIFICATE-----
875 /// MIIBHjCBxKADAgECAghDngCv6xWIXDAKBggqhkjOPQQDAjAUMRIwEAYDVQQDDAlr
876 /// ZXlmZW5kZXIwIBcNNzAwMTAxMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMBQxEjAQ
877 /// BgNVBAMMCWtleWZlbmRlcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJsHIrsZ
878 /// 6fJzrk12GK7nW6bGyTIIZiQUq0uaKbn21dgPiDCO5+iYVXAqnWu4IMVZQnkFJmte
879 /// PRUUuM3119f8ffkwCgYIKoZIzj0EAwIDSQAwRgIhALH4fDYJ21tRecXp9IipBlil
880 /// p+hJCj77zBvFmGYy/UnPAiEA8csj7U6BfzvK4EiQyUZa7/as+nXwj3XHU/i8LyLm
881 /// Chw=
882 /// -----END CERTIFICATE-----"#;
883 ///
884 /// // R-Administrators can set a new TLS certificate
885 /// nethsm.set_tls_cert(cert)?;
886 ///
887 /// // N-Administrators can not set a new TLS certificate
888 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
889 /// assert!(nethsm.set_tls_cert(cert).is_err());
890 /// # Ok(())
891 /// # }
892 /// ```
893 /// [DER]: https://en.wikipedia.org/wiki/X.690#DER_encoding
894 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
895 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
896 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
897 pub fn set_tls_cert(&self, certificate: &str) -> Result<(), Error> {
898 debug!(
899 "Set a new TLS certificate for the NetHSM at {} using {}",
900 self.url.borrow(),
901 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
902 );
903
904 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
905 config_tls_cert_pem_put(&self.create_connection_config(), certificate).map_err(
906 |error| {
907 Error::Api(format!(
908 "Setting API TLS certificate failed: {}",
909 NetHsmApiError::from(error)
910 ))
911 },
912 )?;
913 Ok(())
914 }
915
916 /// Gets the [network configuration].
917 ///
918 /// Retrieves the [network configuration] of the NetHSM as [`NetworkConfig`].
919 ///
920 /// This call requires using [`Credentials`] of a system-wide user in the
921 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
922 ///
923 /// # Errors
924 ///
925 /// Returns an [`Error::Api`] if retrieving network configuration fails:
926 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
927 /// * the used [`Credentials`] are not correct
928 /// * the used [`Credentials`] are not that of a system-wide user in the
929 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
930 ///
931 /// # Examples
932 ///
933 /// ```no_run
934 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
935 ///
936 /// # fn main() -> testresult::TestResult {
937 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
938 /// let nethsm = NetHsm::new(
939 /// Connection::new(
940 /// "https://example.org/api/v1".try_into()?,
941 /// ConnectionSecurity::Unsafe,
942 /// ),
943 /// Some(Credentials::new(
944 /// "admin".parse()?,
945 /// Some(Passphrase::new("passphrase".to_string())),
946 /// )),
947 /// None,
948 /// None,
949 /// )?;
950 /// // add a user in the Administrator role for a namespace (N-Administrator)
951 /// nethsm.add_user(
952 /// "Namespace1 Admin".to_string(),
953 /// UserRole::Administrator,
954 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
955 /// Some("namespace1~admin1".parse()?),
956 /// )?;
957 /// // create accompanying namespace
958 /// nethsm.add_namespace(&"namespace1".parse()?)?;
959 ///
960 /// // R-Administrators can get the network configuration
961 /// println!("{:?}", nethsm.get_network()?);
962 ///
963 /// // N-Administrators can not get the network configuration
964 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
965 /// assert!(nethsm.get_network().is_err());
966 /// # Ok(())
967 /// # }
968 /// ```
969 /// [network configuration]: https://docs.nitrokey.com/nethsm/administration#network
970 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
971 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
972 pub fn get_network(&self) -> Result<NetworkConfig, Error> {
973 debug!(
974 "Get network configuration for the NetHSM at {} using {}",
975 self.url.borrow(),
976 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
977 );
978
979 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
980 Ok(config_network_get(&self.create_connection_config())
981 .map_err(|error| {
982 Error::Api(format!(
983 "Getting network config failed: {}",
984 NetHsmApiError::from(error)
985 ))
986 })?
987 .entity)
988 }
989
990 /// Sets the [network configuration].
991 ///
992 /// Sets the [network configuration] of the NetHSM on the basis of a [`NetworkConfig`].
993 ///
994 /// This call requires using [`Credentials`] of a system-wide user in the
995 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
996 ///
997 /// # Errors
998 ///
999 /// Returns an [`Error::Api`] if setting the network configuration fails:
1000 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1001 /// * the provided `network_config` is not valid
1002 /// * the used [`Credentials`] are not correct
1003 /// * the used [`Credentials`] are not that of a system-wide user in the
1004 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1005 ///
1006 /// # Examples
1007 ///
1008 /// ```no_run
1009 /// use nethsm::{
1010 /// Connection,
1011 /// ConnectionSecurity,
1012 /// Credentials,
1013 /// NetHsm,
1014 /// NetworkConfig,
1015 /// Passphrase,
1016 /// UserRole,
1017 /// };
1018 ///
1019 /// # fn main() -> testresult::TestResult {
1020 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1021 /// let nethsm = NetHsm::new(
1022 /// Connection::new(
1023 /// "https://example.org/api/v1".try_into()?,
1024 /// ConnectionSecurity::Unsafe,
1025 /// ),
1026 /// Some(Credentials::new(
1027 /// "admin".parse()?,
1028 /// Some(Passphrase::new("passphrase".to_string())),
1029 /// )),
1030 /// None,
1031 /// None,
1032 /// )?;
1033 /// // add a user in the Administrator role for a namespace (N-Administrator)
1034 /// nethsm.add_user(
1035 /// "Namespace1 Admin".to_string(),
1036 /// UserRole::Administrator,
1037 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1038 /// Some("namespace1~admin1".parse()?),
1039 /// )?;
1040 /// // create accompanying namespace
1041 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1042 ///
1043 /// let network_config = NetworkConfig::new(
1044 /// "192.168.1.1".to_string(),
1045 /// "255.255.255.0".to_string(),
1046 /// "0.0.0.0".to_string(),
1047 /// );
1048 ///
1049 /// // R-Administrators can set the network configuration
1050 /// nethsm.set_network(network_config.clone())?;
1051 ///
1052 /// // N-Administrators can not set the network configuration
1053 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1054 /// assert!(nethsm.set_network(network_config).is_err());
1055 /// # Ok(())
1056 /// # }
1057 /// ```
1058 /// [network configuration]: https://docs.nitrokey.com/nethsm/administration#network
1059 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1060 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1061 pub fn set_network(&self, network_config: NetworkConfig) -> Result<(), Error> {
1062 debug!(
1063 "Set a new network configuration (IP: {}, Netmask: {}, Gateway: {}) for the NetHSM at {} using {}",
1064 network_config.ip_address,
1065 network_config.netmask,
1066 network_config.gateway,
1067 self.url.borrow(),
1068 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1069 );
1070
1071 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1072 config_network_put(&self.create_connection_config(), network_config).map_err(|error| {
1073 Error::Api(format!(
1074 "Setting network config failed: {}",
1075 NetHsmApiError::from(error)
1076 ))
1077 })?;
1078 Ok(())
1079 }
1080
1081 /// Gets the current [time].
1082 ///
1083 /// This call requires using [`Credentials`] of a system-wide user in the
1084 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1085 ///
1086 /// # Errors
1087 ///
1088 /// Returns an [`Error::Api`] if retrieving [time] fails:
1089 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1090 /// * the used [`Credentials`] are not correct
1091 /// * the used [`Credentials`] are not that of a system-wide user in the
1092 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1093 ///
1094 /// # Examples
1095 ///
1096 /// ```no_run
1097 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1098 ///
1099 /// # fn main() -> testresult::TestResult {
1100 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1101 /// let nethsm = NetHsm::new(
1102 /// Connection::new(
1103 /// "https://example.org/api/v1".try_into()?,
1104 /// ConnectionSecurity::Unsafe,
1105 /// ),
1106 /// Some(Credentials::new(
1107 /// "admin".parse()?,
1108 /// Some(Passphrase::new("passphrase".to_string())),
1109 /// )),
1110 /// None,
1111 /// None,
1112 /// )?;
1113 /// // add a user in the Administrator role for a namespace (N-Administrator)
1114 /// nethsm.add_user(
1115 /// "Namespace1 Admin".to_string(),
1116 /// UserRole::Administrator,
1117 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1118 /// Some("namespace1~admin1".parse()?),
1119 /// )?;
1120 /// // create accompanying namespace
1121 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1122 ///
1123 /// // R-Administrators can get the time
1124 /// println!("{:?}", nethsm.get_time()?);
1125 ///
1126 /// // N-Administrators can not get the time
1127 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1128 /// assert!(nethsm.get_time().is_err());
1129 /// # Ok(())
1130 /// # }
1131 /// ```
1132 /// [time]: https://docs.nitrokey.com/nethsm/administration#time
1133 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1134 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1135 pub fn get_time(&self) -> Result<String, Error> {
1136 debug!(
1137 "Retrieve the system time for the NetHSM at {} using {}",
1138 self.url.borrow(),
1139 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1140 );
1141
1142 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1143 Ok(config_time_get(&self.create_connection_config())
1144 .map_err(|error| {
1145 Error::Api(format!(
1146 "Getting NetHSM system time failed: {}",
1147 NetHsmApiError::from(error)
1148 ))
1149 })?
1150 .entity
1151 .time)
1152 }
1153
1154 /// Sets the current [time].
1155 ///
1156 /// This call requires using [`Credentials`] of a system-wide user in the
1157 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1158 ///
1159 /// # Errors
1160 ///
1161 /// Returns an [`Error::Api`] if setting [time] fails:
1162 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1163 /// * the provided `time` is not valid
1164 /// * the used [`Credentials`] are not correct
1165 /// * the used [`Credentials`] are not that of a system-wide user in the
1166 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1167 ///
1168 /// # Examples
1169 ///
1170 /// ```no_run
1171 /// use chrono::Utc;
1172 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1173 ///
1174 /// # fn main() -> testresult::TestResult {
1175 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1176 /// let nethsm = NetHsm::new(
1177 /// Connection::new(
1178 /// "https://example.org/api/v1".try_into()?,
1179 /// ConnectionSecurity::Unsafe,
1180 /// ),
1181 /// Some(Credentials::new(
1182 /// "admin".parse()?,
1183 /// Some(Passphrase::new("passphrase".to_string())),
1184 /// )),
1185 /// None,
1186 /// None,
1187 /// )?;
1188 /// // add a user in the Administrator role for a namespace (N-Administrator)
1189 /// nethsm.add_user(
1190 /// "Namespace1 Admin".to_string(),
1191 /// UserRole::Administrator,
1192 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1193 /// Some("namespace1~admin1".parse()?),
1194 /// )?;
1195 /// // create accompanying namespace
1196 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1197 ///
1198 /// // R-Administrators can set the time
1199 /// nethsm.set_time(Utc::now())?;
1200 ///
1201 /// // N-Administrators can not set the time
1202 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1203 /// assert!(nethsm.set_time(Utc::now()).is_err());
1204 /// # Ok(())
1205 /// # }
1206 /// ```
1207 /// [time]: https://docs.nitrokey.com/nethsm/administration#time
1208 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1209 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1210 pub fn set_time(&self, time: DateTime<Utc>) -> Result<(), Error> {
1211 debug!(
1212 "Set the system time to {time} for the NetHSM at {} using {}",
1213 self.url.borrow(),
1214 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1215 );
1216
1217 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1218 config_time_put(
1219 &self.create_connection_config(),
1220 TimeConfig::new(time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)),
1221 )
1222 .map_err(|error| {
1223 Error::Api(format!(
1224 "Setting NetHSM system time failed: {}",
1225 NetHsmApiError::from(error)
1226 ))
1227 })?;
1228 Ok(())
1229 }
1230
1231 /// Gets the [logging configuration].
1232 ///
1233 /// This call requires using [`Credentials`] of a system-wide user in the
1234 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1235 ///
1236 /// # Errors
1237 ///
1238 /// Returns an [`Error::Api`] if getting the [logging configuration] fails:
1239 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1240 /// * the used [`Credentials`] are not correct
1241 /// * the used [`Credentials`] are not that of a system-wide user in the
1242 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1243 ///
1244 /// # Examples
1245 ///
1246 /// ```no_run
1247 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1248 ///
1249 /// # fn main() -> testresult::TestResult {
1250 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1251 /// let nethsm = NetHsm::new(
1252 /// Connection::new(
1253 /// "https://example.org/api/v1".try_into()?,
1254 /// ConnectionSecurity::Unsafe,
1255 /// ),
1256 /// Some(Credentials::new(
1257 /// "admin".parse()?,
1258 /// Some(Passphrase::new("passphrase".to_string())),
1259 /// )),
1260 /// None,
1261 /// None,
1262 /// )?;
1263 /// // add a user in the Administrator role for a namespace (N-Administrator)
1264 /// nethsm.add_user(
1265 /// "Namespace1 Admin".to_string(),
1266 /// UserRole::Administrator,
1267 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1268 /// Some("namespace1~admin1".parse()?),
1269 /// )?;
1270 /// // create accompanying namespace
1271 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1272 ///
1273 /// // R-Administrators can get logging configuration
1274 /// println!("{:?}", nethsm.get_logging()?);
1275 ///
1276 /// // N-Administrators can not get logging configuration
1277 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1278 /// assert!(nethsm.get_logging().is_err());
1279 /// # Ok(())
1280 /// # }
1281 /// ```
1282 /// [logging configuration]: https://docs.nitrokey.com/nethsm/administration#logging
1283 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1284 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1285 pub fn get_logging(&self) -> Result<LoggingConfig, Error> {
1286 debug!(
1287 "Retrieve the logging information of the NetHSM at {} using {}",
1288 self.url.borrow(),
1289 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1290 );
1291
1292 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1293 Ok(config_logging_get(&self.create_connection_config())
1294 .map_err(|error| {
1295 Error::Api(format!(
1296 "Getting logging config failed: {}",
1297 NetHsmApiError::from(error)
1298 ))
1299 })?
1300 .entity)
1301 }
1302
1303 /// Sets the [logging configuration].
1304 ///
1305 /// Sets the NetHSM's [logging configuration] by providing `ip_address` and `port` of a host to
1306 /// send logs to. The log level is configured using `log_level`.
1307 ///
1308 /// This call requires using [`Credentials`] of a system-wide user in the
1309 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1310 ///
1311 /// # Errors
1312 ///
1313 /// Returns an [`Error::Api`] if setting the logging configuration fails:
1314 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1315 /// * the provided `ip_address`, `port` or `log_level` are not valid
1316 /// * the used [`Credentials`] are not correct
1317 /// * the used [`Credentials`] are not that of a system-wide user in the
1318 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1319 ///
1320 /// # Examples
1321 ///
1322 /// ```no_run
1323 /// use std::net::Ipv4Addr;
1324 ///
1325 /// use nethsm::{
1326 /// Connection,
1327 /// ConnectionSecurity,
1328 /// Credentials,
1329 /// LogLevel,
1330 /// NetHsm,
1331 /// Passphrase,
1332 /// UserRole,
1333 /// };
1334 ///
1335 /// # fn main() -> testresult::TestResult {
1336 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1337 /// let nethsm = NetHsm::new(
1338 /// Connection::new(
1339 /// "https://example.org/api/v1".try_into()?,
1340 /// ConnectionSecurity::Unsafe,
1341 /// ),
1342 /// Some(Credentials::new(
1343 /// "admin".parse()?,
1344 /// Some(Passphrase::new("passphrase".to_string())),
1345 /// )),
1346 /// None,
1347 /// None,
1348 /// )?;
1349 /// // add a user in the Administrator role for a namespace (N-Administrator)
1350 /// nethsm.add_user(
1351 /// "Namespace1 Admin".to_string(),
1352 /// UserRole::Administrator,
1353 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1354 /// Some("namespace1~admin1".parse()?),
1355 /// )?;
1356 /// // create accompanying namespace
1357 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1358 ///
1359 /// // R-Administrators can set logging configuration
1360 /// nethsm.set_logging(Ipv4Addr::new(192, 168, 1, 2), 513, LogLevel::Debug)?;
1361 ///
1362 /// // N-Administrators can not set logging configuration
1363 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1364 /// assert!(
1365 /// nethsm
1366 /// .set_logging(Ipv4Addr::new(192, 168, 1, 2), 513, LogLevel::Debug)
1367 /// .is_err()
1368 /// );
1369 /// # Ok(())
1370 /// # }
1371 /// ```
1372 /// [logging configuration]: https://docs.nitrokey.com/nethsm/administration#logging
1373 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1374 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1375 pub fn set_logging(
1376 &self,
1377 ip_address: Ipv4Addr,
1378 port: u32,
1379 log_level: LogLevel,
1380 ) -> Result<(), Error> {
1381 debug!(
1382 "Set the logging configuration to {ip_address}:{port} ({log_level}) for the NetHSM at {} using {}",
1383 self.url.borrow(),
1384 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1385 );
1386
1387 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1388 let ip_address = ip_address.to_string();
1389 config_logging_put(
1390 &self.create_connection_config(),
1391 LoggingConfig::new(ip_address, port as i32, log_level.into()),
1392 )
1393 .map_err(|error| {
1394 Error::Api(format!(
1395 "Setting logging config failed: {}",
1396 NetHsmApiError::from(error)
1397 ))
1398 })?;
1399 Ok(())
1400 }
1401
1402 /// Sets the [backup] passphrase.
1403 ///
1404 /// Sets `current_passphrase` to `new_passphrase`, which changes the [backup] passphrase for the
1405 /// NetHSM.
1406 ///
1407 /// This call requires using [`Credentials`] of a system-wide user in the
1408 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1409 ///
1410 /// # Errors
1411 ///
1412 /// Returns an [`Error::Api`] if setting the backup passphrase fails:
1413 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1414 /// * the provided `current_passphrase` is not correct
1415 /// * the used [`Credentials`] are not correct
1416 /// * the used [`Credentials`] are not that of a system-wide user in the
1417 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1418 ///
1419 /// # Examples
1420 ///
1421 /// ```no_run
1422 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1423 ///
1424 /// # fn main() -> testresult::TestResult {
1425 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1426 /// let nethsm = NetHsm::new(
1427 /// Connection::new(
1428 /// "https://example.org/api/v1".try_into()?,
1429 /// ConnectionSecurity::Unsafe,
1430 /// ),
1431 /// Some(Credentials::new(
1432 /// "admin".parse()?,
1433 /// Some(Passphrase::new("passphrase".to_string())),
1434 /// )),
1435 /// None,
1436 /// None,
1437 /// )?;
1438 /// // add a user in the Administrator role for a namespace (N-Administrator)
1439 /// nethsm.add_user(
1440 /// "Namespace1 Admin".to_string(),
1441 /// UserRole::Administrator,
1442 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1443 /// Some("namespace1~admin1".parse()?),
1444 /// )?;
1445 /// // create accompanying namespace
1446 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1447 ///
1448 /// // R-Administrators can set the backup passphrase
1449 /// nethsm.set_backup_passphrase(
1450 /// Passphrase::new("current-backup-passphrase".to_string()),
1451 /// Passphrase::new("new-backup-passphrase".to_string()),
1452 /// )?;
1453 ///
1454 /// // N-Administrators can not set logging configuration
1455 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1456 /// assert!(
1457 /// nethsm
1458 /// .set_backup_passphrase(
1459 /// Passphrase::new("new-backup-passphrase".to_string()),
1460 /// Passphrase::new("current-backup-passphrase".to_string()),
1461 /// )
1462 /// .is_err()
1463 /// );
1464 /// # Ok(())
1465 /// # }
1466 /// ```
1467 /// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
1468 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1469 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1470 pub fn set_backup_passphrase(
1471 &self,
1472 current_passphrase: Passphrase,
1473 new_passphrase: Passphrase,
1474 ) -> Result<(), Error> {
1475 debug!(
1476 "Set the backup passphrase for the NetHSM at {} using {}",
1477 self.url.borrow(),
1478 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1479 );
1480
1481 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1482 config_backup_passphrase_put(
1483 &self.create_connection_config(),
1484 BackupPassphraseConfig::new(
1485 new_passphrase.expose_owned(),
1486 current_passphrase.expose_owned(),
1487 ),
1488 )
1489 .map_err(|error| {
1490 Error::Api(format!(
1491 "Setting backup passphrase failed: {}",
1492 NetHsmApiError::from(error),
1493 ))
1494 })?;
1495 Ok(())
1496 }
1497
1498 /// Creates a [backup].
1499 ///
1500 /// Triggers the creation and download of a [backup] of the NetHSM.
1501 /// **NOTE**: Before creating the first [backup], the [backup] passphrase must be set using
1502 /// [`set_backup_passphrase`][`NetHsm::set_backup_passphrase`].
1503 ///
1504 /// This call requires using [`Credentials`] of a user in the [`Backup`][`UserRole::Backup`]
1505 /// [role].
1506 ///
1507 /// # Errors
1508 ///
1509 /// Returns an [`Error::Api`] if creating a [backup] fails:
1510 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1511 /// * the used [`Credentials`] are not correct
1512 /// * the used [`Credentials`] are not that of a user in the [`Backup`][`UserRole::Backup`]
1513 /// [role]
1514 /// * the [backup] passphrase has not yet been set
1515 ///
1516 /// # Examples
1517 ///
1518 /// ```no_run
1519 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
1520 ///
1521 /// # fn main() -> testresult::TestResult {
1522 /// // create a connection with a user in the Backup role
1523 /// let nethsm = NetHsm::new(
1524 /// Connection::new(
1525 /// "https://example.org/api/v1".try_into()?,
1526 /// ConnectionSecurity::Unsafe,
1527 /// ),
1528 /// Some(Credentials::new(
1529 /// "backup1".parse()?,
1530 /// Some(Passphrase::new("passphrase".to_string())),
1531 /// )),
1532 /// None,
1533 /// None,
1534 /// )?;
1535 ///
1536 /// // create a backup and write it to file
1537 /// std::fs::write("nethsm.bkp", nethsm.backup()?)?;
1538 /// # Ok(())
1539 /// # }
1540 /// ```
1541 /// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
1542 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1543 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1544 pub fn backup(&self) -> Result<Vec<u8>, Error> {
1545 debug!(
1546 "Retrieve a backup of the NetHSM at {} using {}",
1547 self.url.borrow(),
1548 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1549 );
1550
1551 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1552 Ok(system_backup_post(&self.create_connection_config())
1553 .map_err(|error| {
1554 Error::Api(format!(
1555 "Getting backup failed: {}",
1556 NetHsmApiError::from(error)
1557 ))
1558 })?
1559 .entity)
1560 }
1561
1562 /// Triggers a [factory reset].
1563 ///
1564 /// Triggers a [factory reset] of the NetHSM.
1565 /// **WARNING**: This action deletes all user and system data! Make sure to create a [backup]
1566 /// using [`backup`][`NetHsm::backup`] first!
1567 ///
1568 /// This call requires using [`Credentials`] of a system-wide user in the
1569 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1570 ///
1571 /// # Errors
1572 ///
1573 /// Returns an [`Error::Api`] if resetting the NetHSM fails:
1574 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1575 /// * the used [`Credentials`] are not correct
1576 /// * the used [`Credentials`] are not that of a system-wide user in the
1577 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1578 ///
1579 /// # Examples
1580 ///
1581 /// ```no_run
1582 /// use nethsm::{
1583 /// Connection,
1584 /// ConnectionSecurity,
1585 /// Credentials,
1586 /// NetHsm,
1587 /// Passphrase,
1588 /// SystemState,
1589 /// UserRole,
1590 /// };
1591 ///
1592 /// # fn main() -> testresult::TestResult {
1593 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1594 /// let nethsm = NetHsm::new(
1595 /// Connection::new(
1596 /// "https://example.org/api/v1".try_into()?,
1597 /// ConnectionSecurity::Unsafe,
1598 /// ),
1599 /// Some(Credentials::new(
1600 /// "admin".parse()?,
1601 /// Some(Passphrase::new("passphrase".to_string())),
1602 /// )),
1603 /// None,
1604 /// None,
1605 /// )?;
1606 /// // add a user in the Administrator role for a namespace (N-Administrator)
1607 /// nethsm.add_user(
1608 /// "Namespace1 Admin".to_string(),
1609 /// UserRole::Administrator,
1610 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1611 /// Some("namespace1~admin1".parse()?),
1612 /// )?;
1613 /// // create accompanying namespace
1614 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1615 ///
1616 /// // N-Administrators can not trigger factory reset
1617 /// assert_eq!(nethsm.state()?, SystemState::Operational);
1618 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1619 /// assert!(nethsm.factory_reset().is_err());
1620 ///
1621 /// // R-Administrators are able to trigger a factory reset
1622 /// assert_eq!(nethsm.state()?, SystemState::Operational);
1623 /// nethsm.use_credentials(&"admin".parse()?)?;
1624 /// nethsm.factory_reset()?;
1625 /// assert_eq!(nethsm.state()?, SystemState::Unprovisioned);
1626 /// # Ok(())
1627 /// # }
1628 /// ```
1629 /// [factory reset]: https://docs.nitrokey.com/nethsm/administration#reset-to-factory-defaults
1630 /// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
1631 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1632 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1633 pub fn factory_reset(&self) -> Result<(), Error> {
1634 debug!(
1635 "Trigger a factory reset of the NetHSM at {} using {}",
1636 self.url.borrow(),
1637 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1638 );
1639
1640 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1641 system_factory_reset_post(&self.create_connection_config()).map_err(|error| {
1642 Error::Api(format!(
1643 "Factory reset failed: {}",
1644 NetHsmApiError::from(error)
1645 ))
1646 })?;
1647 Ok(())
1648 }
1649
1650 /// Restores NetHSM from [backup].
1651 ///
1652 /// [Restores] a NetHSM from a [backup], by providing a `backup_passphrase` (see
1653 /// [`set_backup_passphrase`][`NetHsm::set_backup_passphrase`]) a new `system_time` for the
1654 /// NetHSM and a backup file (created using [`backup`][`NetHsm::backup`]).
1655 ///
1656 /// The NetHSM must be in [`Operational`][`SystemState::Operational`] or
1657 /// [`Unprovisioned`][`SystemState::Unprovisioned`] [state].
1658 ///
1659 /// Any existing user data is safely removed and replaced by that of the [backup], after which
1660 /// the NetHSM ends up in [`Locked`][`SystemState::Locked`] [state].
1661 /// If the NetHSM is in [`Unprovisioned`][`SystemState::Unprovisioned`] [state], additionally
1662 /// the system configuration from the backup is applied and leads to a
1663 /// [`reboot`][`NetHsm::reboot`] of the NetHSM.
1664 ///
1665 /// This call requires using [`Credentials`] of a system-wide user in the
1666 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1667 ///
1668 /// # Errors
1669 ///
1670 /// Returns an [`Error::Api`] if restoring the NetHSM from [backup] fails:
1671 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] or
1672 /// [`Unprovisioned`][`SystemState::Unprovisioned`] [state]
1673 /// * the used [`Credentials`] are not correct
1674 /// * the used [`Credentials`] are not that of a system-wide user in the
1675 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1676 ///
1677 /// # Examples
1678 ///
1679 /// ```no_run
1680 /// use chrono::Utc;
1681 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1682 ///
1683 /// #
1684 /// # fn main() -> testresult::TestResult {
1685 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1686 /// let nethsm = NetHsm::new(
1687 /// Connection::new(
1688 /// "https://example.org/api/v1".try_into()?,
1689 /// ConnectionSecurity::Unsafe,
1690 /// ),
1691 /// Some(Credentials::new(
1692 /// "admin".parse()?,
1693 /// Some(Passphrase::new("passphrase".to_string())),
1694 /// )),
1695 /// None,
1696 /// None,
1697 /// )?;
1698 /// // add a user in the Administrator role for a namespace (N-Administrator)
1699 /// nethsm.add_user(
1700 /// "Namespace1 Admin".to_string(),
1701 /// UserRole::Administrator,
1702 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1703 /// Some("namespace1~admin1".parse()?),
1704 /// )?;
1705 /// // create accompanying namespace
1706 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1707 ///
1708 /// // N-Administrators can not restore from backup
1709 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1710 /// assert!(
1711 /// nethsm
1712 /// .restore(
1713 /// Passphrase::new("backup-passphrase".to_string()),
1714 /// Utc::now(),
1715 /// std::fs::read("nethsm.bkp")?,
1716 /// )
1717 /// .is_err()
1718 /// );
1719 ///
1720 /// // R-Administrators can restore from backup
1721 /// nethsm.use_credentials(&"admin".parse()?)?;
1722 /// nethsm.restore(
1723 /// Passphrase::new("backup-passphrase".to_string()),
1724 /// Utc::now(),
1725 /// std::fs::read("nethsm.bkp")?,
1726 /// )?;
1727 /// # Ok(())
1728 /// # }
1729 /// ```
1730 /// [Restores]: https://docs.nitrokey.com/nethsm/administration#restore
1731 /// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
1732 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1733 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1734 pub fn restore(
1735 &self,
1736 backup_passphrase: Passphrase,
1737 system_time: DateTime<Utc>,
1738 backup: Vec<u8>,
1739 ) -> Result<(), Error> {
1740 debug!(
1741 "Restore the NetHSM at {} from backup with the new system time {system_time} using {}",
1742 self.url.borrow(),
1743 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1744 );
1745
1746 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1747 system_restore_post(
1748 &self.create_connection_config(),
1749 Some(nethsm_sdk_rs::models::RestoreRequestArguments {
1750 backup_passphrase: Some(backup_passphrase.expose_owned()),
1751 system_time: Some(system_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)),
1752 }),
1753 Some(backup),
1754 )
1755 .map_err(|error| {
1756 Error::Api(format!(
1757 "Restoring backup failed: {}",
1758 NetHsmApiError::from(error)
1759 ))
1760 })?;
1761 Ok(())
1762 }
1763
1764 /// Locks the NetHSM.
1765 ///
1766 /// Locks the NetHSM and sets its [state] to [`Locked`][`SystemState::Locked`].
1767 ///
1768 /// This call requires using [`Credentials`] of a system-wide user in the
1769 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1770 ///
1771 /// # Errors
1772 ///
1773 /// Returns an [`Error::Api`] if locking the NetHSM fails:
1774 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1775 /// * the used [`Credentials`] are not correct
1776 /// * the used [`Credentials`] are not that of a system-wide user in the
1777 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1778 ///
1779 /// # Examples
1780 ///
1781 /// ```no_run
1782 /// use nethsm::{
1783 /// Connection,
1784 /// ConnectionSecurity,
1785 /// Credentials,
1786 /// NetHsm,
1787 /// Passphrase,
1788 /// SystemState,
1789 /// UserRole,
1790 /// };
1791 ///
1792 /// # fn main() -> testresult::TestResult {
1793 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1794 /// let nethsm = NetHsm::new(
1795 /// Connection::new(
1796 /// "https://example.org/api/v1".try_into()?,
1797 /// ConnectionSecurity::Unsafe,
1798 /// ),
1799 /// Some(Credentials::new(
1800 /// "admin".parse()?,
1801 /// Some(Passphrase::new("passphrase".to_string())),
1802 /// )),
1803 /// None,
1804 /// None,
1805 /// )?;
1806 /// // add a user in the Administrator role for a namespace (N-Administrator)
1807 /// nethsm.add_user(
1808 /// "Namespace1 Admin".to_string(),
1809 /// UserRole::Administrator,
1810 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1811 /// Some("namespace1~admin1".parse()?),
1812 /// )?;
1813 /// // create accompanying namespace
1814 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1815 ///
1816 /// assert_eq!(nethsm.state()?, SystemState::Operational);
1817 ///
1818 /// // N-Administrators can not lock the NetHSM
1819 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1820 /// assert!(nethsm.lock().is_err());
1821 ///
1822 /// // R-Administrators can lock the NetHSM
1823 /// nethsm.use_credentials(&"admin".parse()?)?;
1824 /// nethsm.lock()?;
1825 /// assert_eq!(nethsm.state()?, SystemState::Locked);
1826 /// # Ok(())
1827 /// # }
1828 /// ```
1829 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1830 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1831 pub fn lock(&self) -> Result<(), Error> {
1832 debug!(
1833 "Lock the NetHSM at {} using {}",
1834 self.url.borrow(),
1835 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1836 );
1837
1838 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1839 lock_post(&self.create_connection_config()).map_err(|error| {
1840 Error::Api(format!(
1841 "Locking NetHSM failed: {}",
1842 NetHsmApiError::from(error)
1843 ))
1844 })?;
1845 Ok(())
1846 }
1847
1848 /// Unlocks the NetHSM.
1849 ///
1850 /// Unlocks the NetHSM if it is in [`Locked`][`SystemState::Locked`] [state] by providing
1851 /// `unlock_passphrase` and sets its [state] to [`Operational`][`SystemState::Operational`].
1852 ///
1853 /// For this call no [`Credentials`] are required and if any are configured, they are ignored.
1854 ///
1855 /// # Errors
1856 ///
1857 /// Returns an [`Error::Api`] if unlocking the NetHSM fails:
1858 /// * the NetHSM is not in [`Locked`][`SystemState::Locked`] [state]
1859 ///
1860 /// # Examples
1861 ///
1862 /// ```no_run
1863 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, SystemState};
1864 ///
1865 /// # fn main() -> testresult::TestResult {
1866 /// // no initial [`Credentials`] are required
1867 /// let nethsm = NetHsm::new(
1868 /// Connection::new(
1869 /// "https://example.org/api/v1".try_into()?,
1870 /// ConnectionSecurity::Unsafe,
1871 /// ),
1872 /// None,
1873 /// None,
1874 /// None,
1875 /// )?;
1876 ///
1877 /// assert_eq!(nethsm.state()?, SystemState::Locked);
1878 /// // unlock the NetHSM
1879 /// nethsm.unlock(Passphrase::new("unlock-passphrase".to_string()))?;
1880 /// assert_eq!(nethsm.state()?, SystemState::Operational);
1881 /// # Ok(())
1882 /// # }
1883 /// ```
1884 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1885 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1886 pub fn unlock(&self, unlock_passphrase: Passphrase) -> Result<(), Error> {
1887 debug!(
1888 "Unlock the NetHSM at {} using {}",
1889 self.url.borrow(),
1890 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1891 );
1892
1893 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
1894 unlock_post(
1895 &self.create_connection_config(),
1896 UnlockRequestData::new(unlock_passphrase.expose_owned()),
1897 )
1898 .map_err(|error| {
1899 Error::Api(format!(
1900 "Unlocking NetHSM failed: {}",
1901 NetHsmApiError::from(error)
1902 ))
1903 })?;
1904 Ok(())
1905 }
1906
1907 /// Retrieves [system information].
1908 ///
1909 /// Returns [system information] in the form of a [`SystemInfo`], which contains various pieces
1910 /// of information such as software version, software build, firmware version, hardware
1911 /// version, device ID and information on TPM related components such as attestation key and
1912 /// relevant PCR values.
1913 ///
1914 /// This call requires using [`Credentials`] of a system-wide user in the
1915 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1916 ///
1917 /// # Errors
1918 ///
1919 /// Returns an [`Error::Api`] if retrieving the system information fails:
1920 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1921 /// * the used [`Credentials`] are not correct
1922 /// * the used [`Credentials`] are not that of a system-wide user in the
1923 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1924 ///
1925 /// # Examples
1926 ///
1927 /// ```no_run
1928 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1929 ///
1930 /// # fn main() -> testresult::TestResult {
1931 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1932 /// let nethsm = NetHsm::new(
1933 /// Connection::new(
1934 /// "https://example.org/api/v1".try_into()?,
1935 /// ConnectionSecurity::Unsafe,
1936 /// ),
1937 /// Some(Credentials::new(
1938 /// "admin".parse()?,
1939 /// Some(Passphrase::new("passphrase".to_string())),
1940 /// )),
1941 /// None,
1942 /// None,
1943 /// )?;
1944 /// // add a user in the Administrator role for a namespace (N-Administrator)
1945 /// nethsm.add_user(
1946 /// "Namespace1 Admin".to_string(),
1947 /// UserRole::Administrator,
1948 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1949 /// Some("namespace1~admin1".parse()?),
1950 /// )?;
1951 /// // create accompanying namespace
1952 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1953 ///
1954 /// // R-Administrators can retrieve system information
1955 /// println!("{:?}", nethsm.system_info()?);
1956 ///
1957 /// // N-Administrators can not retrieve system information
1958 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1959 /// assert!(nethsm.system_info().is_err());
1960 /// # Ok(())
1961 /// # }
1962 /// ```
1963 /// [system information]: https://docs.nitrokey.com/nethsm/administration#system-information
1964 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1965 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1966 pub fn system_info(&self) -> Result<SystemInfo, Error> {
1967 debug!(
1968 "Retrieve system information about the NetHSM at {} using {}",
1969 self.url.borrow(),
1970 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
1971 );
1972
1973 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1974 Ok(system_info_get(&self.create_connection_config())
1975 .map_err(|error| {
1976 Error::Api(format!(
1977 "Retrieving system information failed: {}",
1978 NetHsmApiError::from(error)
1979 ))
1980 })?
1981 .entity)
1982 }
1983
1984 /// [Reboots] the NetHSM.
1985 ///
1986 /// [Reboots] the NetHSM, if it is in [`Operational`][`SystemState::Operational`] [state].
1987 ///
1988 /// This call requires using [`Credentials`] of a system-wide user in the
1989 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1990 ///
1991 /// # Errors
1992 ///
1993 /// Returns an [`Error::Api`] if rebooting the NetHSM fails:
1994 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1995 /// * the used [`Credentials`] are not correct
1996 /// * the used [`Credentials`] are not that of a system-wide user in the
1997 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1998 ///
1999 /// # Examples
2000 ///
2001 /// ```no_run
2002 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2003 ///
2004 /// # fn main() -> testresult::TestResult {
2005 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2006 /// let nethsm = NetHsm::new(
2007 /// Connection::new(
2008 /// "https://example.org/api/v1".try_into()?,
2009 /// ConnectionSecurity::Unsafe,
2010 /// ),
2011 /// Some(Credentials::new(
2012 /// "admin".parse()?,
2013 /// Some(Passphrase::new("passphrase".to_string())),
2014 /// )),
2015 /// None,
2016 /// None,
2017 /// )?;
2018 /// // add a user in the Administrator role for a namespace (N-Administrator)
2019 /// nethsm.add_user(
2020 /// "Namespace1 Admin".to_string(),
2021 /// UserRole::Administrator,
2022 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2023 /// Some("namespace1~admin1".parse()?),
2024 /// )?;
2025 /// // create accompanying namespace
2026 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2027 ///
2028 /// // N-Administrators can not reboot the NetHSM
2029 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2030 /// assert!(nethsm.reboot().is_err());
2031 ///
2032 /// // R-Administrators can reboot the NetHSM
2033 /// nethsm.use_credentials(&"admin".parse()?)?;
2034 /// nethsm.reboot()?;
2035 /// # Ok(())
2036 /// # }
2037 /// ```
2038 /// [Reboots]: https://docs.nitrokey.com/nethsm/administration#reboot-and-shutdown
2039 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2040 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2041 pub fn reboot(&self) -> Result<(), Error> {
2042 debug!(
2043 "Reboot the NetHSM at {} using {}",
2044 self.url.borrow(),
2045 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
2046 );
2047
2048 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2049 system_reboot_post(&self.create_connection_config()).map_err(|error| {
2050 Error::Api(format!(
2051 "Rebooting NetHSM failed: {}",
2052 NetHsmApiError::from(error)
2053 ))
2054 })?;
2055 Ok(())
2056 }
2057
2058 /// [Shuts down] the NetHSM.
2059 ///
2060 /// [Shuts down] the NetHSM, if it is in [`Operational`][`SystemState::Operational`] [state].
2061 ///
2062 /// This call requires using [`Credentials`] of a system-wide user in the
2063 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2064 ///
2065 /// # Errors
2066 ///
2067 /// Returns an [`Error::Api`] if shutting down the NetHSM fails:
2068 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2069 /// * the used [`Credentials`] are not correct
2070 /// * the used [`Credentials`] are not that of a system-wide user in the
2071 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2072 ///
2073 /// # Examples
2074 ///
2075 /// ```no_run
2076 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2077 ///
2078 /// # fn main() -> testresult::TestResult {
2079 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2080 /// let nethsm = NetHsm::new(
2081 /// Connection::new(
2082 /// "https://example.org/api/v1".try_into()?,
2083 /// ConnectionSecurity::Unsafe,
2084 /// ),
2085 /// Some(Credentials::new(
2086 /// "admin".parse()?,
2087 /// Some(Passphrase::new("passphrase".to_string())),
2088 /// )),
2089 /// None,
2090 /// None,
2091 /// )?;
2092 /// // add a user in the Administrator role for a namespace (N-Administrator)
2093 /// nethsm.add_user(
2094 /// "Namespace1 Admin".to_string(),
2095 /// UserRole::Administrator,
2096 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2097 /// Some("namespace1~admin1".parse()?),
2098 /// )?;
2099 /// // create accompanying namespace
2100 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2101 ///
2102 /// // N-Administrators can not shut down the NetHSM
2103 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2104 /// assert!(nethsm.shutdown().is_err());
2105 ///
2106 /// // R-Administrators can shut down the NetHSM
2107 /// nethsm.use_credentials(&"admin".parse()?)?;
2108 /// nethsm.shutdown()?;
2109 /// # Ok(())
2110 /// # }
2111 /// ```
2112 /// [Shuts down]: https://docs.nitrokey.com/nethsm/administration#reboot-and-shutdown
2113 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2114 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2115 pub fn shutdown(&self) -> Result<(), Error> {
2116 debug!(
2117 "Shut down the NetHSM at {} using {}",
2118 self.url.borrow(),
2119 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
2120 );
2121
2122 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2123 system_shutdown_post(&self.create_connection_config()).map_err(|error| {
2124 Error::Api(format!(
2125 "Shutting down NetHSM failed: {}",
2126 NetHsmApiError::from(error)
2127 ))
2128 })?;
2129 Ok(())
2130 }
2131
2132 /// Uploads a software update.
2133 ///
2134 /// WARNING: This function has shown flaky behavior during tests with the official container!
2135 /// Upload may have to be repeated!
2136 ///
2137 /// Uploads a [software update] to the NetHSM, if it is in
2138 /// [`Operational`][`SystemState::Operational`] [state] and returns information about the
2139 /// software update as [`SystemUpdateData`].
2140 /// Software updates can successively be installed ([`commit_update`][`NetHsm::commit_update`])
2141 /// or canceled ([`cancel_update`][`NetHsm::cancel_update`]).
2142 ///
2143 /// This call requires using [`Credentials`] of a system-wide user in the
2144 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2145 ///
2146 /// # Errors
2147 ///
2148 /// Returns an [`Error::Api`] if uploading the software update fails:
2149 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2150 /// * the used [`Credentials`] are not correct
2151 /// * the used [`Credentials`] are not that of a system-wide user in the
2152 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2153 ///
2154 /// # Examples
2155 ///
2156 /// ```no_run
2157 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2158 ///
2159 /// # fn main() -> testresult::TestResult {
2160 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2161 /// let nethsm = NetHsm::new(
2162 /// Connection::new(
2163 /// "https://example.org/api/v1".try_into()?,
2164 /// ConnectionSecurity::Unsafe,
2165 /// ),
2166 /// Some(Credentials::new(
2167 /// "admin".parse()?,
2168 /// Some(Passphrase::new("passphrase".to_string())),
2169 /// )),
2170 /// None,
2171 /// None,
2172 /// )?;
2173 /// // add a user in the Administrator role for a namespace (N-Administrator)
2174 /// nethsm.add_user(
2175 /// "Namespace1 Admin".to_string(),
2176 /// UserRole::Administrator,
2177 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2178 /// Some("namespace1~admin1".parse()?),
2179 /// )?;
2180 /// // create accompanying namespace
2181 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2182 ///
2183 /// // N-Administrators can not upload software updates to the NetHSM
2184 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2185 /// assert!(nethsm.upload_update(std::fs::read("update.bin")?).is_err());
2186 ///
2187 /// // R-Administrators can upload software updates to the NetHSM
2188 /// nethsm.use_credentials(&"admin".parse()?)?;
2189 /// println!("{:?}", nethsm.upload_update(std::fs::read("update.bin")?)?);
2190 /// # Ok(())
2191 /// # }
2192 /// ```
2193 /// [software update]: https://docs.nitrokey.com/nethsm/administration#software-update
2194 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2195 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2196 pub fn upload_update(&self, update: Vec<u8>) -> Result<SystemUpdateData, Error> {
2197 debug!(
2198 "Upload an update to the NetHSM at {} using {}",
2199 self.url.borrow(),
2200 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
2201 );
2202
2203 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2204 Ok(system_update_post(&self.create_connection_config(), update)
2205 .map_err(|error| {
2206 println!("error during upload");
2207 Error::Api(format!(
2208 "Uploading update failed: {}",
2209 NetHsmApiError::from(error)
2210 ))
2211 })?
2212 .entity)
2213 }
2214
2215 /// Commits an already uploaded [software update].
2216 ///
2217 /// Commits a [software update] previously uploaded to the NetHSM (using
2218 /// [`upload_update`][`NetHsm::upload_update`]), if the NetHSM is in
2219 /// [`Operational`][`SystemState::Operational`] [state].
2220 /// Successfully committing a [software update] leads to the [reboot] of the NetHSM.
2221 ///
2222 /// This call requires using [`Credentials`] of a system-wide user in the
2223 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2224 ///
2225 /// # Errors
2226 ///
2227 /// Returns an [`Error::Api`] if committing the software update fails:
2228 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2229 /// * there is no software update to commit
2230 /// * the used [`Credentials`] are not correct
2231 /// * the used [`Credentials`] are not that of a system-wide user in the
2232 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2233 ///
2234 /// # Examples
2235 ///
2236 /// ```no_run
2237 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2238 ///
2239 /// # fn main() -> testresult::TestResult {
2240 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2241 /// let nethsm = NetHsm::new(
2242 /// Connection::new(
2243 /// "https://example.org/api/v1".try_into()?,
2244 /// ConnectionSecurity::Unsafe,
2245 /// ),
2246 /// Some(Credentials::new(
2247 /// "admin".parse()?,
2248 /// Some(Passphrase::new("passphrase".to_string())),
2249 /// )),
2250 /// None,
2251 /// None,
2252 /// )?;
2253 /// // add a user in the Administrator role for a namespace (N-Administrator)
2254 /// nethsm.add_user(
2255 /// "Namespace1 Admin".to_string(),
2256 /// UserRole::Administrator,
2257 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2258 /// Some("namespace1~admin1".parse()?),
2259 /// )?;
2260 /// // create accompanying namespace
2261 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2262 ///
2263 /// println!("{:?}", nethsm.upload_update(std::fs::read("update.bin")?)?);
2264 ///
2265 /// // N-Administrators can not commit software updates on a NetHSM
2266 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2267 /// assert!(nethsm.commit_update().is_err());
2268 ///
2269 /// // R-Administrators can commit software updates on a NetHSM
2270 /// nethsm.use_credentials(&"admin".parse()?)?;
2271 /// nethsm.commit_update()?;
2272 /// # Ok(())
2273 /// # }
2274 /// ```
2275 /// [software update]: https://docs.nitrokey.com/nethsm/administration#software-update
2276 /// [reboot]: https://docs.nitrokey.com/nethsm/administration#reboot-and-shutdown
2277 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2278 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2279 pub fn commit_update(&self) -> Result<(), Error> {
2280 debug!(
2281 "Commit an already uploaded update on the NetHSM at {} using {}",
2282 self.url.borrow(),
2283 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
2284 );
2285
2286 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2287 system_commit_update_post(&self.create_connection_config()).map_err(|error| {
2288 Error::Api(format!(
2289 "Committing update failed: {}",
2290 NetHsmApiError::from(error)
2291 ))
2292 })?;
2293 Ok(())
2294 }
2295
2296 /// Cancels an already uploaded [software update].
2297 ///
2298 /// Cancels a [software update] previously uploaded to the NetHSM (using
2299 /// [`upload_update`][`NetHsm::upload_update`]), if the NetHSM is in
2300 /// [`Operational`][`SystemState::Operational`] [state].
2301 ///
2302 /// This call requires using [`Credentials`] of a system-wide user in the
2303 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2304 ///
2305 /// # Errors
2306 ///
2307 /// Returns an [`Error::Api`] if canceling the software update fails:
2308 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2309 /// * there is no software update to cancel
2310 /// * the used [`Credentials`] are not correct
2311 /// * the used [`Credentials`] are not that of a system-wide user in the
2312 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2313 ///
2314 /// # Examples
2315 ///
2316 /// ```no_run
2317 /// use nethsm::{
2318 /// Connection,
2319 /// ConnectionSecurity,
2320 /// Credentials,
2321 /// NetHsm,
2322 /// Passphrase,
2323 /// SystemState,
2324 /// UserRole,
2325 /// };
2326 ///
2327 /// # fn main() -> testresult::TestResult {
2328 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2329 /// let nethsm = NetHsm::new(
2330 /// Connection::new(
2331 /// "https://example.org/api/v1".try_into()?,
2332 /// ConnectionSecurity::Unsafe,
2333 /// ),
2334 /// Some(Credentials::new(
2335 /// "admin".parse()?,
2336 /// Some(Passphrase::new("passphrase".to_string())),
2337 /// )),
2338 /// None,
2339 /// None,
2340 /// )?;
2341 /// // add a user in the Administrator role for a namespace (N-Administrator)
2342 /// nethsm.add_user(
2343 /// "Namespace1 Admin".to_string(),
2344 /// UserRole::Administrator,
2345 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2346 /// Some("namespace1~admin1".parse()?),
2347 /// )?;
2348 /// // create accompanying namespace
2349 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2350 ///
2351 /// println!("{:?}", nethsm.upload_update(std::fs::read("update.bin")?)?);
2352 /// assert_eq!(nethsm.state()?, SystemState::Operational);
2353 ///
2354 /// // N-Administrators can not cancel software updates on a NetHSM
2355 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2356 /// assert!(nethsm.cancel_update().is_err());
2357 ///
2358 /// // R-Administrators can cancel software updates on a NetHSM
2359 /// nethsm.cancel_update()?;
2360 /// assert_eq!(nethsm.state()?, SystemState::Operational);
2361 /// # Ok(())
2362 /// # }
2363 /// ```
2364 /// [software update]: https://docs.nitrokey.com/nethsm/administration#software-update
2365 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2366 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2367 pub fn cancel_update(&self) -> Result<(), Error> {
2368 debug!(
2369 "Cancel an already uploaded update on the NetHSM at {} using {}",
2370 self.url.borrow(),
2371 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
2372 );
2373
2374 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2375 system_cancel_update_post(&self.create_connection_config()).map_err(|error| {
2376 Error::Api(format!(
2377 "Cancelling update failed: {}",
2378 NetHsmApiError::from(error)
2379 ))
2380 })?;
2381 Ok(())
2382 }
2383
2384 /// Generates [random] bytes.
2385 ///
2386 /// Retrieves `length` [random] bytes from the NetHSM, if it is in
2387 /// [`Operational`][`SystemState::Operational`] [state].
2388 ///
2389 /// This call requires using [`Credentials`] of a user in the [`Operator`][`UserRole::Operator`]
2390 /// [role].
2391 ///
2392 /// # Errors
2393 ///
2394 /// Returns an [`Error::Api`] if retrieving random bytes fails:
2395 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2396 /// * the used [`Credentials`] are not correct
2397 /// * the used [`Credentials`] are not that of a user in the [`Operator`][`UserRole::Operator`]
2398 /// [role]
2399 ///
2400 /// # Examples
2401 ///
2402 /// ```no_run
2403 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2404 ///
2405 /// # fn main() -> testresult::TestResult {
2406 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2407 /// let nethsm = NetHsm::new(
2408 /// Connection::new(
2409 /// "https://example.org/api/v1".try_into()?,
2410 /// ConnectionSecurity::Unsafe,
2411 /// ),
2412 /// Some(Credentials::new(
2413 /// "admin".parse()?,
2414 /// Some(Passphrase::new("passphrase".to_string())),
2415 /// )),
2416 /// None,
2417 /// None,
2418 /// )?;
2419 /// // add a system-wide user in the Operator role
2420 /// nethsm.add_user(
2421 /// "Operator1".to_string(),
2422 /// UserRole::Operator,
2423 /// Passphrase::new("operator-passphrase".to_string()),
2424 /// Some("operator1".parse()?),
2425 /// )?;
2426 /// nethsm.use_credentials(&"operator1".parse()?)?;
2427 ///
2428 /// // get 10 random bytes
2429 /// println!("{:#?}", nethsm.random(10)?);
2430 /// # Ok(())
2431 /// # }
2432 /// ```
2433 /// [random]: https://docs.nitrokey.com/nethsm/operation#random
2434 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
2435 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2436 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2437 pub fn random(&self, length: u32) -> Result<Vec<u8>, Error> {
2438 debug!(
2439 "Create {length} random bytes on the NetHSM at {} using {}",
2440 self.url.borrow(),
2441 user_or_no_user_string(self.current_credentials.borrow().as_ref()),
2442 );
2443
2444 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
2445 let base64_bytes = random_post(
2446 &self.create_connection_config(),
2447 RandomRequestData::new(length as i32),
2448 )
2449 .map_err(|error| {
2450 Error::Api(format!(
2451 "Getting random bytes failed: {}",
2452 NetHsmApiError::from(error)
2453 ))
2454 })?
2455 .entity
2456 .random;
2457 Base64::decode_vec(&base64_bytes).map_err(Error::Base64Decode)
2458 }
2459}