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