nethsm/lib.rs
1//! A high-level library to interact with the API of a [Nitrokey NetHSM].
2//!
3//! Provides high-level integration with a [Nitrokey NetHSM] and the official container.
4//! As this crate is a wrapper around [`nethsm_sdk_rs`] it covers all available actions from
5//! provisioning, over key and user management to backup and restore.
6//!
7//! The NetHSM provides dedicated [user management] based on a [role] system (see [`UserRole`])
8//! which can be used to separate concerns.
9//! Each user has exactly one [role].
10//!
11//! With the help of a [namespace] concept, it is possible to segregate users and their keys into
12//! secluded groups.
13//! Notably, this introduces *R-Administrators* (system-wide users in the
14//! [`Administrator`][`UserRole::Administrator`] [role]), which have access to all system-wide
15//! actions, but can *not* modify users and keys in a [namespace] and *N-Administrators*
16//! ([namespace] users in the [`Administrator`][`UserRole::Administrator`] [role]), which have
17//! access only to actions towards users and keys in their own [namespace].
18//! [Namespace] users in the [`Operator`][`UserRole::Operator`] [role] only have access to keys in
19//! their own [namespace], while system-wide users only have access to system-wide keys.
20//!
21//! The cryptographic key material on the NetHSM can be assigned to one or several [tags].
22//! Users in the [`Operator`][`UserRole::Operator`] [role] can be assigned to the same [tags]
23//! to gain access to the respective keys.
24//!
25//! Using the central [`NetHsm`] struct it is possible to establish a TLS connection for multiple
26//! users and all available operations.
27//! TLS validation can be configured based on a variant of the [`ConnectionSecurity`] enum:
28//! - [`ConnectionSecurity::Unsafe`]: The host certificate is not validated.
29//! - [`ConnectionSecurity::Fingerprints`]: The host certificate is validated based on configurable
30//! fingerprints.
31//! - [`ConnectionSecurity::Native`]: The host certificate is validated using the native Operating
32//! System trust store.
33//!
34//! Apart from the crate specific documentation it is very recommended to read the canonical
35//! upstream documentation as well: <https://docs.nitrokey.com/nethsm/>
36//!
37//! ## Reexports
38//!
39//! This crate re-exports the following types, so that the respective crates do not have to be
40//! relied upon directly:
41//!
42//! * [`chrono::DateTime`]
43//! * [`chrono::Utc`]
44//! * [`nethsm_sdk_rs::models::DistinguishedName`]
45//! * [`nethsm_sdk_rs::models::InfoData`]
46//! * [`nethsm_sdk_rs::models::LoggingConfig`]
47//! * [`nethsm_sdk_rs::models::NetworkConfig`]
48//! * [`nethsm_sdk_rs::models::PublicKey`]
49//! * [`nethsm_sdk_rs::models::SystemInfo`]
50//! * [`nethsm_sdk_rs::models::SystemState`]
51//! * [`nethsm_sdk_rs::models::SystemUpdateData`]
52//! * [`nethsm_sdk_rs::models::UserData`]
53//!
54//! # Examples
55//!
56//! ```
57//! use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
58//!
59//! # fn main() -> testresult::TestResult {
60//! // Create a new connection to a NetHSM at "https://example.org" using admin credentials
61//! let nethsm = NetHsm::new(
62//! Connection::new(
63//! "https://example.org/api/v1".try_into()?,
64//! ConnectionSecurity::Unsafe,
65//! ),
66//! Some(Credentials::new("admin".parse()?, Some(Passphrase::new("passphrase".to_string())))),
67//! None,
68//! None,
69//! )?;
70//!
71//! // Connections can be initialized without any credentials and more than one can be provided later on
72//! let nethsm = NetHsm::new(
73//! Connection::new(
74//! "https://example.org/api/v1".try_into()?,
75//! ConnectionSecurity::Unsafe,
76//! ),
77//! None,
78//! None,
79//! None,
80//! )?;
81//!
82//! nethsm.add_credentials(Credentials::new("admin".parse()?, Some(Passphrase::new("passphrase".to_string()))));
83//! nethsm.add_credentials(Credentials::new("user1".parse()?, Some(Passphrase::new("other_passphrase".to_string()))));
84//!
85//! // A set of credentials must be used before establishing a connection with the configured NetHSM
86//! nethsm.use_credentials(&"user1".parse()?)?;
87//! # Ok(())
88//! # }
89//! ```
90//! [Nitrokey NetHSM]: https://docs.nitrokey.com/nethsm/
91//! [user management]: https://docs.nitrokey.com/nethsm/administration#user-management
92//! [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
93//! [tags]: https://docs.nitrokey.com/nethsm/operation#tags-for-keys
94//! [role]: https://docs.nitrokey.com/nethsm/administration#roles
95use std::cell::RefCell;
96use std::collections::HashMap;
97use std::io::Read;
98use std::net::Ipv4Addr;
99#[cfg(doc)]
100use std::thread::available_parallelism;
101
102use base64ct::{Base64, Encoding};
103pub use chrono::{DateTime, Utc};
104use log::error;
105use md5::{Digest as _, Md5};
106use nethsm_sdk_rs::apis::configuration::Configuration;
107use nethsm_sdk_rs::apis::default_api::{
108 KeysPostBody,
109 config_backup_passphrase_put,
110 config_logging_get,
111 config_logging_put,
112 config_network_get,
113 config_network_put,
114 config_time_get,
115 config_time_put,
116 config_tls_cert_pem_get,
117 config_tls_cert_pem_put,
118 config_tls_csr_pem_post,
119 config_tls_generate_post,
120 config_tls_public_pem_get,
121 config_unattended_boot_get,
122 config_unattended_boot_put,
123 config_unlock_passphrase_put,
124 health_alive_get,
125 health_ready_get,
126 health_state_get,
127 info_get,
128 keys_generate_post,
129 keys_get,
130 keys_key_id_cert_delete,
131 keys_key_id_cert_get,
132 keys_key_id_cert_put,
133 keys_key_id_csr_pem_post,
134 keys_key_id_decrypt_post,
135 keys_key_id_delete,
136 keys_key_id_encrypt_post,
137 keys_key_id_get,
138 keys_key_id_public_pem_get,
139 keys_key_id_put,
140 keys_key_id_restrictions_tags_tag_delete,
141 keys_key_id_restrictions_tags_tag_put,
142 keys_key_id_sign_post,
143 keys_post,
144 lock_post,
145 metrics_get,
146 namespaces_get,
147 namespaces_namespace_id_delete,
148 namespaces_namespace_id_put,
149 provision_post,
150 random_post,
151 system_backup_post,
152 system_cancel_update_post,
153 system_commit_update_post,
154 system_factory_reset_post,
155 system_info_get,
156 system_reboot_post,
157 system_restore_post,
158 system_shutdown_post,
159 system_update_post,
160 unlock_post,
161 users_get,
162 users_post,
163 users_user_id_delete,
164 users_user_id_get,
165 users_user_id_passphrase_post,
166 users_user_id_put,
167 users_user_id_tags_get,
168 users_user_id_tags_tag_delete,
169 users_user_id_tags_tag_put,
170};
171use nethsm_sdk_rs::models::{
172 BackupPassphraseConfig,
173 DecryptRequestData,
174 EncryptRequestData,
175 KeyGenerateRequestData,
176 KeyRestrictions,
177 PrivateKey,
178 ProvisionRequestData,
179 RandomRequestData,
180 SignRequestData,
181 TimeConfig,
182 TlsKeyGenerateRequestData,
183 UnlockPassphraseConfig,
184 UnlockRequestData,
185 UserPassphrasePostData,
186 UserPostData,
187};
188// Re-export some useful types so that users do not have to use nethsm-sdk-rs directly
189pub use nethsm_sdk_rs::models::{
190 DistinguishedName,
191 InfoData,
192 LoggingConfig,
193 NetworkConfig,
194 PublicKey,
195 SystemInfo,
196 SystemState,
197 SystemUpdateData,
198 UserData,
199};
200use nethsm_sdk_rs::ureq::Agent;
201use serde_json::Value;
202use sha1::Sha1;
203use sha2::{Digest, Sha224, Sha256, Sha384, Sha512};
204
205pub mod connection;
206pub use connection::{Connection, Url};
207
208mod key;
209pub use key::{
210 CryptographicKeyContext,
211 MIN_RSA_BIT_LENGTH,
212 PrivateKeyImport,
213 SigningKeySetup,
214 key_type_and_mechanisms_match_signature_type,
215 key_type_matches_length,
216 key_type_matches_mechanisms,
217 tls_key_type_matches_length,
218};
219
220mod nethsm_sdk;
221use nethsm_sdk::NetHsmApiError;
222pub use nethsm_sdk::{
223 BootMode,
224 DecryptMode,
225 EncryptMode,
226 KeyFormat,
227 KeyMechanism,
228 KeyType,
229 LogLevel,
230 SignatureType,
231 TlsKeyType,
232 UserRole,
233};
234mod openpgp;
235pub use openpgp::{
236 KeyUsageFlags as OpenPgpKeyUsageFlags,
237 OpenPgpUserId,
238 OpenPgpUserIdList,
239 OpenPgpVersion,
240 extract_certificate as extract_openpgp_certificate,
241 tsk_to_private_key_import,
242};
243
244#[cfg(feature = "test-helpers")]
245pub mod test;
246
247mod tls;
248use tls::create_agent;
249pub use tls::{ConnectionSecurity, HostCertificateFingerprints};
250
251mod user;
252pub use key::KeyId;
253pub use user::Error as UserError;
254use user::NamespaceSupport;
255pub use user::{Credentials, FullCredentials, NamespaceId, Passphrase, UserId};
256
257/// An error that may occur when using a NetHSM.
258#[derive(Debug, thiserror::Error)]
259pub enum Error {
260 /// Wraps a [`rustls::Error`] for issues with rustls based TLS setups
261 #[error("TLS error: {0}")]
262 Rustls(#[from] rustls::Error),
263
264 /// A Base64 encoded string can not be decode
265 #[error("Decoding Base64 string failed: {0}")]
266 Base64Decode(#[from] base64ct::Error),
267
268 /// A generic error with a custom message
269 #[error("NetHSM error: {0}")]
270 Default(String),
271
272 /// The loading of TLS root certificates from the platform's native certificate store failed
273 #[error("Loading system TLS certs failed: {0:?}")]
274 CertLoading(Vec<rustls_native_certs::Error>),
275
276 /// No TLS root certificates from the platform's native certificate store could be added
277 ///
278 /// Provides the number certificates that failed to be added
279 #[error("Unable to load any system TLS certs ({failed} failed)")]
280 NoSystemCertsAdded {
281 /// The number of certificates that failed to be added.
282 failed: usize,
283 },
284
285 /// A call to the NetHSM API failed
286 #[error("NetHSM API error: {0}")]
287 Api(String),
288
289 /// An error occurred in the [`connection`] module.
290 #[error("NetHSM connection error:\n{0}")]
291 Connection(#[from] connection::Error),
292
293 /// An error with a key occurred
294 #[error("Key error: {0}")]
295 Key(#[from] key::Error),
296
297 /// User data error
298 #[error("User data error: {0}")]
299 User(#[from] user::Error),
300
301 /// OpenPGP error
302 #[error("OpenPGP error: {0}")]
303 OpenPgp(#[from] openpgp::Error),
304}
305
306/// Validates a [backup].
307///
308/// Parses a previously created backup file. If `passphrase` is
309/// [`Some`], additionally decrypts the backup and verifies the
310/// encrypted backup version number.
311///
312/// # Errors
313///
314/// Returns an [`nethsm_backup::Error`] if validating a [backup] fails:
315/// * the magic number is missing in the file
316/// * the version number is unknown
317/// * the provided passphrase is incorrect
318///
319/// # Examples
320///
321/// ```no_run
322/// use nethsm::{
323/// Connection,
324/// ConnectionSecurity,
325/// Credentials,
326/// NetHsm,
327/// Passphrase,
328/// validate_backup,
329/// };
330///
331/// # fn main() -> testresult::TestResult {
332/// // create a connection with a user in the Backup role
333/// let nethsm = NetHsm::new(
334/// Connection::new(
335/// "https://example.org/api/v1".try_into()?,
336/// ConnectionSecurity::Unsafe,
337/// ),
338/// Some(Credentials::new(
339/// "backup1".parse()?,
340/// Some(Passphrase::new("passphrase".to_string())),
341/// )),
342/// None,
343/// None,
344/// )?;
345///
346/// // create a backup and write it to file
347/// std::fs::write("nethsm.bkp", nethsm.backup()?)?;
348///
349/// // check for consistency only
350/// validate_backup(&mut std::fs::File::open("nethsm.bkp")?, None)?;
351///
352/// // check for correct passphrase by decrypting and validating the encrypted backup version
353/// validate_backup(
354/// &mut std::fs::File::open("nethsm.bkp")?,
355/// Passphrase::new("a sample password".into()),
356/// )?;
357/// # Ok(())
358/// # }
359/// ```
360/// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
361pub fn validate_backup(
362 reader: &mut impl Read,
363 passphrase: impl Into<Option<Passphrase>>,
364) -> Result<(), nethsm_backup::Error> {
365 let passphrase = passphrase.into();
366 let backup = nethsm_backup::Backup::parse(reader)?;
367 if let Some(passphrase) = passphrase {
368 let decryptor = backup.decrypt(passphrase.expose_borrowed().as_bytes())?;
369 let version = decryptor.version()?;
370 if version.len() != 1 || version[0] != 0 {
371 return Err(nethsm_backup::Error::BadVersion {
372 highest_supported_version: 0,
373 backup_version: version,
374 });
375 }
376 }
377 Ok(())
378}
379
380/// A network connection to a NetHSM.
381///
382/// Defines a network configuration for the connection and a list of user [`Credentials`] that can
383/// be used over this connection.
384#[derive(Debug)]
385pub struct NetHsm {
386 /// The agent for the requests
387 agent: RefCell<Agent>,
388 /// The URL path for the target API
389 url: RefCell<Url>,
390 /// The default [`Credentials`] to use for requests
391 current_credentials: RefCell<Option<UserId>>,
392 /// The list of all available credentials
393 credentials: RefCell<HashMap<UserId, Credentials>>,
394}
395
396impl NetHsm {
397 /// Creates a new NetHSM connection.
398 ///
399 /// Creates a new NetHSM connection based on a [`Connection`].
400 ///
401 /// Optionally initial `credentials` (used when communicating with the NetHSM),
402 /// `max_idle_connections` to set the size of the connection pool (defaults to `100`) and
403 /// `timeout_seconds` to set the timeout for a successful socket connection (defaults to `10`)
404 /// can be provided.
405 ///
406 /// # Errors
407 ///
408 /// - the TLS client configuration can not be created,
409 /// - or [`ConnectionSecurity::Native`] is provided as `tls_security`, but no certification
410 /// authority certificates are available on the system.
411 pub fn new(
412 connection: Connection,
413 credentials: Option<Credentials>,
414 max_idle_connections: Option<usize>,
415 timeout_seconds: Option<u64>,
416 ) -> Result<Self, Error> {
417 let agent = RefCell::new(create_agent(
418 connection.tls_security,
419 max_idle_connections,
420 timeout_seconds,
421 )?);
422
423 let (current_credentials, credentials) = if let Some(credentials) = credentials {
424 (
425 RefCell::new(Some(credentials.user_id.clone())),
426 RefCell::new(HashMap::from([(credentials.user_id.clone(), credentials)])),
427 )
428 } else {
429 (Default::default(), Default::default())
430 };
431
432 Ok(Self {
433 agent,
434 url: RefCell::new(connection.url),
435 current_credentials,
436 credentials,
437 })
438 }
439
440 /// Validates the potential [namespace] access of a context.
441 ///
442 /// Validates, that [`current_credentials`][`NetHsm::current_credentials`] can be used in a
443 /// defined context. This function relies on [`UserId::validate_namespace_access`] and should be
444 /// used for validating the context of [`NetHsm`] methods.
445 ///
446 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
447 fn validate_namespace_access(
448 &self,
449 support: NamespaceSupport,
450 target: Option<&UserId>,
451 role: Option<&UserRole>,
452 ) -> Result<(), Error> {
453 if let Some(current_user_id) = self.current_credentials.borrow().to_owned() {
454 current_user_id.validate_namespace_access(support, target, role)?
455 }
456 Ok(())
457 }
458
459 /// Creates a connection configuration.
460 ///
461 /// Uses the [`Agent`] configured during creation of the [`NetHsm`], the current [`Url`] and
462 /// [`Credentials`] to create a [`Configuration`] for a connection to the API of a NetHSM.
463 fn create_connection_config(&self) -> Configuration {
464 let current_credentials = self.current_credentials.borrow().to_owned();
465 Configuration {
466 client: self.agent.borrow().to_owned(),
467 base_path: self.url.borrow().to_string(),
468 basic_auth: if let Some(current_credentials) = current_credentials {
469 self.credentials
470 .borrow()
471 .get(¤t_credentials)
472 .map(Into::into)
473 } else {
474 None
475 },
476 user_agent: Some(format!(
477 "{}/{}",
478 env!("CARGO_PKG_NAME"),
479 env!("CARGO_PKG_VERSION")
480 )),
481 ..Default::default()
482 }
483 }
484
485 /// Sets the connection agent for the NetHSM connection.
486 ///
487 /// Allows setting the
488 /// - [`ConnectionSecurity`] which defines the TLS security model for the connection,
489 /// - maximum idle connections per host using the optional `max_idle_connections` (defaults to
490 /// [`available_parallelism`] and falls back to `100` if unavailable),
491 /// - and timeout in seconds for a successful socket connection using the optional
492 /// `timeout_seconds` (defaults to `10`).
493 ///
494 /// # Errors
495 ///
496 /// Returns an error if
497 ///
498 /// - the TLS client configuration can not be created,
499 /// - [`ConnectionSecurity::Native`] is provided as `tls_security`, but no certification
500 /// authority certificates are available on the system.
501 ///
502 /// # Examples
503 ///
504 /// ```
505 /// use nethsm::{Connection, ConnectionSecurity, NetHsm, Url};
506 ///
507 /// # fn main() -> testresult::TestResult {
508 /// // Create a new connection for a NetHSM at "https://example.org"
509 /// let nethsm = NetHsm::new(
510 /// Connection::new(
511 /// "https://example.org/api/v1".try_into()?,
512 /// ConnectionSecurity::Unsafe,
513 /// ),
514 /// None,
515 /// None,
516 /// None,
517 /// )?;
518 ///
519 /// // change the connection agent to something else
520 /// nethsm.set_agent(ConnectionSecurity::Unsafe, Some(200), Some(30))?;
521 /// # Ok(())
522 /// # }
523 /// ```
524 pub fn set_agent(
525 &self,
526 tls_security: ConnectionSecurity,
527 max_idle_connections: Option<usize>,
528 timeout_seconds: Option<u64>,
529 ) -> Result<(), Error> {
530 *self.agent.borrow_mut() =
531 create_agent(tls_security, max_idle_connections, timeout_seconds)?;
532 Ok(())
533 }
534
535 /// Sets the URL for the NetHSM connection.
536 ///
537 /// # Examples
538 ///
539 /// ```
540 /// use nethsm::{Connection, ConnectionSecurity, NetHsm, Url};
541 ///
542 /// # fn main() -> testresult::TestResult {
543 /// // Create a new connection for a NetHSM at "https://example.org"
544 /// let nethsm = NetHsm::new(
545 /// Connection::new(
546 /// "https://example.org/api/v1".try_into()?,
547 /// ConnectionSecurity::Unsafe,
548 /// ),
549 /// None,
550 /// None,
551 /// None,
552 /// )?;
553 ///
554 /// // change the url to something else
555 /// nethsm.set_url(Url::new("https://other.org/api/v1")?);
556 /// # Ok(())
557 /// # }
558 /// ```
559 pub fn set_url(&self, url: Url) {
560 *self.url.borrow_mut() = url;
561 }
562
563 /// Adds [`Credentials`] to the list of available ones.
564 ///
565 /// # Examples
566 ///
567 /// ```
568 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
569 ///
570 /// # fn main() -> testresult::TestResult {
571 /// let nethsm = NetHsm::new(
572 /// Connection::new(
573 /// "https://example.org/api/v1".try_into()?,
574 /// ConnectionSecurity::Unsafe,
575 /// ),
576 /// None,
577 /// None,
578 /// None,
579 /// )?;
580 ///
581 /// // add credentials
582 /// nethsm.add_credentials(Credentials::new(
583 /// "admin".parse()?,
584 /// Some(Passphrase::new("passphrase".to_string())),
585 /// ));
586 /// nethsm.add_credentials(Credentials::new(
587 /// "user1".parse()?,
588 /// Some(Passphrase::new("other_passphrase".to_string())),
589 /// ));
590 /// nethsm.add_credentials(Credentials::new("user2".parse()?, None));
591 /// # Ok(())
592 /// # }
593 /// ```
594 pub fn add_credentials(&self, credentials: Credentials) {
595 // remove any previously existing credentials (User IDs are unique)
596 self.remove_credentials(&credentials.user_id);
597 self.credentials
598 .borrow_mut()
599 .insert(credentials.user_id.clone(), credentials);
600 }
601
602 /// Removes [`Credentials`] from the list of available and currently used ones.
603 ///
604 /// Removes [`Credentials`] from the list of available ones and if identical unsets the
605 /// ones used for further authentication as well.
606 ///
607 /// # Examples
608 ///
609 /// ```
610 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
611 ///
612 /// # fn main() -> testresult::TestResult {
613 /// let nethsm = NetHsm::new(
614 /// Connection::new(
615 /// "https://example.org/api/v1".try_into()?,
616 /// ConnectionSecurity::Unsafe,
617 /// ),
618 /// Some(Credentials::new(
619 /// "admin".parse()?,
620 /// Some(Passphrase::new("passphrase".to_string())),
621 /// )),
622 /// None,
623 /// None,
624 /// )?;
625 ///
626 /// // remove credentials
627 /// nethsm.remove_credentials(&"admin".parse()?);
628 /// # Ok(())
629 /// # }
630 /// ```
631 pub fn remove_credentials(&self, user_id: &UserId) {
632 self.credentials.borrow_mut().remove(user_id);
633 if self
634 .current_credentials
635 .borrow()
636 .as_ref()
637 .is_some_and(|id| id == user_id)
638 {
639 *self.current_credentials.borrow_mut() = None
640 }
641 }
642
643 /// Sets [`Credentials`] to use for the next connection.
644 ///
645 /// # Errors
646 ///
647 /// An [`Error`] is returned if no [`Credentials`] with the [`UserId`] `user_id` can be found.
648 ///
649 /// # Examples
650 ///
651 /// ```
652 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
653 ///
654 /// # fn main() -> testresult::TestResult {
655 /// let nethsm = NetHsm::new(
656 /// Connection::new(
657 /// "https://example.org/api/v1".try_into()?,
658 /// ConnectionSecurity::Unsafe,
659 /// ),
660 /// None,
661 /// None,
662 /// None,
663 /// )?;
664 ///
665 /// // add credentials
666 /// nethsm.add_credentials(Credentials::new(
667 /// "admin".parse()?,
668 /// Some(Passphrase::new("passphrase".to_string())),
669 /// ));
670 /// nethsm.add_credentials(Credentials::new(
671 /// "user1".parse()?,
672 /// Some(Passphrase::new("other_passphrase".to_string())),
673 /// ));
674 ///
675 /// // use admin credentials
676 /// nethsm.use_credentials(&"admin".parse()?)?;
677 ///
678 /// // use operator credentials
679 /// nethsm.use_credentials(&"user1".parse()?)?;
680 ///
681 /// // this fails, because the user has not been added yet
682 /// assert!(nethsm.use_credentials(&"user2".parse()?).is_err());
683 /// # Ok(())
684 /// # }
685 /// ```
686 pub fn use_credentials(&self, user_id: &UserId) -> Result<(), Error> {
687 if self.credentials.borrow().contains_key(user_id) {
688 if self.current_credentials.borrow().as_ref().is_none()
689 || self
690 .current_credentials
691 .borrow()
692 .as_ref()
693 .is_some_and(|id| id != user_id)
694 {
695 *self.current_credentials.borrow_mut() = Some(user_id.to_owned());
696 }
697 } else {
698 return Err(Error::Default(format!(
699 "The credentials for User ID \"{user_id}\" need to be added before they can be used!"
700 )));
701 }
702 Ok(())
703 }
704
705 /// Provisions a NetHSM.
706 ///
707 /// [Provisioning] is the initial setup step for a NetHSM.
708 /// It sets the `unlock_passphrase`, which is used to [`unlock`][`NetHsm::unlock`] a device in
709 /// [`Locked`][`SystemState::Locked`] [state], the initial `admin_passphrase` for the
710 /// default [`Administrator`][`UserRole::Administrator`] account ("admin") and the
711 /// `system_time`. The unlock passphrase can later on be changed using
712 /// [`set_unlock_passphrase`][`NetHsm::set_unlock_passphrase`] and the admin passphrase using
713 /// [`set_user_passphrase`][`NetHsm::set_user_passphrase`].
714 ///
715 /// For this call no [`Credentials`] are required and if any are configured, they are ignored.
716 ///
717 /// # Errors
718 ///
719 /// Returns an [`Error::Api`] if provisioning fails:
720 /// * the NetHSM is not in [`Unprovisioned`][`SystemState::Unprovisioned`] [state]
721 /// * the provided data is malformed
722 ///
723 /// # Examples
724 ///
725 /// ```no_run
726 /// use chrono::Utc;
727 /// use nethsm::{Connection, ConnectionSecurity, NetHsm, Passphrase};
728 ///
729 /// # fn main() -> testresult::TestResult {
730 /// // no initial credentials are required
731 /// let nethsm = NetHsm::new(
732 /// Connection::new(
733 /// "https://example.org/api/v1".try_into()?,
734 /// ConnectionSecurity::Unsafe,
735 /// ),
736 /// None,
737 /// None,
738 /// None,
739 /// )?;
740 ///
741 /// // provision the NetHSM
742 /// nethsm.provision(
743 /// Passphrase::new("unlock-the-device".to_string()),
744 /// Passphrase::new("admin-passphrase".to_string()),
745 /// Utc::now(),
746 /// )?;
747 /// # Ok(())
748 /// # }
749 /// ```
750 /// [Provisioning]: https://docs.nitrokey.com/nethsm/getting-started#provisioning
751 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
752 pub fn provision(
753 &self,
754 unlock_passphrase: Passphrase,
755 admin_passphrase: Passphrase,
756 system_time: DateTime<Utc>,
757 ) -> Result<(), Error> {
758 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
759 provision_post(
760 &self.create_connection_config(),
761 ProvisionRequestData::new(
762 unlock_passphrase.expose_owned(),
763 admin_passphrase.expose_owned(),
764 system_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
765 ),
766 )
767 .map_err(|error| {
768 Error::Api(format!(
769 "Provisioning failed: {}",
770 NetHsmApiError::from(error)
771 ))
772 })?;
773 Ok(())
774 }
775
776 /// Returns whether the NetHSM is in [`Unprovisioned`][`SystemState::Unprovisioned`] or
777 /// [`Locked`][`SystemState::Locked`] [state].
778 ///
779 /// For this call no [`Credentials`] are required and if any are configured, they are ignored.
780 ///
781 /// # Errors
782 ///
783 /// Returns an [`Error::Api`] if the information can not be retrieved or the NetHSM is in
784 /// [`Operational`][`SystemState::Operational`] [state].
785 ///
786 /// # Examples
787 ///
788 /// ```no_run
789 /// use nethsm::{Connection, ConnectionSecurity, NetHsm};
790 ///
791 /// # fn main() -> testresult::TestResult {
792 /// // no initial credentials are required
793 /// let nethsm = NetHsm::new(
794 /// Connection::new(
795 /// "https://example.org/api/v1".try_into()?,
796 /// ConnectionSecurity::Unsafe,
797 /// ),
798 /// None,
799 /// None,
800 /// None,
801 /// )?;
802 ///
803 /// // check whether the NetHSM is locked or unprovisioned
804 /// assert!(nethsm.alive().is_ok());
805 /// # Ok(())
806 /// # }
807 /// ```
808 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
809 pub fn alive(&self) -> Result<(), Error> {
810 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
811 health_alive_get(&self.create_connection_config()).map_err(|error| {
812 Error::Api(format!(
813 "Retrieving alive status failed: {}",
814 NetHsmApiError::from(error)
815 ))
816 })?;
817 Ok(())
818 }
819
820 /// Returns whether the NetHSM is in [`Operational`][`SystemState::Operational`] [state].
821 ///
822 /// For this call no [`Credentials`] are required and if any are configured, they are ignored.
823 ///
824 /// # Errors
825 ///
826 /// Returns an [`Error::Api`] if the information can not be retrieved or the NetHSM is in
827 /// [`Unprovisioned`][`SystemState::Unprovisioned`] or [`Locked`][`SystemState::Locked`]
828 /// [state].
829 ///
830 /// # Examples
831 ///
832 /// ```no_run
833 /// use nethsm::{Connection, ConnectionSecurity, NetHsm};
834 ///
835 /// # fn main() -> testresult::TestResult {
836 /// // no initial credentials are required
837 /// let nethsm = NetHsm::new(
838 /// Connection::new(
839 /// "https://example.org/api/v1".try_into()?,
840 /// ConnectionSecurity::Unsafe,
841 /// ),
842 /// None,
843 /// None,
844 /// None,
845 /// )?;
846 ///
847 /// // check whether the NetHSM is operational
848 /// assert!(nethsm.ready().is_ok());
849 /// # Ok(())
850 /// # }
851 /// ```
852 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
853 pub fn ready(&self) -> Result<(), Error> {
854 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
855 health_ready_get(&self.create_connection_config()).map_err(|error| {
856 Error::Api(format!(
857 "Retrieving ready status failed: {}",
858 NetHsmApiError::from(error)
859 ))
860 })?;
861 Ok(())
862 }
863
864 /// Returns the system [state] of the NetHSM.
865 ///
866 /// Returns a variant of [`SystemState`], which describes the [state] a NetHSM is currently in.
867 ///
868 /// For this call no [`Credentials`] are required and if any are configured, they are ignored.
869 ///
870 /// # Errors
871 ///
872 /// Returns an [`Error::Api`] if the [state] information can not be retrieved.
873 ///
874 /// # Examples
875 ///
876 /// ```no_run
877 /// use nethsm::{Connection, ConnectionSecurity, NetHsm};
878 ///
879 /// # fn main() -> testresult::TestResult {
880 /// // no initial credentials are required
881 /// let nethsm = NetHsm::new(
882 /// Connection::new(
883 /// "https://example.org/api/v1".try_into()?,
884 /// ConnectionSecurity::Unsafe,
885 /// ),
886 /// None,
887 /// None,
888 /// None,
889 /// )?;
890 ///
891 /// // retrieve the state
892 /// println!("{:?}", nethsm.state()?);
893 /// # Ok(())
894 /// # }
895 /// ```
896 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
897 pub fn state(&self) -> Result<SystemState, Error> {
898 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
899 let health_state = health_state_get(&self.create_connection_config()).map_err(|error| {
900 Error::Api(format!(
901 "Retrieving state failed: {}",
902 NetHsmApiError::from(error)
903 ))
904 })?;
905 Ok(health_state.entity.state)
906 }
907
908 /// Returns [device information] for the NetHSM.
909 ///
910 /// Returns an [`InfoData`], which provides the [device information].
911 ///
912 /// For this call no [`Credentials`] are required and if any are configured, they are ignored.
913 ///
914 /// # Errors
915 ///
916 /// Returns an [`Error::Api`] if the NetHSM [device information] can not be retrieved.
917 ///
918 /// # Examples
919 ///
920 /// ```no_run
921 /// use nethsm::{Connection, ConnectionSecurity, NetHsm};
922 ///
923 /// # fn main() -> testresult::TestResult {
924 /// // no initial credentials are required
925 /// let nethsm = NetHsm::new(
926 /// Connection::new(
927 /// "https://example.org/api/v1".try_into()?,
928 /// ConnectionSecurity::Unsafe,
929 /// ),
930 /// None,
931 /// None,
932 /// None,
933 /// )?;
934 ///
935 /// // retrieve the NetHSM info
936 /// println!("{:?}", nethsm.info()?);
937 /// # Ok(())
938 /// # }
939 /// ```
940 /// [device information]: https://docs.nitrokey.com/nethsm/administration#device-information
941 pub fn info(&self) -> Result<InfoData, Error> {
942 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
943 let info = info_get(&self.create_connection_config()).map_err(|error| {
944 Error::Api(format!(
945 "Retrieving device information failed: {}",
946 NetHsmApiError::from(error)
947 ))
948 })?;
949 Ok(info.entity)
950 }
951
952 /// Returns metrics for the NetHSM.
953 ///
954 /// Returns a [`Value`][`serde_json::Value`] which provides [metrics] for the NetHSM.
955 ///
956 /// This call requires using [`Credentials`] of a user in the [`Metrics`][`UserRole::Metrics`]
957 /// [role].
958 ///
959 /// # Errors
960 ///
961 /// Returns an [`Error::Api`] if the NetHSM [metrics] can not be retrieved:
962 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
963 /// * the used [`Credentials`] are not correct
964 /// * the used [`Credentials`] are not that of a user in the [`Metrics`][`UserRole::Metrics`]
965 /// [role]
966 ///
967 /// # Examples
968 ///
969 /// ```no_run
970 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
971 ///
972 /// # fn main() -> testresult::TestResult {
973 /// // create a connection with a system-wide user in the Metrics role
974 /// let nethsm = NetHsm::new(
975 /// Connection::new(
976 /// "https://example.org/api/v1".try_into()?,
977 /// ConnectionSecurity::Unsafe,
978 /// ),
979 /// Some(Credentials::new(
980 /// "metrics".parse()?,
981 /// Some(Passphrase::new("metrics-passphrase".to_string())),
982 /// )),
983 /// None,
984 /// None,
985 /// )?;
986 ///
987 /// // retrieve the metrics
988 /// println!("{:?}", nethsm.metrics()?);
989 /// # Ok(())
990 /// # }
991 /// ```
992 /// [metrics]: https://docs.nitrokey.com/nethsm/administration#metrics
993 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
994 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
995 pub fn metrics(&self) -> Result<Value, Error> {
996 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
997 let metrics = metrics_get(&self.create_connection_config()).map_err(|error| {
998 Error::Api(format!(
999 "Retrieving metrics failed: {}",
1000 NetHsmApiError::from(error)
1001 ))
1002 })?;
1003 Ok(metrics.entity)
1004 }
1005
1006 /// Sets the [unlock passphrase].
1007 ///
1008 /// Changes the [unlock passphrase] from `current_passphrase` to `new_passphrase`.
1009 ///
1010 /// This call requires using [`Credentials`] of a system-wide user in the
1011 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1012 ///
1013 /// # Errors
1014 ///
1015 /// Returns an [`Error::Api`] if the [unlock passphrase] can not be changed:
1016 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1017 /// * the provided `current_passphrase` is not correct
1018 /// * the used [`Credentials`] are not correct
1019 /// * the used [`Credentials`] are not that of a system-wide user in the
1020 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1021 ///
1022 /// # Examples
1023 ///
1024 /// ```no_run
1025 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1026 ///
1027 /// # fn main() -> testresult::TestResult {
1028 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1029 /// let nethsm = NetHsm::new(
1030 /// Connection::new(
1031 /// "https://example.org/api/v1".try_into()?,
1032 /// ConnectionSecurity::Unsafe,
1033 /// ),
1034 /// Some(Credentials::new(
1035 /// "admin".parse()?,
1036 /// Some(Passphrase::new("passphrase".to_string())),
1037 /// )),
1038 /// None,
1039 /// None,
1040 /// )?;
1041 /// // add a user in the Administrator role for a namespace (N-Administrator)
1042 /// nethsm.add_user(
1043 /// "Namespace1 Admin".to_string(),
1044 /// UserRole::Administrator,
1045 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1046 /// Some("namespace1~admin1".parse()?),
1047 /// )?;
1048 /// // create accompanying namespace
1049 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1050 ///
1051 /// // R-Administrators can set the unlock passphrase
1052 /// nethsm.set_unlock_passphrase(
1053 /// Passphrase::new("current-unlock-passphrase".to_string()),
1054 /// Passphrase::new("new-unlock-passphrase".to_string()),
1055 /// )?;
1056 ///
1057 /// // N-Administrators can not set the unlock passphrase
1058 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1059 /// assert!(
1060 /// nethsm
1061 /// .set_unlock_passphrase(
1062 /// Passphrase::new("current-unlock-passphrase".to_string()),
1063 /// Passphrase::new("new-unlock-passphrase".to_string()),
1064 /// )
1065 /// .is_err()
1066 /// );
1067 /// # Ok(())
1068 /// # }
1069 /// ```
1070 /// [unlock passphrase]: https://docs.nitrokey.com/nethsm/administration#unlock-passphrase
1071 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1072 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1073 pub fn set_unlock_passphrase(
1074 &self,
1075 current_passphrase: Passphrase,
1076 new_passphrase: Passphrase,
1077 ) -> Result<(), Error> {
1078 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1079 config_unlock_passphrase_put(
1080 &self.create_connection_config(),
1081 UnlockPassphraseConfig::new(
1082 new_passphrase.expose_owned(),
1083 current_passphrase.expose_owned(),
1084 ),
1085 )
1086 .map_err(|error| {
1087 Error::Api(format!(
1088 "Changing unlock passphrase failed: {}",
1089 NetHsmApiError::from(error)
1090 ))
1091 })?;
1092 Ok(())
1093 }
1094
1095 /// Returns the [boot mode].
1096 ///
1097 /// Returns a variant of [`BootMode`] which represents the NetHSM's [boot mode].
1098 ///
1099 /// This call requires using [`Credentials`] of a system-wide user in the
1100 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1101 ///
1102 /// # Errors
1103 ///
1104 /// Returns an [`Error::Api`] if the boot mode can not be retrieved:
1105 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
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::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1114 ///
1115 /// # fn main() -> testresult::TestResult {
1116 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1117 /// let nethsm = NetHsm::new(
1118 /// Connection::new(
1119 /// "https://example.org/api/v1".try_into()?,
1120 /// ConnectionSecurity::Unsafe,
1121 /// ),
1122 /// Some(Credentials::new(
1123 /// "admin".parse()?,
1124 /// Some(Passphrase::new("passphrase".to_string())),
1125 /// )),
1126 /// None,
1127 /// None,
1128 /// )?;
1129 /// // add a user in the Administrator role for a namespace (N-Administrator)
1130 /// nethsm.add_user(
1131 /// "Namespace1 Admin".to_string(),
1132 /// UserRole::Administrator,
1133 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1134 /// Some("namespace1~admin1".parse()?),
1135 /// )?;
1136 /// // create accompanying namespace
1137 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1138 ///
1139 /// // R-Administrators can retrieve the boot mode
1140 /// println!("{:?}", nethsm.get_boot_mode()?);
1141 ///
1142 /// // N-Administrators can not retrieve the boot mode
1143 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1144 /// assert!(nethsm.get_boot_mode().is_err());
1145 /// # Ok(())
1146 /// # }
1147 /// ```
1148 /// [boot mode]: https://docs.nitrokey.com/nethsm/administration#boot-mode
1149 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1150 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1151 pub fn get_boot_mode(&self) -> Result<BootMode, Error> {
1152 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1153 Ok(BootMode::from(
1154 config_unattended_boot_get(&self.create_connection_config())
1155 .map_err(|error| {
1156 Error::Api(format!(
1157 "Retrieving boot mode failed: {}",
1158 NetHsmApiError::from(error)
1159 ))
1160 })?
1161 .entity,
1162 ))
1163 }
1164
1165 /// Sets the [boot mode].
1166 ///
1167 /// Sets the NetHSM's [boot mode] based on a [`BootMode`] variant.
1168 ///
1169 /// This call requires using [`Credentials`] of a system-wide user in the
1170 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1171 ///
1172 /// # Errors
1173 ///
1174 /// Returns an [`Error::Api`] if the boot mode can not be set:
1175 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1176 /// * the used [`Credentials`] are not correct
1177 /// * the used [`Credentials`] are not that of a system-wide user in the
1178 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1179 ///
1180 /// # Examples
1181 ///
1182 /// ```no_run
1183 /// use nethsm::{
1184 /// BootMode,
1185 /// Connection,
1186 /// ConnectionSecurity,
1187 /// Credentials,
1188 /// NetHsm,
1189 /// Passphrase,
1190 /// UserRole,
1191 /// };
1192 ///
1193 /// # fn main() -> testresult::TestResult {
1194 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1195 /// let nethsm = NetHsm::new(
1196 /// Connection::new(
1197 /// "https://example.org/api/v1".try_into()?,
1198 /// ConnectionSecurity::Unsafe,
1199 /// ),
1200 /// Some(Credentials::new(
1201 /// "admin".parse()?,
1202 /// Some(Passphrase::new("passphrase".to_string())),
1203 /// )),
1204 /// None,
1205 /// None,
1206 /// )?;
1207 /// // add a user in the Administrator role for a namespace (N-Administrator)
1208 /// nethsm.add_user(
1209 /// "Namespace1 Admin".to_string(),
1210 /// UserRole::Administrator,
1211 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1212 /// Some("namespace1~admin1".parse()?),
1213 /// )?;
1214 /// // create accompanying namespace
1215 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1216 ///
1217 /// // R-Administrators can set the boot mode
1218 /// // set the boot mode to unattended
1219 /// nethsm.set_boot_mode(BootMode::Unattended)?;
1220 /// // set the boot mode to attended
1221 /// nethsm.set_boot_mode(BootMode::Attended)?;
1222 ///
1223 /// // N-Administrators can not set the boot mode
1224 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1225 /// assert!(nethsm.set_boot_mode(BootMode::Attended).is_err());
1226 /// # Ok(())
1227 /// # }
1228 /// ```
1229 /// [boot mode]: https://docs.nitrokey.com/nethsm/administration#boot-mode
1230 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1231 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1232 pub fn set_boot_mode(&self, boot_mode: BootMode) -> Result<(), Error> {
1233 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1234 config_unattended_boot_put(&self.create_connection_config(), boot_mode.into()).map_err(
1235 |error| {
1236 Error::Api(format!(
1237 "Setting boot mode failed: {}",
1238 NetHsmApiError::from(error)
1239 ))
1240 },
1241 )?;
1242 Ok(())
1243 }
1244
1245 /// Returns the TLS public key of the API.
1246 ///
1247 /// Returns the NetHSM's public key part of its [TLS certificate] which is used for
1248 /// communication with the API.
1249 ///
1250 /// This call requires using [`Credentials`] of a system-wide user in the
1251 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1252 ///
1253 /// # Errors
1254 ///
1255 /// Returns an [`Error::Api`] if the NetHSM's TLS public key can not be retrieved:
1256 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1257 /// * the used [`Credentials`] are not correct
1258 /// * the used [`Credentials`] are not that of a system-wide user in the
1259 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1260 ///
1261 /// # Examples
1262 ///
1263 /// ```no_run
1264 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1265 ///
1266 /// # fn main() -> testresult::TestResult {
1267 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1268 /// let nethsm = NetHsm::new(
1269 /// Connection::new(
1270 /// "https://example.org/api/v1".try_into()?,
1271 /// ConnectionSecurity::Unsafe,
1272 /// ),
1273 /// Some(Credentials::new(
1274 /// "admin".parse()?,
1275 /// Some(Passphrase::new("passphrase".to_string())),
1276 /// )),
1277 /// None,
1278 /// None,
1279 /// )?;
1280 /// // add a user in the Administrator role for a namespace (N-Administrator)
1281 /// nethsm.add_user(
1282 /// "Namespace1 Admin".to_string(),
1283 /// UserRole::Administrator,
1284 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1285 /// Some("namespace1~admin1".parse()?),
1286 /// )?;
1287 /// // create accompanying namespace
1288 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1289 ///
1290 /// // R-Administrators can get the TLS public key
1291 /// println!("{}", nethsm.get_tls_public_key()?);
1292 ///
1293 /// // N-Administrators can not get the TLS public key
1294 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1295 /// assert!(nethsm.get_tls_public_key().is_err());
1296 /// # Ok(())
1297 /// # }
1298 /// ```
1299 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
1300 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1301 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1302 pub fn get_tls_public_key(&self) -> Result<String, Error> {
1303 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1304 Ok(config_tls_public_pem_get(&self.create_connection_config())
1305 .map_err(|error| {
1306 Error::Api(format!(
1307 "Retrieving API TLS public key failed: {}",
1308 NetHsmApiError::from(error)
1309 ))
1310 })?
1311 .entity)
1312 }
1313
1314 /// Returns the TLS certificate of the API.
1315 ///
1316 /// Returns the NetHSM's [TLS certificate] which is used for communication with the API.
1317 ///
1318 /// This call requires using [`Credentials`] of a system-wide user in the
1319 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1320 ///
1321 /// # Errors
1322 ///
1323 /// Returns an [`Error::Api`] if the NetHSM's TLS certificate can not be retrieved:
1324 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1325 /// * the used [`Credentials`] are not correct
1326 /// * the used [`Credentials`] are not that of a system-wide user in the
1327 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1328 ///
1329 /// # Examples
1330 ///
1331 /// ```no_run
1332 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1333 ///
1334 /// # fn main() -> testresult::TestResult {
1335 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1336 /// let nethsm = NetHsm::new(
1337 /// Connection::new(
1338 /// "https://example.org/api/v1".try_into()?,
1339 /// ConnectionSecurity::Unsafe,
1340 /// ),
1341 /// Some(Credentials::new(
1342 /// "admin".parse()?,
1343 /// Some(Passphrase::new("passphrase".to_string())),
1344 /// )),
1345 /// None,
1346 /// None,
1347 /// )?;
1348 /// // add a user in the Administrator role for a namespace (N-Administrator)
1349 /// nethsm.add_user(
1350 /// "Namespace1 Admin".to_string(),
1351 /// UserRole::Administrator,
1352 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1353 /// Some("namespace1~admin1".parse()?),
1354 /// )?;
1355 /// // create accompanying namespace
1356 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1357 ///
1358 /// // R-Administrators can get the TLS certificate
1359 /// println!("{}", nethsm.get_tls_cert()?);
1360 ///
1361 /// // N-Administrators can not get the TLS certificate
1362 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1363 /// assert!(nethsm.get_tls_cert().is_err());
1364 /// # Ok(())
1365 /// # }
1366 /// ```
1367 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
1368 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1369 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1370 pub fn get_tls_cert(&self) -> Result<String, Error> {
1371 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1372 Ok(config_tls_cert_pem_get(&self.create_connection_config())
1373 .map_err(|error| {
1374 Error::Api(format!(
1375 "Retrieving API TLS certificate failed: {}",
1376 NetHsmApiError::from(error)
1377 ))
1378 })?
1379 .entity)
1380 }
1381
1382 /// Returns a Certificate Signing Request ([CSR]) for the API's [TLS certificate].
1383 ///
1384 /// Based on [`DistinguishedName`] data returns a [CSR] in [PKCS#10] format for the NetHSM's
1385 /// [TLS certificate].
1386 ///
1387 /// This call requires using [`Credentials`] of a system-wide user in the
1388 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1389 ///
1390 /// # Errors
1391 ///
1392 /// Returns an [`Error::Api`] if the [CSR] can not be retrieved:
1393 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1394 /// * the used [`Credentials`] are not correct
1395 /// * the used [`Credentials`] are not that of a system-wide user in the
1396 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1397 ///
1398 /// # Examples
1399 ///
1400 /// ```no_run
1401 /// use nethsm::{
1402 /// Connection,
1403 /// ConnectionSecurity,
1404 /// Credentials,
1405 /// DistinguishedName,
1406 /// NetHsm,
1407 /// Passphrase,
1408 /// UserRole,
1409 /// };
1410 ///
1411 /// # fn main() -> testresult::TestResult {
1412 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1413 /// let nethsm = NetHsm::new(
1414 /// Connection::new(
1415 /// "https://example.org/api/v1".try_into()?,
1416 /// ConnectionSecurity::Unsafe,
1417 /// ),
1418 /// Some(Credentials::new(
1419 /// "admin".parse()?,
1420 /// Some(Passphrase::new("passphrase".to_string())),
1421 /// )),
1422 /// None,
1423 /// None,
1424 /// )?;
1425 /// // add a user in the Administrator role for a namespace (N-Administrator)
1426 /// nethsm.add_user(
1427 /// "Namespace1 Admin".to_string(),
1428 /// UserRole::Administrator,
1429 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1430 /// Some("namespace1~admin1".parse()?),
1431 /// )?;
1432 /// // create accompanying namespace
1433 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1434 ///
1435 /// // R-Administrators can get a CSR for the TLS certificate
1436 /// println!(
1437 /// "{}",
1438 /// nethsm.get_tls_csr(DistinguishedName {
1439 /// country_name: Some("DE".to_string()),
1440 /// state_or_province_name: Some("Berlin".to_string()),
1441 /// locality_name: Some("Berlin".to_string()),
1442 /// organization_name: Some("Foobar Inc".to_string()),
1443 /// organizational_unit_name: Some("Department of Foo".to_string()),
1444 /// common_name: "Foobar Inc".to_string(),
1445 /// email_address: Some("foobar@mcfooface.com".to_string()),
1446 /// })?
1447 /// );
1448 ///
1449 /// // N-Administrators can not get a CSR for the TLS certificate
1450 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1451 /// assert!(
1452 /// nethsm
1453 /// .get_tls_csr(DistinguishedName {
1454 /// country_name: Some("DE".to_string()),
1455 /// state_or_province_name: Some("Berlin".to_string()),
1456 /// locality_name: Some("Berlin".to_string()),
1457 /// organization_name: Some("Foobar Inc".to_string()),
1458 /// organizational_unit_name: Some("Department of Foo".to_string()),
1459 /// common_name: "Foobar Inc".to_string(),
1460 /// email_address: Some("foobar@mcfooface.com".to_string()),
1461 /// })
1462 /// .is_err()
1463 /// );
1464 /// # Ok(())
1465 /// # }
1466 /// ```
1467 /// [CSR]: https://en.wikipedia.org/wiki/Certificate_signing_request
1468 /// [PKCS#10]: https://en.wikipedia.org/wiki/Certificate_signing_request#Structure_of_a_PKCS_#10_CSR
1469 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
1470 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1471 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1472 pub fn get_tls_csr(&self, distinguished_name: DistinguishedName) -> Result<String, Error> {
1473 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1474 Ok(
1475 config_tls_csr_pem_post(&self.create_connection_config(), distinguished_name)
1476 .map_err(|error| {
1477 Error::Api(format!(
1478 "Retrieving CSR for TLS certificate failed: {}",
1479 NetHsmApiError::from(error),
1480 ))
1481 })?
1482 .entity,
1483 )
1484 }
1485
1486 /// Generates a new [TLS certificate] for the API.
1487 ///
1488 /// Generates a new [TLS certificate] (used for communication with the API) based on
1489 /// `tls_key_type` and `length`.
1490 ///
1491 /// This call requires using [`Credentials`] of a system-wide user in the
1492 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1493 ///
1494 /// # Errors
1495 ///
1496 /// Returns an [`Error::Api`] if the new [TLS certificate] can not be generated:
1497 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1498 /// * the `tls_key_type` and `length` combination is not valid
1499 /// * the used [`Credentials`] are not correct
1500 /// * the used [`Credentials`] are not that of a system-wide user in the
1501 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1502 ///
1503 /// # Examples
1504 ///
1505 /// ```no_run
1506 /// use nethsm::{
1507 /// Connection,
1508 /// ConnectionSecurity,
1509 /// Credentials,
1510 /// NetHsm,
1511 /// Passphrase,
1512 /// TlsKeyType,
1513 /// UserRole,
1514 /// };
1515 ///
1516 /// # fn main() -> testresult::TestResult {
1517 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1518 /// let nethsm = NetHsm::new(
1519 /// Connection::new(
1520 /// "https://example.org/api/v1".try_into()?,
1521 /// ConnectionSecurity::Unsafe,
1522 /// ),
1523 /// Some(Credentials::new(
1524 /// "admin".parse()?,
1525 /// Some(Passphrase::new("passphrase".to_string())),
1526 /// )),
1527 /// None,
1528 /// None,
1529 /// )?;
1530 /// // add a user in the Administrator role for a namespace (N-Administrator)
1531 /// nethsm.add_user(
1532 /// "Namespace1 Admin".to_string(),
1533 /// UserRole::Administrator,
1534 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1535 /// Some("namespace1~admin1".parse()?),
1536 /// )?;
1537 /// // create accompanying namespace
1538 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1539 ///
1540 /// // R-Administrators can generate a new TLS certificate
1541 /// nethsm.generate_tls_cert(TlsKeyType::Rsa, Some(4096))?;
1542 ///
1543 /// // N-Administrators can not generate a new TLS certificate
1544 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1545 /// assert!(
1546 /// nethsm
1547 /// .generate_tls_cert(TlsKeyType::Rsa, Some(4096))
1548 /// .is_err()
1549 /// );
1550 /// # Ok(())
1551 /// # }
1552 /// ```
1553 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
1554 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1555 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1556 pub fn generate_tls_cert(
1557 &self,
1558 tls_key_type: TlsKeyType,
1559 length: Option<u32>,
1560 ) -> Result<(), Error> {
1561 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1562 // ensure the tls_key_type - length combination is valid
1563 tls_key_type_matches_length(tls_key_type, length)?;
1564 config_tls_generate_post(
1565 &self.create_connection_config(),
1566 TlsKeyGenerateRequestData {
1567 r#type: tls_key_type.into(),
1568 length: length.map(|length| length as i32),
1569 },
1570 )
1571 .map_err(|error| {
1572 Error::Api(format!(
1573 "Generating API TLS certificate failed: {}",
1574 NetHsmApiError::from(error)
1575 ))
1576 })?;
1577 Ok(())
1578 }
1579
1580 /// Sets a new [TLS certificate] for the API.
1581 ///
1582 /// Accepts a Base64 encoded [DER] certificate provided using `certificate` which is added as
1583 /// new [TLS certificate] for communication with the API.
1584 ///
1585 /// This call requires using [`Credentials`] of a system-wide user in the
1586 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1587 ///
1588 /// # Errors
1589 ///
1590 /// Returns an [`Error::Api`] if setting a new TLS certificate fails:
1591 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1592 /// * the provided `certificate` is not valid
1593 /// * the used [`Credentials`] are not correct
1594 /// * the used [`Credentials`] are not that of a system-wide user in the
1595 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1596 ///
1597 /// # Examples
1598 ///
1599 /// ```no_run
1600 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1601 ///
1602 /// # fn main() -> testresult::TestResult {
1603 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1604 /// let nethsm = NetHsm::new(
1605 /// Connection::new(
1606 /// "https://example.org/api/v1".try_into()?,
1607 /// ConnectionSecurity::Unsafe,
1608 /// ),
1609 /// Some(Credentials::new(
1610 /// "admin".parse()?,
1611 /// Some(Passphrase::new("passphrase".to_string())),
1612 /// )),
1613 /// None,
1614 /// None,
1615 /// )?;
1616 /// // add a user in the Administrator role for a namespace (N-Administrator)
1617 /// nethsm.add_user(
1618 /// "Namespace1 Admin".to_string(),
1619 /// UserRole::Administrator,
1620 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1621 /// Some("namespace1~admin1".parse()?),
1622 /// )?;
1623 /// // create accompanying namespace
1624 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1625 ///
1626 /// let cert = r#"-----BEGIN CERTIFICATE-----
1627 /// MIIBHjCBxKADAgECAghDngCv6xWIXDAKBggqhkjOPQQDAjAUMRIwEAYDVQQDDAlr
1628 /// ZXlmZW5kZXIwIBcNNzAwMTAxMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMBQxEjAQ
1629 /// BgNVBAMMCWtleWZlbmRlcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJsHIrsZ
1630 /// 6fJzrk12GK7nW6bGyTIIZiQUq0uaKbn21dgPiDCO5+iYVXAqnWu4IMVZQnkFJmte
1631 /// PRUUuM3119f8ffkwCgYIKoZIzj0EAwIDSQAwRgIhALH4fDYJ21tRecXp9IipBlil
1632 /// p+hJCj77zBvFmGYy/UnPAiEA8csj7U6BfzvK4EiQyUZa7/as+nXwj3XHU/i8LyLm
1633 /// Chw=
1634 /// -----END CERTIFICATE-----"#;
1635 ///
1636 /// // R-Administrators can set a new TLS certificate
1637 /// nethsm.set_tls_cert(cert)?;
1638 ///
1639 /// // N-Administrators can not set a new TLS certificate
1640 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1641 /// assert!(nethsm.set_tls_cert(cert).is_err());
1642 /// # Ok(())
1643 /// # }
1644 /// ```
1645 /// [DER]: https://en.wikipedia.org/wiki/X.690#DER_encoding
1646 /// [TLS certificate]: https://docs.nitrokey.com/nethsm/administration#tls-certificate
1647 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1648 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1649 pub fn set_tls_cert(&self, certificate: &str) -> Result<(), Error> {
1650 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1651 config_tls_cert_pem_put(&self.create_connection_config(), certificate).map_err(
1652 |error| {
1653 Error::Api(format!(
1654 "Setting API TLS certificate failed: {}",
1655 NetHsmApiError::from(error)
1656 ))
1657 },
1658 )?;
1659 Ok(())
1660 }
1661
1662 /// Gets the [network configuration].
1663 ///
1664 /// Retrieves the [network configuration] of the NetHSM as [`NetworkConfig`].
1665 ///
1666 /// This call requires using [`Credentials`] of a system-wide user in the
1667 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1668 ///
1669 /// # Errors
1670 ///
1671 /// Returns an [`Error::Api`] if retrieving network configuration fails:
1672 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1673 /// * the used [`Credentials`] are not correct
1674 /// * the used [`Credentials`] are not that of a system-wide user in the
1675 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1676 ///
1677 /// # Examples
1678 ///
1679 /// ```no_run
1680 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1681 ///
1682 /// # fn main() -> testresult::TestResult {
1683 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1684 /// let nethsm = NetHsm::new(
1685 /// Connection::new(
1686 /// "https://example.org/api/v1".try_into()?,
1687 /// ConnectionSecurity::Unsafe,
1688 /// ),
1689 /// Some(Credentials::new(
1690 /// "admin".parse()?,
1691 /// Some(Passphrase::new("passphrase".to_string())),
1692 /// )),
1693 /// None,
1694 /// None,
1695 /// )?;
1696 /// // add a user in the Administrator role for a namespace (N-Administrator)
1697 /// nethsm.add_user(
1698 /// "Namespace1 Admin".to_string(),
1699 /// UserRole::Administrator,
1700 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1701 /// Some("namespace1~admin1".parse()?),
1702 /// )?;
1703 /// // create accompanying namespace
1704 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1705 ///
1706 /// // R-Administrators can get the network configuration
1707 /// println!("{:?}", nethsm.get_network()?);
1708 ///
1709 /// // N-Administrators can not get the network configuration
1710 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1711 /// assert!(nethsm.get_network().is_err());
1712 /// # Ok(())
1713 /// # }
1714 /// ```
1715 /// [network configuration]: https://docs.nitrokey.com/nethsm/administration#network
1716 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1717 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1718 pub fn get_network(&self) -> Result<NetworkConfig, Error> {
1719 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1720 Ok(config_network_get(&self.create_connection_config())
1721 .map_err(|error| {
1722 Error::Api(format!(
1723 "Getting network config failed: {}",
1724 NetHsmApiError::from(error)
1725 ))
1726 })?
1727 .entity)
1728 }
1729
1730 /// Sets the [network configuration].
1731 ///
1732 /// Sets the [network configuration] of the NetHSM on the basis of a [`NetworkConfig`].
1733 ///
1734 /// This call requires using [`Credentials`] of a system-wide user in the
1735 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1736 ///
1737 /// # Errors
1738 ///
1739 /// Returns an [`Error::Api`] if setting the network configuration fails:
1740 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1741 /// * the provided `network_config` is not valid
1742 /// * the used [`Credentials`] are not correct
1743 /// * the used [`Credentials`] are not that of a system-wide user in the
1744 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1745 ///
1746 /// # Examples
1747 ///
1748 /// ```no_run
1749 /// use nethsm::{
1750 /// Connection,
1751 /// ConnectionSecurity,
1752 /// Credentials,
1753 /// NetHsm,
1754 /// NetworkConfig,
1755 /// Passphrase,
1756 /// UserRole,
1757 /// };
1758 ///
1759 /// # fn main() -> testresult::TestResult {
1760 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1761 /// let nethsm = NetHsm::new(
1762 /// Connection::new(
1763 /// "https://example.org/api/v1".try_into()?,
1764 /// ConnectionSecurity::Unsafe,
1765 /// ),
1766 /// Some(Credentials::new(
1767 /// "admin".parse()?,
1768 /// Some(Passphrase::new("passphrase".to_string())),
1769 /// )),
1770 /// None,
1771 /// None,
1772 /// )?;
1773 /// // add a user in the Administrator role for a namespace (N-Administrator)
1774 /// nethsm.add_user(
1775 /// "Namespace1 Admin".to_string(),
1776 /// UserRole::Administrator,
1777 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1778 /// Some("namespace1~admin1".parse()?),
1779 /// )?;
1780 /// // create accompanying namespace
1781 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1782 ///
1783 /// let network_config = NetworkConfig::new(
1784 /// "192.168.1.1".to_string(),
1785 /// "255.255.255.0".to_string(),
1786 /// "0.0.0.0".to_string(),
1787 /// );
1788 ///
1789 /// // R-Administrators can set the network configuration
1790 /// nethsm.set_network(network_config.clone())?;
1791 ///
1792 /// // N-Administrators can not set the network configuration
1793 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1794 /// assert!(nethsm.set_network(network_config).is_err());
1795 /// # Ok(())
1796 /// # }
1797 /// ```
1798 /// [network configuration]: https://docs.nitrokey.com/nethsm/administration#network
1799 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1800 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1801 pub fn set_network(&self, network_config: NetworkConfig) -> Result<(), Error> {
1802 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1803 config_network_put(&self.create_connection_config(), network_config).map_err(|error| {
1804 Error::Api(format!(
1805 "Setting network config failed: {}",
1806 NetHsmApiError::from(error)
1807 ))
1808 })?;
1809 Ok(())
1810 }
1811
1812 /// Gets the current [time].
1813 ///
1814 /// This call requires using [`Credentials`] of a system-wide user in the
1815 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1816 ///
1817 /// # Errors
1818 ///
1819 /// Returns an [`Error::Api`] if retrieving [time] fails:
1820 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1821 /// * the used [`Credentials`] are not correct
1822 /// * the used [`Credentials`] are not that of a system-wide user in the
1823 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1824 ///
1825 /// # Examples
1826 ///
1827 /// ```no_run
1828 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1829 ///
1830 /// # fn main() -> testresult::TestResult {
1831 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1832 /// let nethsm = NetHsm::new(
1833 /// Connection::new(
1834 /// "https://example.org/api/v1".try_into()?,
1835 /// ConnectionSecurity::Unsafe,
1836 /// ),
1837 /// Some(Credentials::new(
1838 /// "admin".parse()?,
1839 /// Some(Passphrase::new("passphrase".to_string())),
1840 /// )),
1841 /// None,
1842 /// None,
1843 /// )?;
1844 /// // add a user in the Administrator role for a namespace (N-Administrator)
1845 /// nethsm.add_user(
1846 /// "Namespace1 Admin".to_string(),
1847 /// UserRole::Administrator,
1848 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1849 /// Some("namespace1~admin1".parse()?),
1850 /// )?;
1851 /// // create accompanying namespace
1852 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1853 ///
1854 /// // R-Administrators can get the time
1855 /// println!("{:?}", nethsm.get_time()?);
1856 ///
1857 /// // N-Administrators can not get the time
1858 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1859 /// assert!(nethsm.get_time().is_err());
1860 /// # Ok(())
1861 /// # }
1862 /// ```
1863 /// [time]: https://docs.nitrokey.com/nethsm/administration#time
1864 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1865 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1866 pub fn get_time(&self) -> Result<String, Error> {
1867 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1868 Ok(config_time_get(&self.create_connection_config())
1869 .map_err(|error| {
1870 Error::Api(format!(
1871 "Getting NetHSM system time failed: {}",
1872 NetHsmApiError::from(error)
1873 ))
1874 })?
1875 .entity
1876 .time)
1877 }
1878
1879 /// Sets the current [time].
1880 ///
1881 /// This call requires using [`Credentials`] of a system-wide user in the
1882 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1883 ///
1884 /// # Errors
1885 ///
1886 /// Returns an [`Error::Api`] if setting [time] fails:
1887 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1888 /// * the provided `time` is not valid
1889 /// * the used [`Credentials`] are not correct
1890 /// * the used [`Credentials`] are not that of a system-wide user in the
1891 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1892 ///
1893 /// # Examples
1894 ///
1895 /// ```no_run
1896 /// use chrono::Utc;
1897 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1898 ///
1899 /// # fn main() -> testresult::TestResult {
1900 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1901 /// let nethsm = NetHsm::new(
1902 /// Connection::new(
1903 /// "https://example.org/api/v1".try_into()?,
1904 /// ConnectionSecurity::Unsafe,
1905 /// ),
1906 /// Some(Credentials::new(
1907 /// "admin".parse()?,
1908 /// Some(Passphrase::new("passphrase".to_string())),
1909 /// )),
1910 /// None,
1911 /// None,
1912 /// )?;
1913 /// // add a user in the Administrator role for a namespace (N-Administrator)
1914 /// nethsm.add_user(
1915 /// "Namespace1 Admin".to_string(),
1916 /// UserRole::Administrator,
1917 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1918 /// Some("namespace1~admin1".parse()?),
1919 /// )?;
1920 /// // create accompanying namespace
1921 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1922 ///
1923 /// // R-Administrators can set the time
1924 /// nethsm.set_time(Utc::now())?;
1925 ///
1926 /// // N-Administrators can not set the time
1927 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1928 /// assert!(nethsm.set_time(Utc::now()).is_err());
1929 /// # Ok(())
1930 /// # }
1931 /// ```
1932 /// [time]: https://docs.nitrokey.com/nethsm/administration#time
1933 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
1934 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
1935 pub fn set_time(&self, time: DateTime<Utc>) -> Result<(), Error> {
1936 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
1937 config_time_put(
1938 &self.create_connection_config(),
1939 TimeConfig::new(time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)),
1940 )
1941 .map_err(|error| {
1942 Error::Api(format!(
1943 "Setting NetHSM system time failed: {}",
1944 NetHsmApiError::from(error)
1945 ))
1946 })?;
1947 Ok(())
1948 }
1949
1950 /// Gets the [logging configuration].
1951 ///
1952 /// This call requires using [`Credentials`] of a system-wide user in the
1953 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
1954 ///
1955 /// # Errors
1956 ///
1957 /// Returns an [`Error::Api`] if getting the [logging configuration] fails:
1958 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
1959 /// * the used [`Credentials`] are not correct
1960 /// * the used [`Credentials`] are not that of a system-wide user in the
1961 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
1962 ///
1963 /// # Examples
1964 ///
1965 /// ```no_run
1966 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
1967 ///
1968 /// # fn main() -> testresult::TestResult {
1969 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
1970 /// let nethsm = NetHsm::new(
1971 /// Connection::new(
1972 /// "https://example.org/api/v1".try_into()?,
1973 /// ConnectionSecurity::Unsafe,
1974 /// ),
1975 /// Some(Credentials::new(
1976 /// "admin".parse()?,
1977 /// Some(Passphrase::new("passphrase".to_string())),
1978 /// )),
1979 /// None,
1980 /// None,
1981 /// )?;
1982 /// // add a user in the Administrator role for a namespace (N-Administrator)
1983 /// nethsm.add_user(
1984 /// "Namespace1 Admin".to_string(),
1985 /// UserRole::Administrator,
1986 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
1987 /// Some("namespace1~admin1".parse()?),
1988 /// )?;
1989 /// // create accompanying namespace
1990 /// nethsm.add_namespace(&"namespace1".parse()?)?;
1991 ///
1992 /// // R-Administrators can get logging configuration
1993 /// println!("{:?}", nethsm.get_logging()?);
1994 ///
1995 /// // N-Administrators can not get logging configuration
1996 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
1997 /// assert!(nethsm.get_logging().is_err());
1998 /// # Ok(())
1999 /// # }
2000 /// ```
2001 /// [logging configuration]: https://docs.nitrokey.com/nethsm/administration#logging
2002 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2003 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2004 pub fn get_logging(&self) -> Result<LoggingConfig, Error> {
2005 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2006 Ok(config_logging_get(&self.create_connection_config())
2007 .map_err(|error| {
2008 Error::Api(format!(
2009 "Getting logging config failed: {}",
2010 NetHsmApiError::from(error)
2011 ))
2012 })?
2013 .entity)
2014 }
2015
2016 /// Sets the [logging configuration].
2017 ///
2018 /// Sets the NetHSM's [logging configuration] by providing `ip_address` and `port` of a host to
2019 /// send logs to. The log level is configured using `log_level`.
2020 ///
2021 /// This call requires using [`Credentials`] of a system-wide user in the
2022 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2023 ///
2024 /// # Errors
2025 ///
2026 /// Returns an [`Error::Api`] if setting the logging configuration fails:
2027 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2028 /// * the provided `ip_address`, `port` or `log_level` are not valid
2029 /// * the used [`Credentials`] are not correct
2030 /// * the used [`Credentials`] are not that of a system-wide user in the
2031 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2032 ///
2033 /// # Examples
2034 ///
2035 /// ```no_run
2036 /// use std::net::Ipv4Addr;
2037 ///
2038 /// use nethsm::{
2039 /// Connection,
2040 /// ConnectionSecurity,
2041 /// Credentials,
2042 /// LogLevel,
2043 /// NetHsm,
2044 /// Passphrase,
2045 /// UserRole,
2046 /// };
2047 ///
2048 /// # fn main() -> testresult::TestResult {
2049 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2050 /// let nethsm = NetHsm::new(
2051 /// Connection::new(
2052 /// "https://example.org/api/v1".try_into()?,
2053 /// ConnectionSecurity::Unsafe,
2054 /// ),
2055 /// Some(Credentials::new(
2056 /// "admin".parse()?,
2057 /// Some(Passphrase::new("passphrase".to_string())),
2058 /// )),
2059 /// None,
2060 /// None,
2061 /// )?;
2062 /// // add a user in the Administrator role for a namespace (N-Administrator)
2063 /// nethsm.add_user(
2064 /// "Namespace1 Admin".to_string(),
2065 /// UserRole::Administrator,
2066 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2067 /// Some("namespace1~admin1".parse()?),
2068 /// )?;
2069 /// // create accompanying namespace
2070 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2071 ///
2072 /// // R-Administrators can set logging configuration
2073 /// nethsm.set_logging(Ipv4Addr::new(192, 168, 1, 2), 513, LogLevel::Debug)?;
2074 ///
2075 /// // N-Administrators can not set logging configuration
2076 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2077 /// assert!(
2078 /// nethsm
2079 /// .set_logging(Ipv4Addr::new(192, 168, 1, 2), 513, LogLevel::Debug)
2080 /// .is_err()
2081 /// );
2082 /// # Ok(())
2083 /// # }
2084 /// ```
2085 /// [logging configuration]: https://docs.nitrokey.com/nethsm/administration#logging
2086 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2087 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2088 pub fn set_logging(
2089 &self,
2090 ip_address: Ipv4Addr,
2091 port: u32,
2092 log_level: LogLevel,
2093 ) -> Result<(), Error> {
2094 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2095 let ip_address = ip_address.to_string();
2096 config_logging_put(
2097 &self.create_connection_config(),
2098 LoggingConfig::new(ip_address, port as i32, log_level.into()),
2099 )
2100 .map_err(|error| {
2101 Error::Api(format!(
2102 "Setting logging config failed: {}",
2103 NetHsmApiError::from(error)
2104 ))
2105 })?;
2106 Ok(())
2107 }
2108
2109 /// Sets the [backup] passphrase.
2110 ///
2111 /// Sets `current_passphrase` to `new_passphrase`, which changes the [backup] passphrase for the
2112 /// NetHSM.
2113 ///
2114 /// This call requires using [`Credentials`] of a system-wide user in the
2115 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2116 ///
2117 /// # Errors
2118 ///
2119 /// Returns an [`Error::Api`] if setting the backup passphrase fails:
2120 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2121 /// * the provided `current_passphrase` is not correct
2122 /// * the used [`Credentials`] are not correct
2123 /// * the used [`Credentials`] are not that of a system-wide user in the
2124 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2125 ///
2126 /// # Examples
2127 ///
2128 /// ```no_run
2129 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2130 ///
2131 /// # fn main() -> testresult::TestResult {
2132 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2133 /// let nethsm = NetHsm::new(
2134 /// Connection::new(
2135 /// "https://example.org/api/v1".try_into()?,
2136 /// ConnectionSecurity::Unsafe,
2137 /// ),
2138 /// Some(Credentials::new(
2139 /// "admin".parse()?,
2140 /// Some(Passphrase::new("passphrase".to_string())),
2141 /// )),
2142 /// None,
2143 /// None,
2144 /// )?;
2145 /// // add a user in the Administrator role for a namespace (N-Administrator)
2146 /// nethsm.add_user(
2147 /// "Namespace1 Admin".to_string(),
2148 /// UserRole::Administrator,
2149 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2150 /// Some("namespace1~admin1".parse()?),
2151 /// )?;
2152 /// // create accompanying namespace
2153 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2154 ///
2155 /// // R-Administrators can set the backup passphrase
2156 /// nethsm.set_backup_passphrase(
2157 /// Passphrase::new("current-backup-passphrase".to_string()),
2158 /// Passphrase::new("new-backup-passphrase".to_string()),
2159 /// )?;
2160 ///
2161 /// // N-Administrators can not set logging configuration
2162 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2163 /// assert!(
2164 /// nethsm
2165 /// .set_backup_passphrase(
2166 /// Passphrase::new("new-backup-passphrase".to_string()),
2167 /// Passphrase::new("current-backup-passphrase".to_string()),
2168 /// )
2169 /// .is_err()
2170 /// );
2171 /// # Ok(())
2172 /// # }
2173 /// ```
2174 /// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
2175 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2176 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2177 pub fn set_backup_passphrase(
2178 &self,
2179 current_passphrase: Passphrase,
2180 new_passphrase: Passphrase,
2181 ) -> Result<(), Error> {
2182 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2183 config_backup_passphrase_put(
2184 &self.create_connection_config(),
2185 BackupPassphraseConfig::new(
2186 new_passphrase.expose_owned(),
2187 current_passphrase.expose_owned(),
2188 ),
2189 )
2190 .map_err(|error| {
2191 Error::Api(format!(
2192 "Setting backup passphrase failed: {}",
2193 NetHsmApiError::from(error),
2194 ))
2195 })?;
2196 Ok(())
2197 }
2198
2199 /// Creates a [backup].
2200 ///
2201 /// Triggers the creation and download of a [backup] of the NetHSM.
2202 /// **NOTE**: Before creating the first [backup], the [backup] passphrase must be set using
2203 /// [`set_backup_passphrase`][`NetHsm::set_backup_passphrase`].
2204 ///
2205 /// This call requires using [`Credentials`] of a user in the [`Backup`][`UserRole::Backup`]
2206 /// [role].
2207 ///
2208 /// # Errors
2209 ///
2210 /// Returns an [`Error::Api`] if creating a [backup] fails:
2211 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2212 /// * the used [`Credentials`] are not correct
2213 /// * the used [`Credentials`] are not that of a user in the [`Backup`][`UserRole::Backup`]
2214 /// [role]
2215 /// * the [backup] passphrase has not yet been set
2216 ///
2217 /// # Examples
2218 ///
2219 /// ```no_run
2220 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
2221 ///
2222 /// # fn main() -> testresult::TestResult {
2223 /// // create a connection with a user in the Backup role
2224 /// let nethsm = NetHsm::new(
2225 /// Connection::new(
2226 /// "https://example.org/api/v1".try_into()?,
2227 /// ConnectionSecurity::Unsafe,
2228 /// ),
2229 /// Some(Credentials::new(
2230 /// "backup1".parse()?,
2231 /// Some(Passphrase::new("passphrase".to_string())),
2232 /// )),
2233 /// None,
2234 /// None,
2235 /// )?;
2236 ///
2237 /// // create a backup and write it to file
2238 /// std::fs::write("nethsm.bkp", nethsm.backup()?)?;
2239 /// # Ok(())
2240 /// # }
2241 /// ```
2242 /// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
2243 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2244 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2245 pub fn backup(&self) -> Result<Vec<u8>, Error> {
2246 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2247 Ok(system_backup_post(&self.create_connection_config())
2248 .map_err(|error| {
2249 Error::Api(format!(
2250 "Getting backup failed: {}",
2251 NetHsmApiError::from(error)
2252 ))
2253 })?
2254 .entity)
2255 }
2256
2257 /// Triggers a [factory reset].
2258 ///
2259 /// Triggers a [factory reset] of the NetHSM.
2260 /// **WARNING**: This action deletes all user and system data! Make sure to create a [backup]
2261 /// using [`backup`][`NetHsm::backup`] first!
2262 ///
2263 /// This call requires using [`Credentials`] of a system-wide user in the
2264 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2265 ///
2266 /// # Errors
2267 ///
2268 /// Returns an [`Error::Api`] if resetting the NetHSM fails:
2269 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2270 /// * the used [`Credentials`] are not correct
2271 /// * the used [`Credentials`] are not that of a system-wide user in the
2272 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2273 ///
2274 /// # Examples
2275 ///
2276 /// ```no_run
2277 /// use nethsm::{
2278 /// Connection,
2279 /// ConnectionSecurity,
2280 /// Credentials,
2281 /// NetHsm,
2282 /// Passphrase,
2283 /// SystemState,
2284 /// UserRole,
2285 /// };
2286 ///
2287 /// # fn main() -> testresult::TestResult {
2288 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2289 /// let nethsm = NetHsm::new(
2290 /// Connection::new(
2291 /// "https://example.org/api/v1".try_into()?,
2292 /// ConnectionSecurity::Unsafe,
2293 /// ),
2294 /// Some(Credentials::new(
2295 /// "admin".parse()?,
2296 /// Some(Passphrase::new("passphrase".to_string())),
2297 /// )),
2298 /// None,
2299 /// None,
2300 /// )?;
2301 /// // add a user in the Administrator role for a namespace (N-Administrator)
2302 /// nethsm.add_user(
2303 /// "Namespace1 Admin".to_string(),
2304 /// UserRole::Administrator,
2305 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2306 /// Some("namespace1~admin1".parse()?),
2307 /// )?;
2308 /// // create accompanying namespace
2309 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2310 ///
2311 /// // N-Administrators can not trigger factory reset
2312 /// assert_eq!(nethsm.state()?, SystemState::Operational);
2313 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2314 /// assert!(nethsm.factory_reset().is_err());
2315 ///
2316 /// // R-Administrators are able to trigger a factory reset
2317 /// assert_eq!(nethsm.state()?, SystemState::Operational);
2318 /// nethsm.use_credentials(&"admin".parse()?)?;
2319 /// nethsm.factory_reset()?;
2320 /// assert_eq!(nethsm.state()?, SystemState::Unprovisioned);
2321 /// # Ok(())
2322 /// # }
2323 /// ```
2324 /// [factory reset]: https://docs.nitrokey.com/nethsm/administration#reset-to-factory-defaults
2325 /// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
2326 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2327 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2328 pub fn factory_reset(&self) -> Result<(), Error> {
2329 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2330 system_factory_reset_post(&self.create_connection_config()).map_err(|error| {
2331 Error::Api(format!(
2332 "Factory reset failed: {}",
2333 NetHsmApiError::from(error)
2334 ))
2335 })?;
2336 Ok(())
2337 }
2338
2339 /// Restores NetHSM from [backup].
2340 ///
2341 /// [Restores] a NetHSM from a [backup], by providing a `backup_passphrase` (see
2342 /// [`set_backup_passphrase`][`NetHsm::set_backup_passphrase`]) a new `system_time` for the
2343 /// NetHSM and a backup file (created using [`backup`][`NetHsm::backup`]).
2344 ///
2345 /// The NetHSM must be in [`Operational`][`SystemState::Operational`] or
2346 /// [`Unprovisioned`][`SystemState::Unprovisioned`] [state].
2347 ///
2348 /// Any existing user data is safely removed and replaced by that of the [backup], after which
2349 /// the NetHSM ends up in [`Locked`][`SystemState::Locked`] [state].
2350 /// If the NetHSM is in [`Unprovisioned`][`SystemState::Unprovisioned`] [state], additionally
2351 /// the system configuration from the backup is applied and leads to a
2352 /// [`reboot`][`NetHsm::reboot`] of the NetHSM.
2353 ///
2354 /// This call requires using [`Credentials`] of a system-wide user in the
2355 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2356 ///
2357 /// # Errors
2358 ///
2359 /// Returns an [`Error::Api`] if restoring the NetHSM from [backup] fails:
2360 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] or
2361 /// [`Unprovisioned`][`SystemState::Unprovisioned`] [state]
2362 /// * the used [`Credentials`] are not correct
2363 /// * the used [`Credentials`] are not that of a system-wide user in the
2364 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2365 ///
2366 /// # Examples
2367 ///
2368 /// ```no_run
2369 /// use chrono::Utc;
2370 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2371 ///
2372 /// #
2373 /// # fn main() -> testresult::TestResult {
2374 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2375 /// let nethsm = NetHsm::new(
2376 /// Connection::new(
2377 /// "https://example.org/api/v1".try_into()?,
2378 /// ConnectionSecurity::Unsafe,
2379 /// ),
2380 /// Some(Credentials::new(
2381 /// "admin".parse()?,
2382 /// Some(Passphrase::new("passphrase".to_string())),
2383 /// )),
2384 /// None,
2385 /// None,
2386 /// )?;
2387 /// // add a user in the Administrator role for a namespace (N-Administrator)
2388 /// nethsm.add_user(
2389 /// "Namespace1 Admin".to_string(),
2390 /// UserRole::Administrator,
2391 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2392 /// Some("namespace1~admin1".parse()?),
2393 /// )?;
2394 /// // create accompanying namespace
2395 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2396 ///
2397 /// // N-Administrators can not restore from backup
2398 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2399 /// assert!(
2400 /// nethsm
2401 /// .restore(
2402 /// Passphrase::new("backup-passphrase".to_string()),
2403 /// Utc::now(),
2404 /// std::fs::read("nethsm.bkp")?,
2405 /// )
2406 /// .is_err()
2407 /// );
2408 ///
2409 /// // R-Administrators can restore from backup
2410 /// nethsm.use_credentials(&"admin".parse()?)?;
2411 /// nethsm.restore(
2412 /// Passphrase::new("backup-passphrase".to_string()),
2413 /// Utc::now(),
2414 /// std::fs::read("nethsm.bkp")?,
2415 /// )?;
2416 /// # Ok(())
2417 /// # }
2418 /// ```
2419 /// [Restores]: https://docs.nitrokey.com/nethsm/administration#restore
2420 /// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
2421 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2422 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2423 pub fn restore(
2424 &self,
2425 backup_passphrase: Passphrase,
2426 system_time: DateTime<Utc>,
2427 backup: Vec<u8>,
2428 ) -> Result<(), Error> {
2429 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2430 system_restore_post(
2431 &self.create_connection_config(),
2432 Some(nethsm_sdk_rs::models::RestoreRequestArguments {
2433 backup_passphrase: Some(backup_passphrase.expose_owned()),
2434 system_time: Some(system_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)),
2435 }),
2436 Some(backup),
2437 )
2438 .map_err(|error| {
2439 Error::Api(format!(
2440 "Restoring backup failed: {}",
2441 NetHsmApiError::from(error)
2442 ))
2443 })?;
2444 Ok(())
2445 }
2446
2447 /// Locks the NetHSM.
2448 ///
2449 /// Locks the NetHSM and sets its [state] to [`Locked`][`SystemState::Locked`].
2450 ///
2451 /// This call requires using [`Credentials`] of a system-wide user in the
2452 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2453 ///
2454 /// # Errors
2455 ///
2456 /// Returns an [`Error::Api`] if locking the NetHSM fails:
2457 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2458 /// * the used [`Credentials`] are not correct
2459 /// * the used [`Credentials`] are not that of a system-wide user in the
2460 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2461 ///
2462 /// # Examples
2463 ///
2464 /// ```no_run
2465 /// use nethsm::{
2466 /// Connection,
2467 /// ConnectionSecurity,
2468 /// Credentials,
2469 /// NetHsm,
2470 /// Passphrase,
2471 /// SystemState,
2472 /// UserRole,
2473 /// };
2474 ///
2475 /// # fn main() -> testresult::TestResult {
2476 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2477 /// let nethsm = NetHsm::new(
2478 /// Connection::new(
2479 /// "https://example.org/api/v1".try_into()?,
2480 /// ConnectionSecurity::Unsafe,
2481 /// ),
2482 /// Some(Credentials::new(
2483 /// "admin".parse()?,
2484 /// Some(Passphrase::new("passphrase".to_string())),
2485 /// )),
2486 /// None,
2487 /// None,
2488 /// )?;
2489 /// // add a user in the Administrator role for a namespace (N-Administrator)
2490 /// nethsm.add_user(
2491 /// "Namespace1 Admin".to_string(),
2492 /// UserRole::Administrator,
2493 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2494 /// Some("namespace1~admin1".parse()?),
2495 /// )?;
2496 /// // create accompanying namespace
2497 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2498 ///
2499 /// assert_eq!(nethsm.state()?, SystemState::Operational);
2500 ///
2501 /// // N-Administrators can not lock the NetHSM
2502 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2503 /// assert!(nethsm.lock().is_err());
2504 ///
2505 /// // R-Administrators can lock the NetHSM
2506 /// nethsm.use_credentials(&"admin".parse()?)?;
2507 /// nethsm.lock()?;
2508 /// assert_eq!(nethsm.state()?, SystemState::Locked);
2509 /// # Ok(())
2510 /// # }
2511 /// ```
2512 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2513 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2514 pub fn lock(&self) -> Result<(), Error> {
2515 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2516 lock_post(&self.create_connection_config()).map_err(|error| {
2517 Error::Api(format!(
2518 "Locking NetHSM failed: {}",
2519 NetHsmApiError::from(error)
2520 ))
2521 })?;
2522 Ok(())
2523 }
2524
2525 /// Unlocks the NetHSM.
2526 ///
2527 /// Unlocks the NetHSM if it is in [`Locked`][`SystemState::Locked`] [state] by providing
2528 /// `unlock_passphrase` and sets its [state] to [`Operational`][`SystemState::Operational`].
2529 ///
2530 /// For this call no [`Credentials`] are required and if any are configured, they are ignored.
2531 ///
2532 /// # Errors
2533 ///
2534 /// Returns an [`Error::Api`] if unlocking the NetHSM fails:
2535 /// * the NetHSM is not in [`Locked`][`SystemState::Locked`] [state]
2536 ///
2537 /// # Examples
2538 ///
2539 /// ```no_run
2540 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, SystemState};
2541 ///
2542 /// # fn main() -> testresult::TestResult {
2543 /// // no initial [`Credentials`] are required
2544 /// let nethsm = NetHsm::new(
2545 /// Connection::new(
2546 /// "https://example.org/api/v1".try_into()?,
2547 /// ConnectionSecurity::Unsafe,
2548 /// ),
2549 /// None,
2550 /// None,
2551 /// None,
2552 /// )?;
2553 ///
2554 /// assert_eq!(nethsm.state()?, SystemState::Locked);
2555 /// // unlock the NetHSM
2556 /// nethsm.unlock(Passphrase::new("unlock-passphrase".to_string()))?;
2557 /// assert_eq!(nethsm.state()?, SystemState::Operational);
2558 /// # Ok(())
2559 /// # }
2560 /// ```
2561 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2562 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2563 pub fn unlock(&self, unlock_passphrase: Passphrase) -> Result<(), Error> {
2564 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
2565 unlock_post(
2566 &self.create_connection_config(),
2567 UnlockRequestData::new(unlock_passphrase.expose_owned()),
2568 )
2569 .map_err(|error| {
2570 Error::Api(format!(
2571 "Unlocking NetHSM failed: {}",
2572 NetHsmApiError::from(error)
2573 ))
2574 })?;
2575 Ok(())
2576 }
2577
2578 /// Retrieves [system information].
2579 ///
2580 /// Returns [system information] in the form of a [`SystemInfo`], which contains various pieces
2581 /// of information such as software version, software build, firmware version, hardware
2582 /// version, device ID and information on TPM related components such as attestation key and
2583 /// relevant PCR values.
2584 ///
2585 /// This call requires using [`Credentials`] of a system-wide user in the
2586 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2587 ///
2588 /// # Errors
2589 ///
2590 /// Returns an [`Error::Api`] if retrieving the system information fails:
2591 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2592 /// * the used [`Credentials`] are not correct
2593 /// * the used [`Credentials`] are not that of a system-wide user in the
2594 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2595 ///
2596 /// # Examples
2597 ///
2598 /// ```no_run
2599 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2600 ///
2601 /// # fn main() -> testresult::TestResult {
2602 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2603 /// let nethsm = NetHsm::new(
2604 /// Connection::new(
2605 /// "https://example.org/api/v1".try_into()?,
2606 /// ConnectionSecurity::Unsafe,
2607 /// ),
2608 /// Some(Credentials::new(
2609 /// "admin".parse()?,
2610 /// Some(Passphrase::new("passphrase".to_string())),
2611 /// )),
2612 /// None,
2613 /// None,
2614 /// )?;
2615 /// // add a user in the Administrator role for a namespace (N-Administrator)
2616 /// nethsm.add_user(
2617 /// "Namespace1 Admin".to_string(),
2618 /// UserRole::Administrator,
2619 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2620 /// Some("namespace1~admin1".parse()?),
2621 /// )?;
2622 /// // create accompanying namespace
2623 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2624 ///
2625 /// // R-Administrators can retrieve system information
2626 /// println!("{:?}", nethsm.system_info()?);
2627 ///
2628 /// // N-Administrators can not retrieve system information
2629 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2630 /// assert!(nethsm.system_info().is_err());
2631 /// # Ok(())
2632 /// # }
2633 /// ```
2634 /// [system information]: https://docs.nitrokey.com/nethsm/administration#system-information
2635 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2636 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2637 pub fn system_info(&self) -> Result<SystemInfo, Error> {
2638 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2639 Ok(system_info_get(&self.create_connection_config())
2640 .map_err(|error| {
2641 Error::Api(format!(
2642 "Retrieving system information failed: {}",
2643 NetHsmApiError::from(error)
2644 ))
2645 })?
2646 .entity)
2647 }
2648
2649 /// [Reboots] the NetHSM.
2650 ///
2651 /// [Reboots] the NetHSM, if it is in [`Operational`][`SystemState::Operational`] [state].
2652 ///
2653 /// This call requires using [`Credentials`] of a system-wide user in the
2654 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2655 ///
2656 /// # Errors
2657 ///
2658 /// Returns an [`Error::Api`] if rebooting the NetHSM fails:
2659 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2660 /// * the used [`Credentials`] are not correct
2661 /// * the used [`Credentials`] are not that of a system-wide user in the
2662 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2663 ///
2664 /// # Examples
2665 ///
2666 /// ```no_run
2667 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2668 ///
2669 /// # fn main() -> testresult::TestResult {
2670 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2671 /// let nethsm = NetHsm::new(
2672 /// Connection::new(
2673 /// "https://example.org/api/v1".try_into()?,
2674 /// ConnectionSecurity::Unsafe,
2675 /// ),
2676 /// Some(Credentials::new(
2677 /// "admin".parse()?,
2678 /// Some(Passphrase::new("passphrase".to_string())),
2679 /// )),
2680 /// None,
2681 /// None,
2682 /// )?;
2683 /// // add a user in the Administrator role for a namespace (N-Administrator)
2684 /// nethsm.add_user(
2685 /// "Namespace1 Admin".to_string(),
2686 /// UserRole::Administrator,
2687 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2688 /// Some("namespace1~admin1".parse()?),
2689 /// )?;
2690 /// // create accompanying namespace
2691 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2692 ///
2693 /// // N-Administrators can not reboot the NetHSM
2694 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2695 /// assert!(nethsm.reboot().is_err());
2696 ///
2697 /// // R-Administrators can reboot the NetHSM
2698 /// nethsm.use_credentials(&"admin".parse()?)?;
2699 /// nethsm.reboot()?;
2700 /// # Ok(())
2701 /// # }
2702 /// ```
2703 /// [Reboots]: https://docs.nitrokey.com/nethsm/administration#reboot-and-shutdown
2704 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2705 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2706 pub fn reboot(&self) -> Result<(), Error> {
2707 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2708 system_reboot_post(&self.create_connection_config()).map_err(|error| {
2709 Error::Api(format!(
2710 "Rebooting NetHSM failed: {}",
2711 NetHsmApiError::from(error)
2712 ))
2713 })?;
2714 Ok(())
2715 }
2716
2717 /// [Shuts down] the NetHSM.
2718 ///
2719 /// [Shuts down] the NetHSM, if it is in [`Operational`][`SystemState::Operational`] [state].
2720 ///
2721 /// This call requires using [`Credentials`] of a system-wide user in the
2722 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2723 ///
2724 /// # Errors
2725 ///
2726 /// Returns an [`Error::Api`] if shutting down the NetHSM fails:
2727 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2728 /// * the used [`Credentials`] are not correct
2729 /// * the used [`Credentials`] are not that of a system-wide user in the
2730 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2731 ///
2732 /// # Examples
2733 ///
2734 /// ```no_run
2735 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2736 ///
2737 /// # fn main() -> testresult::TestResult {
2738 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2739 /// let nethsm = NetHsm::new(
2740 /// Connection::new(
2741 /// "https://example.org/api/v1".try_into()?,
2742 /// ConnectionSecurity::Unsafe,
2743 /// ),
2744 /// Some(Credentials::new(
2745 /// "admin".parse()?,
2746 /// Some(Passphrase::new("passphrase".to_string())),
2747 /// )),
2748 /// None,
2749 /// None,
2750 /// )?;
2751 /// // add a user in the Administrator role for a namespace (N-Administrator)
2752 /// nethsm.add_user(
2753 /// "Namespace1 Admin".to_string(),
2754 /// UserRole::Administrator,
2755 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2756 /// Some("namespace1~admin1".parse()?),
2757 /// )?;
2758 /// // create accompanying namespace
2759 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2760 ///
2761 /// // N-Administrators can not shut down the NetHSM
2762 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2763 /// assert!(nethsm.shutdown().is_err());
2764 ///
2765 /// // R-Administrators can shut down the NetHSM
2766 /// nethsm.use_credentials(&"admin".parse()?)?;
2767 /// nethsm.shutdown()?;
2768 /// # Ok(())
2769 /// # }
2770 /// ```
2771 /// [Shuts down]: https://docs.nitrokey.com/nethsm/administration#reboot-and-shutdown
2772 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2773 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2774 pub fn shutdown(&self) -> Result<(), Error> {
2775 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2776 system_shutdown_post(&self.create_connection_config()).map_err(|error| {
2777 Error::Api(format!(
2778 "Shutting down NetHSM failed: {}",
2779 NetHsmApiError::from(error)
2780 ))
2781 })?;
2782 Ok(())
2783 }
2784
2785 /// Uploads a software update.
2786 ///
2787 /// WARNING: This function has shown flaky behavior during tests with the official container!
2788 /// Upload may have to be repeated!
2789 ///
2790 /// Uploads a [software update] to the NetHSM, if it is in
2791 /// [`Operational`][`SystemState::Operational`] [state] and returns information about the
2792 /// software update as [`SystemUpdateData`].
2793 /// Software updates can successively be installed ([`commit_update`][`NetHsm::commit_update`])
2794 /// or canceled ([`cancel_update`][`NetHsm::cancel_update`]).
2795 ///
2796 /// This call requires using [`Credentials`] of a system-wide user in the
2797 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2798 ///
2799 /// # Errors
2800 ///
2801 /// Returns an [`Error::Api`] if uploading the software update fails:
2802 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2803 /// * the used [`Credentials`] are not correct
2804 /// * the used [`Credentials`] are not that of a system-wide user in the
2805 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2806 ///
2807 /// # Examples
2808 ///
2809 /// ```no_run
2810 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2811 ///
2812 /// # fn main() -> testresult::TestResult {
2813 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2814 /// let nethsm = NetHsm::new(
2815 /// Connection::new(
2816 /// "https://example.org/api/v1".try_into()?,
2817 /// ConnectionSecurity::Unsafe,
2818 /// ),
2819 /// Some(Credentials::new(
2820 /// "admin".parse()?,
2821 /// Some(Passphrase::new("passphrase".to_string())),
2822 /// )),
2823 /// None,
2824 /// None,
2825 /// )?;
2826 /// // add a user in the Administrator role for a namespace (N-Administrator)
2827 /// nethsm.add_user(
2828 /// "Namespace1 Admin".to_string(),
2829 /// UserRole::Administrator,
2830 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2831 /// Some("namespace1~admin1".parse()?),
2832 /// )?;
2833 /// // create accompanying namespace
2834 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2835 ///
2836 /// // N-Administrators can not upload software updates to the NetHSM
2837 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2838 /// assert!(nethsm.upload_update(std::fs::read("update.bin")?).is_err());
2839 ///
2840 /// // R-Administrators can upload software updates to the NetHSM
2841 /// nethsm.use_credentials(&"admin".parse()?)?;
2842 /// println!("{:?}", nethsm.upload_update(std::fs::read("update.bin")?)?);
2843 /// # Ok(())
2844 /// # }
2845 /// ```
2846 /// [software update]: https://docs.nitrokey.com/nethsm/administration#software-update
2847 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2848 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2849 pub fn upload_update(&self, update: Vec<u8>) -> Result<SystemUpdateData, Error> {
2850 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2851 Ok(system_update_post(&self.create_connection_config(), update)
2852 .map_err(|error| {
2853 println!("error during upload");
2854 Error::Api(format!(
2855 "Uploading update failed: {}",
2856 NetHsmApiError::from(error)
2857 ))
2858 })?
2859 .entity)
2860 }
2861
2862 /// Commits an already uploaded [software update].
2863 ///
2864 /// Commits a [software update] previously uploaded to the NetHSM (using
2865 /// [`upload_update`][`NetHsm::upload_update`]), if the NetHSM is in
2866 /// [`Operational`][`SystemState::Operational`] [state].
2867 /// Successfully committing a [software update] leads to the [reboot] of the NetHSM.
2868 ///
2869 /// This call requires using [`Credentials`] of a system-wide user in the
2870 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2871 ///
2872 /// # Errors
2873 ///
2874 /// Returns an [`Error::Api`] if committing the software update fails:
2875 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2876 /// * there is no software update to commit
2877 /// * the used [`Credentials`] are not correct
2878 /// * the used [`Credentials`] are not that of a system-wide user in the
2879 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2880 ///
2881 /// # Examples
2882 ///
2883 /// ```no_run
2884 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
2885 ///
2886 /// # fn main() -> testresult::TestResult {
2887 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2888 /// let nethsm = NetHsm::new(
2889 /// Connection::new(
2890 /// "https://example.org/api/v1".try_into()?,
2891 /// ConnectionSecurity::Unsafe,
2892 /// ),
2893 /// Some(Credentials::new(
2894 /// "admin".parse()?,
2895 /// Some(Passphrase::new("passphrase".to_string())),
2896 /// )),
2897 /// None,
2898 /// None,
2899 /// )?;
2900 /// // add a user in the Administrator role for a namespace (N-Administrator)
2901 /// nethsm.add_user(
2902 /// "Namespace1 Admin".to_string(),
2903 /// UserRole::Administrator,
2904 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2905 /// Some("namespace1~admin1".parse()?),
2906 /// )?;
2907 /// // create accompanying namespace
2908 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2909 ///
2910 /// println!("{:?}", nethsm.upload_update(std::fs::read("update.bin")?)?);
2911 ///
2912 /// // N-Administrators can not commit software updates on a NetHSM
2913 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2914 /// assert!(nethsm.commit_update().is_err());
2915 ///
2916 /// // R-Administrators can commit software updates on a NetHSM
2917 /// nethsm.use_credentials(&"admin".parse()?)?;
2918 /// nethsm.commit_update()?;
2919 /// # Ok(())
2920 /// # }
2921 /// ```
2922 /// [software update]: https://docs.nitrokey.com/nethsm/administration#software-update
2923 /// [reboot]: https://docs.nitrokey.com/nethsm/administration#reboot-and-shutdown
2924 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
2925 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
2926 pub fn commit_update(&self) -> Result<(), Error> {
2927 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
2928 system_commit_update_post(&self.create_connection_config()).map_err(|error| {
2929 Error::Api(format!(
2930 "Committing update failed: {}",
2931 NetHsmApiError::from(error)
2932 ))
2933 })?;
2934 Ok(())
2935 }
2936
2937 /// Cancels an already uploaded [software update].
2938 ///
2939 /// Cancels a [software update] previously uploaded to the NetHSM (using
2940 /// [`upload_update`][`NetHsm::upload_update`]), if the NetHSM is in
2941 /// [`Operational`][`SystemState::Operational`] [state].
2942 ///
2943 /// This call requires using [`Credentials`] of a system-wide user in the
2944 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
2945 ///
2946 /// # Errors
2947 ///
2948 /// Returns an [`Error::Api`] if canceling the software update fails:
2949 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
2950 /// * there is no software update to cancel
2951 /// * the used [`Credentials`] are not correct
2952 /// * the used [`Credentials`] are not that of a system-wide user in the
2953 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
2954 ///
2955 /// # Examples
2956 ///
2957 /// ```no_run
2958 /// use nethsm::{
2959 /// Connection,
2960 /// ConnectionSecurity,
2961 /// Credentials,
2962 /// NetHsm,
2963 /// Passphrase,
2964 /// SystemState,
2965 /// UserRole,
2966 /// };
2967 ///
2968 /// # fn main() -> testresult::TestResult {
2969 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
2970 /// let nethsm = NetHsm::new(
2971 /// Connection::new(
2972 /// "https://example.org/api/v1".try_into()?,
2973 /// ConnectionSecurity::Unsafe,
2974 /// ),
2975 /// Some(Credentials::new(
2976 /// "admin".parse()?,
2977 /// Some(Passphrase::new("passphrase".to_string())),
2978 /// )),
2979 /// None,
2980 /// None,
2981 /// )?;
2982 /// // add a user in the Administrator role for a namespace (N-Administrator)
2983 /// nethsm.add_user(
2984 /// "Namespace1 Admin".to_string(),
2985 /// UserRole::Administrator,
2986 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
2987 /// Some("namespace1~admin1".parse()?),
2988 /// )?;
2989 /// // create accompanying namespace
2990 /// nethsm.add_namespace(&"namespace1".parse()?)?;
2991 ///
2992 /// println!("{:?}", nethsm.upload_update(std::fs::read("update.bin")?)?);
2993 /// assert_eq!(nethsm.state()?, SystemState::Operational);
2994 ///
2995 /// // N-Administrators can not cancel software updates on a NetHSM
2996 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
2997 /// assert!(nethsm.cancel_update().is_err());
2998 ///
2999 /// // R-Administrators can cancel software updates on a NetHSM
3000 /// nethsm.cancel_update()?;
3001 /// assert_eq!(nethsm.state()?, SystemState::Operational);
3002 /// # Ok(())
3003 /// # }
3004 /// ```
3005 /// [software update]: https://docs.nitrokey.com/nethsm/administration#software-update
3006 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3007 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3008 pub fn cancel_update(&self) -> Result<(), Error> {
3009 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
3010 system_cancel_update_post(&self.create_connection_config()).map_err(|error| {
3011 Error::Api(format!(
3012 "Cancelling update failed: {}",
3013 NetHsmApiError::from(error)
3014 ))
3015 })?;
3016 Ok(())
3017 }
3018
3019 /// Adds a new namespace.
3020 ///
3021 /// Adds a new [namespace] with the ID `namespace_id`.
3022 ///
3023 /// **WARNING**: A user in the [`Administrator`][`UserRole::Administrator`] [role] must be added
3024 /// for the [namespace] using [`add_user`][`NetHsm::add_user`] **before** creating the
3025 /// [namespace]! Otherwise there is no user to administrate the new [namespace]!
3026 ///
3027 /// This call requires using [`Credentials`] of a system-wide user in the
3028 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
3029 ///
3030 /// # Errors
3031 ///
3032 /// Returns an [`Error::Api`] if adding the namespace fails:
3033 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3034 /// * the namespace identified by `namespace_id` exists already
3035 /// * the used [`Credentials`] are not correct
3036 /// * the used [`Credentials`] are not that of a system-wide user in the
3037 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
3038 ///
3039 /// # Examples
3040 ///
3041 /// ```no_run
3042 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
3043 ///
3044 /// # fn main() -> testresult::TestResult {
3045 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3046 /// let nethsm = NetHsm::new(
3047 /// Connection::new(
3048 /// "https://example.org/api/v1".try_into()?,
3049 /// ConnectionSecurity::Unsafe,
3050 /// ),
3051 /// Some(Credentials::new(
3052 /// "admin".parse()?,
3053 /// Some(Passphrase::new("passphrase".to_string())),
3054 /// )),
3055 /// None,
3056 /// None,
3057 /// )?;
3058 ///
3059 /// // add a user in the Administrator role for a namespace (N-Administrator)
3060 /// nethsm.add_user(
3061 /// "Namespace1 Admin".to_string(),
3062 /// UserRole::Administrator,
3063 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
3064 /// Some("namespace1~admin1".parse()?),
3065 /// )?;
3066 /// // create accompanying namespace
3067 /// nethsm.add_namespace(&"namespace1".parse()?)?;
3068 ///
3069 /// // N-Administrator can not create namespaces
3070 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
3071 /// assert!(nethsm.add_namespace(&"namespace2".parse()?).is_err());
3072 /// # Ok(())
3073 /// # }
3074 /// ```
3075 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3076 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3077 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3078 pub fn add_namespace(&self, namespace_id: &NamespaceId) -> Result<(), Error> {
3079 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
3080 namespaces_namespace_id_put(&self.create_connection_config(), namespace_id.as_ref())
3081 .map_err(|error| {
3082 Error::Api(format!(
3083 "Adding namespace failed: {}",
3084 NetHsmApiError::from(error)
3085 ))
3086 })?;
3087 Ok(())
3088 }
3089
3090 /// Gets all available [namespaces].
3091 ///
3092 /// This call requires using [`Credentials`] of a system-wide user in the
3093 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
3094 ///
3095 /// # Errors
3096 ///
3097 /// Returns an [`Error::Api`] if getting the namespaces fails:
3098 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3099 /// * the used [`Credentials`] are not correct
3100 /// * the used [`Credentials`] are not that of a system-wide user in the
3101 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
3102 ///
3103 /// # Examples
3104 ///
3105 /// ```no_run
3106 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
3107 ///
3108 /// # fn main() -> testresult::TestResult {
3109 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3110 /// let nethsm = NetHsm::new(
3111 /// Connection::new(
3112 /// "https://example.org/api/v1".try_into()?,
3113 /// ConnectionSecurity::Unsafe,
3114 /// ),
3115 /// Some(Credentials::new(
3116 /// "admin".parse()?,
3117 /// Some(Passphrase::new("passphrase".to_string())),
3118 /// )),
3119 /// None,
3120 /// None,
3121 /// )?;
3122 ///
3123 /// // print list of all namespaces
3124 /// println!("{:?}", nethsm.get_namespaces()?);
3125 ///
3126 /// // add a user in the Administrator role for a namespace (N-Administrator)
3127 /// nethsm.add_user(
3128 /// "Namespace1 Admin".to_string(),
3129 /// UserRole::Administrator,
3130 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
3131 /// Some("namespace1~admin1".parse()?),
3132 /// )?;
3133 /// // create accompanying namespace
3134 /// nethsm.add_namespace(&"namespace1".parse()?)?;
3135 ///
3136 /// // N-Administrator can not get namespaces
3137 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
3138 /// assert!(nethsm.get_namespaces().is_err());
3139 /// # Ok(())
3140 /// # }
3141 /// ```
3142 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3143 /// [namespaces]: https://docs.nitrokey.com/nethsm/administration#namespaces
3144 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3145 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3146 pub fn get_namespaces(&self) -> Result<Vec<NamespaceId>, Error> {
3147 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
3148 let valid_namespaces = {
3149 let mut invalid_namespaces = Vec::new();
3150 let valid_namespaces = namespaces_get(&self.create_connection_config())
3151 .map_err(|error| {
3152 Error::Api(format!(
3153 "Getting namespaces failed: {}",
3154 NetHsmApiError::from(error)
3155 ))
3156 })?
3157 .entity
3158 .into_iter()
3159 .filter_map(|x| {
3160 if let Ok(namespace) = NamespaceId::new(x.id.clone()) {
3161 Some(namespace)
3162 } else {
3163 invalid_namespaces.push(x.id);
3164 None
3165 }
3166 })
3167 .collect::<Vec<NamespaceId>>();
3168
3169 if !invalid_namespaces.is_empty() {
3170 return Err(UserError::InvalidNamespaceIds {
3171 namespace_ids: invalid_namespaces,
3172 }
3173 .into());
3174 }
3175 valid_namespaces
3176 };
3177
3178 Ok(valid_namespaces)
3179 }
3180
3181 /// Deletes an existing [namespace].
3182 ///
3183 /// Deletes the [namespace] identified by `namespace_id`.
3184 ///
3185 /// **WARNING**: This call deletes the [namespace] and all keys in it! Make sure to create a
3186 /// [`backup`][`NetHsm::backup`]!
3187 ///
3188 /// This call requires using [`Credentials`] of a system-wide user in the
3189 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*).
3190 ///
3191 /// # Errors
3192 ///
3193 /// Returns an [`Error::Api`] if deleting the namespace fails:
3194 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3195 /// * the [namespace] identified by `namespace_id` does not exist
3196 /// * the used [`Credentials`] are not correct
3197 /// * the used [`Credentials`] are not that of a system-wide user in the
3198 /// [`Administrator`][`UserRole::Administrator`] [role] (*R-Administrator*)
3199 ///
3200 /// # Examples
3201 ///
3202 /// ```no_run
3203 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
3204 ///
3205 /// # fn main() -> testresult::TestResult {
3206 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3207 /// let nethsm = NetHsm::new(
3208 /// Connection::new(
3209 /// "https://example.org/api/v1".try_into()?,
3210 /// ConnectionSecurity::Unsafe,
3211 /// ),
3212 /// Some(Credentials::new(
3213 /// "admin".parse()?,
3214 /// Some(Passphrase::new("passphrase".to_string())),
3215 /// )),
3216 /// None,
3217 /// None,
3218 /// )?;
3219 /// // add a user in the Administrator role for a namespace (N-Administrator)
3220 /// nethsm.add_user(
3221 /// "Namespace1 Admin".to_string(),
3222 /// UserRole::Administrator,
3223 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
3224 /// Some("namespace1~admin1".parse()?),
3225 /// )?;
3226 /// // create accompanying namespace
3227 /// nethsm.add_namespace(&"namespace1".parse()?)?;
3228 ///
3229 /// // N-Administrators can not delete namespaces
3230 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
3231 /// assert!(nethsm.delete_namespace(&"namespace1".parse()?).is_err());
3232 ///
3233 /// // R-Administrators can delete namespaces
3234 /// nethsm.use_credentials(&"admin".parse()?)?;
3235 /// nethsm.delete_namespace(&"namespace1".parse()?)?;
3236 /// # Ok(())
3237 /// # }
3238 /// ```
3239 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3240 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3241 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3242 pub fn delete_namespace(&self, namespace_id: &NamespaceId) -> Result<(), Error> {
3243 self.validate_namespace_access(NamespaceSupport::Unsupported, None, None)?;
3244 namespaces_namespace_id_delete(&self.create_connection_config(), namespace_id.as_ref())
3245 .map_err(|error| {
3246 Error::Api(format!(
3247 "Deleting namespace failed: {}",
3248 NetHsmApiError::from(error)
3249 ))
3250 })?;
3251 Ok(())
3252 }
3253
3254 /// [Adds a user] and returns its User ID.
3255 ///
3256 /// A new user is created by providing a `real_name` from which a User ID is derived (optionally
3257 /// a User ID can be provided with `user_id`), a `role` which describes the user's access rights
3258 /// on the NetHSM (see [`UserRole`]) and a `passphrase`.
3259 ///
3260 /// Internally, this function also calls [`add_credentials`][`NetHsm::add_credentials`] to
3261 /// add the new user to the list of available credentials.
3262 ///
3263 /// This call requires using [`Credentials`] of a user in the
3264 /// [`Administrator`][`UserRole::Administrator`] [role].
3265 /// When adding a user to a [namespace], that does not yet exist, the caller must
3266 /// be a system-wide [`Administrator`][`UserRole::Administrator`] (*R-Administrator*).
3267 /// When adding a user to an already existing [namespace], the caller must be an
3268 /// [`Administrator`][`UserRole::Administrator`] in that [namespace]
3269 /// (*N-Administrator*).
3270 ///
3271 /// ## Namespaces
3272 ///
3273 /// New users *implicitly* inherit the [namespace] of the caller.
3274 /// A [namespace] can be provided *explicitly* by prefixing the User ID with the ID of a
3275 /// [namespace] and the `~` character (e.g. `namespace1~user1`).
3276 /// When specifying a namespace as part of the User ID and the [namespace] exists already, the
3277 /// caller must be an [`Administrator`][`UserRole::Administrator`] of that [namespace]
3278 /// (*N-Administrator*).
3279 /// When specifying a [namespace] as part of the User ID and the [namespace] does not yet exist,
3280 /// the caller must be a system-wide [`Administrator`][`UserRole::Administrator`]
3281 /// (*R-Administrator*).
3282 ///
3283 /// **NOTE**: Users in the [`Backup`][`UserRole::Backup`] and [`Metrics`][`UserRole::Metrics`]
3284 /// [role] can not be created for a [namespace], as their underlying functionality can only be
3285 /// used in a system-wide context!
3286 ///
3287 /// # Errors
3288 ///
3289 /// Returns an [`Error::Api`] if adding the user fails:
3290 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3291 /// * the provided `real_name`, `passphrase` or `user_id` are not valid
3292 /// * the provided `user_id` exists already
3293 /// * the used [`Credentials`] are not correct
3294 /// * the used [`Credentials`] are not that of a system-wide
3295 /// [`Administrator`][`UserRole::Administrator`], when adding a user to a not yet existing
3296 /// [namespace]
3297 /// * the used [`Credentials`] are not that of an [`Administrator`][`UserRole::Administrator`]
3298 /// in the [namespace] the user is about to be added to
3299 ///
3300 /// # Examples
3301 ///
3302 /// ```no_run
3303 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
3304 ///
3305 /// # fn main() -> testresult::TestResult {
3306 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3307 /// let nethsm = NetHsm::new(
3308 /// Connection::new(
3309 /// "https://example.org/api/v1".try_into()?,
3310 /// ConnectionSecurity::Unsafe,
3311 /// ),
3312 /// Some(Credentials::new(
3313 /// "admin".parse()?,
3314 /// Some(Passphrase::new("passphrase".to_string())),
3315 /// )),
3316 /// None,
3317 /// None,
3318 /// )?;
3319 ///
3320 /// // add a system-wide user in the Operator role
3321 /// nethsm.add_user(
3322 /// "Operator One".to_string(),
3323 /// UserRole::Operator,
3324 /// Passphrase::new("operator1-passphrase".to_string()),
3325 /// Some("user1".parse()?),
3326 /// )?;
3327 ///
3328 /// // this fails because the user exists already
3329 /// assert!(nethsm
3330 /// .add_user(
3331 /// "Operator One".to_string(),
3332 /// UserRole::Operator,
3333 /// Passphrase::new("operator1-passphrase".to_string()),
3334 /// Some("user1".parse()?),
3335 /// )
3336 /// .is_err());
3337 ///
3338 /// // add a user in the Administrator role (N-Administrator) for a not yet existing namespace "namespace1"
3339 /// nethsm.add_user(
3340 /// "Namespace1 Admin".to_string(),
3341 /// UserRole::Administrator,
3342 /// Passphrase::new("namespace1-admin-passphrase".to_string()),
3343 /// Some("namespace1~admin1".parse()?),
3344 /// )?;
3345 ///
3346 /// # Ok(())
3347 /// # }
3348 /// ```
3349 /// [Adds a user]: https://docs.nitrokey.com/nethsm/administration#add-user
3350 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3351 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3352 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3353 pub fn add_user(
3354 &self,
3355 real_name: String,
3356 role: UserRole,
3357 passphrase: Passphrase,
3358 user_id: Option<UserId>,
3359 ) -> Result<UserId, Error> {
3360 self.validate_namespace_access(NamespaceSupport::Supported, user_id.as_ref(), Some(&role))?;
3361 let user_id = if let Some(user_id) = user_id {
3362 users_user_id_put(
3363 &self.create_connection_config(),
3364 &user_id.to_string(),
3365 UserPostData::new(real_name, role.into(), passphrase.expose_owned()),
3366 )
3367 .map_err(|error| {
3368 Error::Api(format!(
3369 "Adding user failed: {}",
3370 NetHsmApiError::from(error)
3371 ))
3372 })?;
3373 user_id
3374 } else {
3375 UserId::new(
3376 users_post(
3377 &self.create_connection_config(),
3378 UserPostData::new(real_name, role.into(), passphrase.expose_owned()),
3379 )
3380 .map_err(|error| {
3381 Error::Api(format!(
3382 "Adding user failed: {}",
3383 NetHsmApiError::from(error)
3384 ))
3385 })?
3386 .entity
3387 .id,
3388 )?
3389 };
3390
3391 // add to list of users
3392 self.add_credentials(Credentials::new(user_id.clone(), Some(passphrase)));
3393
3394 Ok(user_id)
3395 }
3396
3397 /// Deletes an existing user.
3398 ///
3399 /// [Deletes a user] identified by `user_id`.
3400 ///
3401 /// Internally, this function also calls [`remove_credentials`][`NetHsm::remove_credentials`] to
3402 /// remove the user from the list of available credentials.
3403 ///
3404 /// This call requires using [`Credentials`] of a user in the
3405 /// [`Administrator`][`UserRole::Administrator`] [role].
3406 ///
3407 /// ## Namespaces
3408 ///
3409 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
3410 /// [namespace]) can only delete users in their own [namespace].
3411 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) can
3412 /// only delete system-wide users, but not those in a [namespace]. To allow *R-Administrators*
3413 /// to delete users in a [namespace], the given [namespace] has to be deleted first using
3414 /// [`delete_namespace`][`NetHsm::delete_namespace`].
3415 ///
3416 /// # Errors
3417 ///
3418 /// Returns an [`Error::Api`] if deleting a user fails:
3419 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3420 /// * the user identified by `user_id` does not exist
3421 /// * the used [`Credentials`] are not correct
3422 /// * the used [`Credentials`] are not that of a user in the
3423 /// [`Administrator`][`UserRole::Administrator`] role
3424 /// * the targeted user is in an existing [namespace], but the caller is an *R-Administrator* or
3425 /// an *N-Administrator* in a different [namespace]
3426 /// * the targeted user is a system-wide user, but the caller is not an *R-Administrator*
3427 /// * the user attempts to delete itself
3428 ///
3429 /// # Examples
3430 ///
3431 /// ```no_run
3432 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
3433 ///
3434 /// # fn main() -> testresult::TestResult {
3435 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3436 /// let nethsm = NetHsm::new(
3437 /// Connection::new(
3438 /// "https://example.org/api/v1".try_into()?,
3439 /// ConnectionSecurity::Unsafe,
3440 /// ),
3441 /// Some(Credentials::new(
3442 /// "admin".parse()?,
3443 /// Some(Passphrase::new("passphrase".to_string())),
3444 /// )),
3445 /// None,
3446 /// None,
3447 /// )?;
3448 ///
3449 /// // add a system-wide user in the Operator role
3450 /// nethsm.add_user(
3451 /// "Operator One".to_string(),
3452 /// UserRole::Operator,
3453 /// Passphrase::new("operator1-passphrase".to_string()),
3454 /// Some("user1".parse()?),
3455 /// )?;
3456 ///
3457 /// // add a user in the Administrator role for a namespace (N-Administrator)
3458 /// nethsm.add_user(
3459 /// "Namespace1 Admin".to_string(),
3460 /// UserRole::Administrator,
3461 /// Passphrase::new("namespce1-admin-passphrase".to_string()),
3462 /// Some("namespace1~admin1".parse()?),
3463 /// )?;
3464 /// // add the accompanying namespace
3465 /// nethsm.add_namespace(&"namespace1".parse()?)?;
3466 ///
3467 /// // R-Administrators can not delete N-Administrators, as long as their namespace exists
3468 /// assert!(nethsm.delete_user(&"namespace1~admin1".parse()?).is_err());
3469 /// // however, after deleting the namespace, this becomes possible
3470 /// nethsm.delete_namespace(&"namespace1".parse()?)?;
3471 /// nethsm.delete_user(&"namespace1~admin1".parse()?)?;
3472 ///
3473 /// // R-Administrators can delete system-wide users
3474 /// nethsm.delete_user(&"user1".parse()?)?;
3475 /// # Ok(())
3476 /// # }
3477 /// ```
3478 /// [Deletes a user]: https://docs.nitrokey.com/nethsm/administration#delete-user
3479 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3480 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3481 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3482 pub fn delete_user(&self, user_id: &UserId) -> Result<(), Error> {
3483 self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
3484 users_user_id_delete(&self.create_connection_config(), &user_id.to_string()).map_err(
3485 |error| {
3486 Error::Api(format!(
3487 "Deleting user failed: {}",
3488 NetHsmApiError::from(error)
3489 ))
3490 },
3491 )?;
3492
3493 // remove from list of credentials
3494 self.remove_credentials(user_id);
3495
3496 Ok(())
3497 }
3498
3499 /// Gets a [list of all User IDs].
3500 ///
3501 /// This call requires using [`Credentials`] of a user in the
3502 /// [`Administrator`][`UserRole::Administrator`] [role].
3503 ///
3504 /// ## Namespaces
3505 ///
3506 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
3507 /// [namespace]) can only list users in their own [namespace].
3508 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) can
3509 /// list all users on the system.
3510 ///
3511 /// # Errors
3512 ///
3513 /// Returns an [`Error::Api`] if retrieving the list of all User IDs fails:
3514 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3515 /// * the used [`Credentials`] are not correct
3516 /// * the used [`Credentials`] are not that of a user in the
3517 /// [`Administrator`][`UserRole::Administrator`] role
3518 ///
3519 /// # Examples
3520 ///
3521 /// ```no_run
3522 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
3523 ///
3524 /// # fn main() -> testresult::TestResult {
3525 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3526 /// let nethsm = NetHsm::new(
3527 /// Connection::new(
3528 /// "https://example.org/api/v1".try_into()?,
3529 /// ConnectionSecurity::Unsafe,
3530 /// ),
3531 /// Some(Credentials::new(
3532 /// "admin".parse()?,
3533 /// Some(Passphrase::new("passphrase".to_string())),
3534 /// )),
3535 /// None,
3536 /// None,
3537 /// )?;
3538 ///
3539 /// // add a user in the Administrator role for a namespace (N-Administrator)
3540 /// nethsm.add_user(
3541 /// "Namespace1 Admin".to_string(),
3542 /// UserRole::Administrator,
3543 /// Passphrase::new("namespce1-admin-passphrase".to_string()),
3544 /// Some("namespace1~admin1".parse()?),
3545 /// )?;
3546 /// // add the accompanying namespace
3547 /// nethsm.add_namespace(&"namespace1".parse()?)?;
3548 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
3549 /// // the N-Administrator only sees itself
3550 /// assert_eq!(nethsm.get_users()?.len(), 1);
3551 ///
3552 /// // use the credentials of the R-Administrator
3553 /// nethsm.use_credentials(&"admin".parse()?)?;
3554 /// // the R-Administrator sees at least itself and the previously created N-Administrator
3555 /// assert!(nethsm.get_users()?.len() >= 2);
3556 /// # Ok(())
3557 /// # }
3558 /// ```
3559 /// [list of all User IDs]: https://docs.nitrokey.com/nethsm/administration#list-users
3560 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3561 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3562 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3563 pub fn get_users(&self) -> Result<Vec<UserId>, Error> {
3564 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
3565 let valid_users = {
3566 let mut invalid_users = Vec::new();
3567 let valid_users = users_get(&self.create_connection_config())
3568 .map_err(|error| {
3569 Error::Api(format!(
3570 "Getting users failed: {}",
3571 NetHsmApiError::from(error)
3572 ))
3573 })?
3574 .entity
3575 .into_iter()
3576 .filter_map(|x| {
3577 if let Ok(user) = UserId::new(x.user.clone()) {
3578 Some(user)
3579 } else {
3580 invalid_users.push(x.user);
3581 None
3582 }
3583 })
3584 .collect::<Vec<UserId>>();
3585
3586 if !invalid_users.is_empty() {
3587 return Err(UserError::InvalidUserIds {
3588 user_ids: invalid_users,
3589 }
3590 .into());
3591 }
3592
3593 valid_users
3594 };
3595
3596 Ok(valid_users)
3597 }
3598
3599 /// Gets [information of a user].
3600 ///
3601 /// This call requires using [`Credentials`] of a user in the
3602 /// [`Administrator`][`UserRole::Administrator`] [role].
3603 ///
3604 /// ## Namespaces
3605 ///
3606 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
3607 /// [namespace]) can only access information about users in their own [namespace].
3608 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) can
3609 /// access information about all users on the system.
3610 ///
3611 /// # Errors
3612 ///
3613 /// Returns an [`Error::Api`] if retrieving information of the user fails:
3614 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3615 /// * the user identified by `user_id` does not exist
3616 /// * the used [`Credentials`] are not correct
3617 /// * the used [`Credentials`] are not that of a user in the
3618 /// [`Administrator`][`UserRole::Administrator`] role
3619 /// * the used [`Credentials`] do not provide access to information about a user in the targeted
3620 /// [namespace] (*N-Administrator* of a different [namespace])
3621 ///
3622 /// # Examples
3623 ///
3624 /// ```no_run
3625 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
3626 ///
3627 /// # fn main() -> testresult::TestResult {
3628 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3629 /// let nethsm = NetHsm::new(
3630 /// Connection::new(
3631 /// "https://example.org/api/v1".try_into()?,
3632 /// ConnectionSecurity::Unsafe,
3633 /// ),
3634 /// Some(Credentials::new(
3635 /// "admin".parse()?,
3636 /// Some(Passphrase::new("passphrase".to_string())),
3637 /// )),
3638 /// None,
3639 /// None,
3640 /// )?;
3641 ///
3642 /// // add a user in the Administrator role for a namespace (N-Administrator)
3643 /// nethsm.add_user(
3644 /// "Namespace1 Admin".to_string(),
3645 /// UserRole::Administrator,
3646 /// Passphrase::new("namespce1-admin-passphrase".to_string()),
3647 /// Some("namespace1~admin1".parse()?),
3648 /// )?;
3649 /// // add the accompanying namespace
3650 /// nethsm.add_namespace(&"namespace1".parse()?)?;
3651 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
3652 /// // the N-Administrator sees itself
3653 /// println!("{:?}", nethsm.get_user(&"namespace1~admin1".parse()?)?);
3654 /// // the N-Administrator can not see the R-Administrator
3655 /// assert!(nethsm.get_user(&"admin".parse()?).is_err());
3656 ///
3657 /// nethsm.use_credentials(&"admin".parse()?)?;
3658 /// // the R-Administrator sees itself
3659 /// println!("{:?}", nethsm.get_user(&"admin".parse()?)?);
3660 /// // the R-Administrator sees the N-Administrator
3661 /// println!("{:?}", nethsm.get_user(&"namespace1~admin1".parse()?)?);
3662 /// // this fails if the user does not exist
3663 /// assert!(nethsm.get_user(&"user1".parse()?).is_err());
3664 /// # Ok(())
3665 /// # }
3666 /// ```
3667 /// [information of a user]: https://docs.nitrokey.com/nethsm/administration#list-users
3668 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3669 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3670 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3671 pub fn get_user(&self, user_id: &UserId) -> Result<UserData, Error> {
3672 self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
3673 Ok(
3674 users_user_id_get(&self.create_connection_config(), &user_id.to_string())
3675 .map_err(|error| {
3676 Error::Api(format!(
3677 "Getting user failed: {}",
3678 NetHsmApiError::from(error)
3679 ))
3680 })?
3681 .entity,
3682 )
3683 }
3684
3685 /// Sets the [passphrase for a user] on the NetHSM.
3686 ///
3687 /// ## Namespaces
3688 ///
3689 /// *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
3690 /// [namespace]) are only able to set the passphrases for users in their own [namespace].
3691 /// *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are only
3692 /// able to set the passphrases for system-wide users.
3693 ///
3694 /// Internally, this function also calls [`add_credentials`][`NetHsm::add_credentials`] to add
3695 /// the updated user [`Credentials`] to the list of available ones.
3696 /// If the calling user is in the [`Administrator`][`UserRole::Administrator`] [role] and
3697 /// changes their own passphrase, additionally
3698 /// [`use_credentials`][`NetHsm::use_credentials`] is called to use the updated passphrase
3699 /// after changing it.
3700 ///
3701 /// This call requires using [`Credentials`] of a user in the
3702 /// [`Administrator`][`UserRole::Administrator`] [role].
3703 ///
3704 /// # Errors
3705 ///
3706 /// Returns an [`Error::Api`] if setting the passphrase for the user fails:
3707 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3708 /// * the user identified by `user_id` does not exist
3709 /// * the used [`Credentials`] are not correct
3710 /// * the used [`Credentials`] are not that of a user in the
3711 /// [`Administrator`][`UserRole::Administrator`] [role]
3712 /// * the targeted user is in a [namespace], but the caller is not an
3713 /// [`Administrator`][`UserRole::Administrator`] of that [namespace] (*N-Administrator*)
3714 /// * the targeted user is a system-wide user, but the caller is not a system-wide
3715 /// [`Administrator`][`UserRole::Administrator`] (*R-Administrator*)
3716 ///
3717 /// # Examples
3718 ///
3719 /// ```no_run
3720 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
3721 ///
3722 /// # fn main() -> testresult::TestResult {
3723 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3724 /// let nethsm = NetHsm::new(
3725 /// Connection::new(
3726 /// "https://example.org/api/v1".try_into()?,
3727 /// ConnectionSecurity::Unsafe,
3728 /// ),
3729 /// Some(Credentials::new(
3730 /// "admin".parse()?,
3731 /// Some(Passphrase::new("passphrase".to_string())),
3732 /// )),
3733 /// None,
3734 /// None,
3735 /// )?;
3736 /// // add a user in the Administrator role for a namespace (N-Administrator)
3737 /// nethsm.add_user(
3738 /// "Namespace1 Admin".to_string(),
3739 /// UserRole::Administrator,
3740 /// Passphrase::new("namespce1-admin-passphrase".to_string()),
3741 /// Some("namespace1~admin1".parse()?),
3742 /// )?;
3743 /// // add the accompanying namespace
3744 /// nethsm.add_namespace(&"namespace1".parse()?)?;
3745 ///
3746 /// // the R-Administrator can set its own passphrase
3747 /// nethsm.set_user_passphrase(
3748 /// "admin".parse()?,
3749 /// Passphrase::new("new-admin-passphrase".to_string()),
3750 /// )?;
3751 /// // the R-Administrator can not set the N-Administrator's passphrase
3752 /// assert!(
3753 /// nethsm
3754 /// .set_user_passphrase(
3755 /// "namespace1~admin".parse()?,
3756 /// Passphrase::new("new-admin-passphrase".to_string()),
3757 /// )
3758 /// .is_err()
3759 /// );
3760 ///
3761 /// // the N-Administrator can set its own passphrase
3762 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
3763 /// nethsm.set_user_passphrase(
3764 /// "namespace1~admin1".parse()?,
3765 /// Passphrase::new("new-admin-passphrase".to_string()),
3766 /// )?;
3767 /// // the N-Administrator can not set the R-Administrator's passphrase
3768 /// assert!(
3769 /// nethsm
3770 /// .set_user_passphrase(
3771 /// "admin".parse()?,
3772 /// Passphrase::new("new-admin-passphrase".to_string())
3773 /// )
3774 /// .is_err()
3775 /// );
3776 /// # Ok(())
3777 /// # }
3778 /// ```
3779 /// [passphrase for a user]: https://docs.nitrokey.com/nethsm/administration#user-passphrase
3780 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3781 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3782 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3783 pub fn set_user_passphrase(
3784 &self,
3785 user_id: UserId,
3786 passphrase: Passphrase,
3787 ) -> Result<(), Error> {
3788 self.validate_namespace_access(NamespaceSupport::Supported, Some(&user_id), None)?;
3789 users_user_id_passphrase_post(
3790 &self.create_connection_config(),
3791 &user_id.to_string(),
3792 UserPassphrasePostData::new(passphrase.expose_owned()),
3793 )
3794 .map_err(|error| {
3795 Error::Api(format!(
3796 "Setting user passphrase failed: {}",
3797 NetHsmApiError::from(error)
3798 ))
3799 })?;
3800
3801 // add to list of available credentials
3802 self.add_credentials(Credentials::new(user_id, Some(passphrase)));
3803
3804 Ok(())
3805 }
3806
3807 /// [Adds a tag] to a user in the [`Operator`][`UserRole::Operator`] [role].
3808 ///
3809 /// A `tag` provides the user identified by `user_id` with access to keys in their [namespace],
3810 /// that are tagged with that same `tag`.
3811 ///
3812 /// **NOTE**: The tag for the key in the same [namespace] must be added beforehand, by calling
3813 /// [`add_key_tag`][`NetHsm::add_key_tag`].
3814 ///
3815 /// This call requires using [`Credentials`] of a user in the
3816 /// [`Administrator`][`UserRole::Administrator`] [role].
3817 ///
3818 /// ## Namespaces
3819 ///
3820 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
3821 /// [namespace]) are only able to add tags for users in their own [namespace].
3822 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
3823 /// only able to add tags for system-wide users.
3824 ///
3825 /// # Errors
3826 ///
3827 /// Returns an [`Error::Api`] if adding the tag for the user fails:
3828 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3829 /// * the user identified by `user_id` does not exist
3830 /// * the user identified by `user_id` is not in the [`Operator`][`UserRole::Operator`] [role]
3831 /// * the used [`Credentials`] are not correct
3832 /// * the used [`Credentials`] are not that of a user in the
3833 /// [`Administrator`][`UserRole::Administrator`] [role]
3834 /// * the caller does not have access to the target user's [namespace]
3835 ///
3836 /// # Examples
3837 ///
3838 /// ```no_run
3839 /// use nethsm::{
3840 /// Connection,
3841 /// ConnectionSecurity,
3842 /// Credentials,
3843 /// KeyMechanism,
3844 /// KeyType,
3845 /// NetHsm,
3846 /// Passphrase,
3847 /// UserRole,
3848 /// };
3849 ///
3850 /// # fn main() -> testresult::TestResult {
3851 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3852 /// let nethsm = NetHsm::new(
3853 /// Connection::new(
3854 /// "https://example.org/api/v1".try_into()?,
3855 /// ConnectionSecurity::Unsafe,
3856 /// ),
3857 /// Some(Credentials::new(
3858 /// "admin".parse()?,
3859 /// Some(Passphrase::new("passphrase".to_string())),
3860 /// )),
3861 /// None,
3862 /// None,
3863 /// )?;
3864 /// // add a user in the Administrator role for a namespace (N-Administrator)
3865 /// nethsm.add_user(
3866 /// "Namespace1 Admin".to_string(),
3867 /// UserRole::Administrator,
3868 /// Passphrase::new("namespce1-admin-passphrase".to_string()),
3869 /// Some("namespace1~admin1".parse()?),
3870 /// )?;
3871 /// // add a user in the Operator role for a namespace
3872 /// nethsm.add_user(
3873 /// "Namespace1 Operator".to_string(),
3874 /// UserRole::Operator,
3875 /// Passphrase::new("namespce1-operator-passphrase".to_string()),
3876 /// Some("namespace1~operator1".parse()?),
3877 /// )?;
3878 /// // add the accompanying namespace
3879 /// nethsm.add_namespace(&"namespace1".parse()?)?;
3880 /// // add a system-wide user in the Operator role
3881 /// nethsm.add_user(
3882 /// "Operator One".to_string(),
3883 /// UserRole::Operator,
3884 /// Passphrase::new("operator1-passphrase".to_string()),
3885 /// Some("user1".parse()?),
3886 /// )?;
3887 /// // generate system-wide key with tag
3888 /// nethsm.generate_key(
3889 /// KeyType::Curve25519,
3890 /// vec![KeyMechanism::EdDsaSignature],
3891 /// None,
3892 /// Some("signing1".parse()?),
3893 /// Some(vec!["tag1".to_string()]),
3894 /// )?;
3895 ///
3896 /// // R-Administrators can add tags for system-wide users
3897 /// nethsm.add_user_tag(&"user1".parse()?, "tag1")?;
3898 /// // R-Administrators can not add tags for namespace users
3899 /// assert!(
3900 /// nethsm
3901 /// .add_user_tag(&"namespace1~user1".parse()?, "tag1")
3902 /// .is_err()
3903 /// );
3904 ///
3905 /// // user tags in namespaces
3906 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
3907 /// // generate key in namespace1 with tag
3908 /// nethsm.generate_key(
3909 /// KeyType::Curve25519,
3910 /// vec![KeyMechanism::EdDsaSignature],
3911 /// None,
3912 /// Some("signing2".parse()?),
3913 /// Some(vec!["tag2".to_string()]),
3914 /// )?;
3915 /// // N-Administrators can not add tags to system-wide users
3916 /// assert!(nethsm.add_user_tag(&"user1".parse()?, "tag2").is_err());
3917 /// // N-Administrators can add tags to users in their own namespace
3918 /// nethsm.add_user_tag(&"namespace1~user1".parse()?, "tag2")?;
3919 /// # Ok(())
3920 /// # }
3921 /// ```
3922 /// [Adds a tag]: https://docs.nitrokey.com/nethsm/administration#tags-for-users
3923 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
3924 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
3925 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
3926 pub fn add_user_tag(&self, user_id: &UserId, tag: &str) -> Result<(), Error> {
3927 self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
3928 users_user_id_tags_tag_put(&self.create_connection_config(), &user_id.to_string(), tag)
3929 .map_err(|error| {
3930 Error::Api(format!(
3931 "Adding tag for user failed: {}",
3932 NetHsmApiError::from(error)
3933 ))
3934 })?;
3935 Ok(())
3936 }
3937
3938 /// [Deletes a tag] from a user in the [`Operator`][`UserRole::Operator`] [role].
3939 ///
3940 /// Removes a `tag` from a target user identified by `user_id`, which removes its access to any
3941 /// key in their [namespace], that carries the same `tag`.
3942 ///
3943 /// This call requires using [`Credentials`] of a user in the
3944 /// [`Administrator`][`UserRole::Administrator`] [role].
3945 ///
3946 /// ## Namespaces
3947 ///
3948 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
3949 /// [namespace]) are only able to delete tags for users in their own [namespace].
3950 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
3951 /// only able to delete tags for system-wide users.
3952 ///
3953 /// # Errors
3954 ///
3955 /// Returns an [`Error::Api`] if deleting the tag from the user fails:
3956 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
3957 /// * the user identified by `user_id` does not exist
3958 /// * the user identified by `user_id` is not in the [`Operator`][`UserRole::Operator`] [role]
3959 /// * the `tag` is not added to user identified by `user_id`
3960 /// * the used [`Credentials`] are not correct
3961 /// * the used [`Credentials`] are not that of a user in the
3962 /// [`Administrator`][`UserRole::Administrator`] [role]
3963 /// * the caller does not have access to the target user's [namespace]
3964 ///
3965 /// # Examples
3966 ///
3967 /// ```no_run
3968 /// use nethsm::{
3969 /// Connection,
3970 /// ConnectionSecurity,
3971 /// Credentials,
3972 /// KeyMechanism,
3973 /// KeyType,
3974 /// NetHsm,
3975 /// Passphrase,
3976 /// UserRole,
3977 /// };
3978 ///
3979 /// # fn main() -> testresult::TestResult {
3980 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
3981 /// let nethsm = NetHsm::new(
3982 /// Connection::new(
3983 /// "https://example.org/api/v1".try_into()?,
3984 /// ConnectionSecurity::Unsafe,
3985 /// ),
3986 /// Some(Credentials::new(
3987 /// "admin".parse()?,
3988 /// Some(Passphrase::new("passphrase".to_string())),
3989 /// )),
3990 /// None,
3991 /// None,
3992 /// )?;
3993 /// // add a user in the Administrator role for a namespace (N-Administrator)
3994 /// nethsm.add_user(
3995 /// "Namespace1 Admin".to_string(),
3996 /// UserRole::Administrator,
3997 /// Passphrase::new("namespce1-admin-passphrase".to_string()),
3998 /// Some("namespace1~admin1".parse()?),
3999 /// )?;
4000 /// // add a user in the Operator role for a namespace
4001 /// nethsm.add_user(
4002 /// "Namespace1 Operator".to_string(),
4003 /// UserRole::Operator,
4004 /// Passphrase::new("namespce1-operator-passphrase".to_string()),
4005 /// Some("namespace1~operator1".parse()?),
4006 /// )?;
4007 /// // add the accompanying namespace
4008 /// nethsm.add_namespace(&"namespace1".parse()?)?;
4009 /// // add a system-wide user in the Operator role
4010 /// nethsm.add_user(
4011 /// "Operator One".to_string(),
4012 /// UserRole::Operator,
4013 /// Passphrase::new("operator1-passphrase".to_string()),
4014 /// Some("user1".parse()?),
4015 /// )?;
4016 /// // generate system-wide key with tag
4017 /// nethsm.generate_key(
4018 /// KeyType::Curve25519,
4019 /// vec![KeyMechanism::EdDsaSignature],
4020 /// None,
4021 /// Some("signing1".parse()?),
4022 /// Some(vec!["tag1".to_string()]),
4023 /// )?;
4024 /// // add tag for system-wide user
4025 /// nethsm.add_user_tag(&"user1".parse()?, "tag1")?;
4026 ///
4027 /// // N-Administrators can not delete tags from system-wide Operator users
4028 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
4029 /// assert!(nethsm.delete_user_tag(&"user1".parse()?, "tag2").is_err());
4030 ///
4031 /// // R-Administrators can delete tags from system-wide Operator users
4032 /// nethsm.use_credentials(&"admin".parse()?)?;
4033 /// nethsm.delete_user_tag(&"user1".parse()?, "tag1")?;
4034 /// # Ok(())
4035 /// # }
4036 /// ```
4037 /// [Deletes a tag]: https://docs.nitrokey.com/nethsm/administration#tags-for-users
4038 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4039 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4040 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4041 pub fn delete_user_tag(&self, user_id: &UserId, tag: &str) -> Result<(), Error> {
4042 self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
4043 users_user_id_tags_tag_delete(&self.create_connection_config(), &user_id.to_string(), tag)
4044 .map_err(|error| {
4045 Error::Api(format!(
4046 "Deleting tag for user failed: {}",
4047 NetHsmApiError::from(error)
4048 ))
4049 })?;
4050 Ok(())
4051 }
4052
4053 /// [Gets all tags] of a user in the [`Operator`][`UserRole::Operator`] [role].
4054 ///
4055 /// This call requires using [`Credentials`] of a user in the
4056 /// [`Administrator`][`UserRole::Administrator`] [role].
4057 ///
4058 /// ## Namespaces
4059 ///
4060 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
4061 /// [namespace]) are only able to get tags of users in their own [namespace].
4062 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
4063 /// able to get tags of system-wide and all [namespace] users.
4064 ///
4065 /// # Errors
4066 ///
4067 /// Returns an [`Error::Api`] if getting the tags for the user fails:
4068 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4069 /// * the user identified by `user_id` does not exist
4070 /// * the user identified by `user_id` is not in the [`Operator`][`UserRole::Operator`] [role]
4071 /// * the used [`Credentials`] are not correct
4072 /// * the used [`Credentials`] are not that of a user in the
4073 /// [`Administrator`][`UserRole::Administrator`] [role]
4074 /// * the caller does not have access to the target user's [namespace]
4075 ///
4076 /// # Examples
4077 ///
4078 /// ```no_run
4079 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
4080 ///
4081 /// # fn main() -> testresult::TestResult {
4082 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4083 /// let nethsm = NetHsm::new(
4084 /// Connection::new(
4085 /// "https://example.org/api/v1".try_into()?,
4086 /// ConnectionSecurity::Unsafe,
4087 /// ),
4088 /// Some(Credentials::new(
4089 /// "admin".parse()?,
4090 /// Some(Passphrase::new("passphrase".to_string())),
4091 /// )),
4092 /// None,
4093 /// None,
4094 /// )?;
4095 /// // add a user in the Administrator role for a namespace (N-Administrator)
4096 /// nethsm.add_user(
4097 /// "Namespace1 Admin".to_string(),
4098 /// UserRole::Administrator,
4099 /// Passphrase::new("namespce1-admin-passphrase".to_string()),
4100 /// Some("namespace1~admin1".parse()?),
4101 /// )?;
4102 /// // add the accompanying namespace
4103 /// nethsm.add_namespace(&"namespace1".parse()?)?;
4104 /// // add a system-wide user in the Operator role
4105 /// nethsm.add_user(
4106 /// "Operator One".to_string(),
4107 /// UserRole::Operator,
4108 /// Passphrase::new("operator1-passphrase".to_string()),
4109 /// Some("user1".parse()?),
4110 /// )?;
4111 ///
4112 /// // R-Administrators can access tags of all users
4113 /// assert!(nethsm.get_user_tags(&"user1".parse()?)?.is_empty());
4114 /// // add a tag for the user
4115 /// nethsm.add_user_tag(&"user1".parse()?, "tag1")?;
4116 /// assert_eq!(nethsm.get_user_tags(&"user1".parse()?)?.len(), 1);
4117 ///
4118 /// // N-Administrators can not access tags of system-wide users
4119 /// nethsm.use_credentials(&"namespace1~admin1".parse()?)?;
4120 /// assert!(nethsm.get_user_tags(&"user1".parse()?).is_err());
4121 /// # Ok(())
4122 /// # }
4123 /// ```
4124 /// [Gets all tags]: https://docs.nitrokey.com/nethsm/administration#tags-for-users
4125 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4126 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4127 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4128 pub fn get_user_tags(&self, user_id: &UserId) -> Result<Vec<String>, Error> {
4129 self.validate_namespace_access(NamespaceSupport::Supported, Some(user_id), None)?;
4130 Ok(
4131 users_user_id_tags_get(&self.create_connection_config(), &user_id.to_string())
4132 .map_err(|error| {
4133 Error::Api(format!(
4134 "Getting tags of user failed: {}",
4135 NetHsmApiError::from(error)
4136 ))
4137 })?
4138 .entity,
4139 )
4140 }
4141
4142 /// [Generates a new key] on the NetHSM.
4143 ///
4144 /// [Generates a new key] with customizable features on the NetHSM.
4145 /// The provided [`KeyType`] and list of [`KeyMechanism`]s have to match:
4146 /// * [`KeyType::Rsa`] requires one of [`KeyMechanism::RsaDecryptionRaw`],
4147 /// [`KeyMechanism::RsaDecryptionPkcs1`], [`KeyMechanism::RsaDecryptionOaepMd5`],
4148 /// [`KeyMechanism::RsaDecryptionOaepSha1`], [`KeyMechanism::RsaDecryptionOaepSha224`],
4149 /// [`KeyMechanism::RsaDecryptionOaepSha256`], [`KeyMechanism::RsaDecryptionOaepSha384`],
4150 /// [`KeyMechanism::RsaDecryptionOaepSha512`], [`KeyMechanism::RsaSignaturePkcs1`],
4151 /// [`KeyMechanism::RsaSignaturePssMd5`], [`KeyMechanism::RsaSignaturePssSha1`],
4152 /// [`KeyMechanism::RsaSignaturePssSha224`], [`KeyMechanism::RsaSignaturePssSha256`],
4153 /// [`KeyMechanism::RsaSignaturePssSha384`] or [`KeyMechanism::RsaSignaturePssSha512`]
4154 /// * [`KeyType::Curve25519`] requires [`KeyMechanism::EdDsaSignature`]
4155 /// * [`KeyType::EcP224`], [`KeyType::EcP256`], [`KeyType::EcP384`] and [`KeyType::EcP521`]
4156 /// require [`KeyMechanism::EcdsaSignature`]
4157 /// * [`KeyType::Generic`] requires one of [`KeyMechanism::AesDecryptionCbc`] or
4158 /// [`KeyMechanism::AesEncryptionCbc`]
4159 ///
4160 /// Optionally the key bit-length using `length`, a custom key ID using `key_id`
4161 /// and a list of `tags` to be attached to the new key can be provided.
4162 /// If no `key_id` is provided, a unique one is generated automatically.
4163 ///
4164 /// **WARNING**: If no `tags` are provided, the generated key is usable by all users in the
4165 /// [`Operator`][`UserRole::Operator`] [role] in the same scope (e.g. same [namespace]) by
4166 /// default!
4167 ///
4168 /// This call requires using [`Credentials`] of a user in the
4169 /// [`Administrator`][`UserRole::Administrator`] [role].
4170 ///
4171 /// ## Namespaces
4172 ///
4173 /// * Keys generated by *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users
4174 /// in a given [namespace]) are only visible to users in their [namespace]. Only users in the
4175 /// [`Operator`][`UserRole::Operator`] [role] in that same [namespace] can be granted access
4176 /// to them.
4177 /// * Keys generated by *R-Administrators* (system-wide
4178 /// [`Administrator`][`UserRole::Administrator`] users) are only visible to system-wide users.
4179 /// Only system-wide users in the [`Operator`][`UserRole::Operator`] [role] (not in any
4180 /// [namespace]) can be granted access to them.
4181 ///
4182 /// # Errors
4183 ///
4184 /// Returns an [`Error::Api`] if generating the key fails:
4185 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4186 /// * a key identified by ` key_id` exists already
4187 /// * the chosen `length` or `tags` options are not valid
4188 /// * the used [`Credentials`] are not correct
4189 /// * the used [`Credentials`] are not that of a user in the
4190 /// [`Administrator`][`UserRole::Administrator`] [role]
4191 ///
4192 /// Returns an [`Error::Key`] if
4193 /// * the provided combination of `key_type` and `mechanisms` is not valid.
4194 /// * the provided combination of `key_type` and `length` is not valid.
4195 ///
4196 /// # Examples
4197 ///
4198 /// ```no_run
4199 /// use nethsm::{
4200 /// Connection,
4201 /// ConnectionSecurity,
4202 /// Credentials,
4203 /// KeyMechanism,
4204 /// KeyType,
4205 /// NetHsm,
4206 /// Passphrase,
4207 /// };
4208 ///
4209 /// # fn main() -> testresult::TestResult {
4210 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4211 /// let nethsm = NetHsm::new(
4212 /// Connection::new(
4213 /// "https://example.org/api/v1".try_into()?,
4214 /// ConnectionSecurity::Unsafe,
4215 /// ),
4216 /// Some(Credentials::new(
4217 /// "admin".parse()?,
4218 /// Some(Passphrase::new("passphrase".to_string())),
4219 /// )),
4220 /// None,
4221 /// None,
4222 /// )?;
4223 ///
4224 /// // generate a Curve25519 key for signing with custom Key ID and tags
4225 /// nethsm.generate_key(
4226 /// KeyType::Curve25519,
4227 /// vec![KeyMechanism::EdDsaSignature],
4228 /// None,
4229 /// Some("signing1".parse()?),
4230 /// Some(vec!["sign_tag1".to_string(), "sign_tag2".to_string()]),
4231 /// )?;
4232 ///
4233 /// // generate a generic key for symmetric encryption and decryption
4234 /// nethsm.generate_key(
4235 /// KeyType::Generic,
4236 /// vec![
4237 /// KeyMechanism::AesEncryptionCbc,
4238 /// KeyMechanism::AesDecryptionCbc,
4239 /// ],
4240 /// Some(128),
4241 /// Some("encryption1".parse()?),
4242 /// Some(vec!["encryption_tag1".to_string()]),
4243 /// )?;
4244 /// # Ok(())
4245 /// # }
4246 /// ```
4247 /// [Generates a new key]: https://docs.nitrokey.com/nethsm/operation#generate-key
4248 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4249 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4250 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4251 pub fn generate_key(
4252 &self,
4253 key_type: KeyType,
4254 mechanisms: Vec<KeyMechanism>,
4255 length: Option<u32>,
4256 key_id: Option<KeyId>,
4257 tags: Option<Vec<String>>,
4258 ) -> Result<KeyId, Error> {
4259 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
4260 // ensure the key_type - mechanisms combinations are valid
4261 key_type_matches_mechanisms(key_type, &mechanisms)?;
4262 // ensure the key_type - length combination is valid
4263 key_type_matches_length(key_type, length)?;
4264
4265 Ok(keys_generate_post(
4266 &self.create_connection_config(),
4267 KeyGenerateRequestData {
4268 mechanisms: mechanisms
4269 .into_iter()
4270 .map(|mechanism| mechanism.into())
4271 .collect(),
4272 r#type: key_type.into(),
4273 length: length.map(|length| length as i32),
4274 id: key_id.map(Into::into),
4275 restrictions: tags.map(|tags| Box::new(KeyRestrictions { tags: Some(tags) })),
4276 },
4277 )
4278 .map_err(|error| {
4279 Error::Api(format!(
4280 "Creating key failed: {}",
4281 NetHsmApiError::from(error)
4282 ))
4283 })?
4284 .entity
4285 .id
4286 .parse()?)
4287 }
4288
4289 /// Imports an existing private key.
4290 ///
4291 /// [Imports an existing key] with custom features into the NetHSM.
4292 /// The [`KeyType`] implied by the provided [`PrivateKeyImport`] and the list of
4293 /// [`KeyMechanism`]s have to match:
4294 /// * [`KeyType::Rsa`] must be used with [`KeyMechanism::RsaDecryptionRaw`],
4295 /// [`KeyMechanism::RsaDecryptionPkcs1`], [`KeyMechanism::RsaDecryptionOaepMd5`],
4296 /// [`KeyMechanism::RsaDecryptionOaepSha1`], [`KeyMechanism::RsaDecryptionOaepSha224`],
4297 /// [`KeyMechanism::RsaDecryptionOaepSha256`], [`KeyMechanism::RsaDecryptionOaepSha384`],
4298 /// [`KeyMechanism::RsaDecryptionOaepSha512`], [`KeyMechanism::RsaSignaturePkcs1`],
4299 /// [`KeyMechanism::RsaSignaturePssMd5`], [`KeyMechanism::RsaSignaturePssSha1`],
4300 /// [`KeyMechanism::RsaSignaturePssSha224`], [`KeyMechanism::RsaSignaturePssSha256`],
4301 /// [`KeyMechanism::RsaSignaturePssSha384`] or [`KeyMechanism::RsaSignaturePssSha512`]
4302 /// * [`KeyType::Curve25519`] must be used with [`KeyMechanism::EdDsaSignature`]
4303 /// * [`KeyType::EcP224`], [`KeyType::EcP256`], [`KeyType::EcP384`] and [`KeyType::EcP521`] must
4304 /// be used with [`KeyMechanism::EcdsaSignature`]
4305 /// * [`KeyType::Generic`] must be used with [`KeyMechanism::AesDecryptionCbc`] or
4306 /// [`KeyMechanism::AesEncryptionCbc`]
4307 ///
4308 /// Optionally a custom Key ID using `key_id` and a list of `tags` to be attached to the new key
4309 /// can be provided.
4310 /// If no `key_id` is provided, a unique one is generated automatically.
4311 ///
4312 /// **WARNING**: If no `tags` are provided, the imported key is usable by all users in the
4313 /// [`Operator`][`UserRole::Operator`] [role] in the same scope (e.g. same [namespace]) by
4314 /// default!
4315 ///
4316 /// This call requires using [`Credentials`] of a user in the
4317 /// [`Administrator`][`UserRole::Administrator`] [role].
4318 ///
4319 /// ## Namespaces
4320 ///
4321 /// * Keys imported by *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in
4322 /// a given [namespace]) are only visible to users in their [namespace]. Only users in the
4323 /// [`Operator`][`UserRole::Operator`] [role] in that same [namespace] can be granted access
4324 /// to them.
4325 /// * Keys imported by *R-Administrators* (system-wide
4326 /// [`Administrator`][`UserRole::Administrator`] users) are only visible to system-wide users.
4327 /// Only system-wide users in the [`Operator`][`UserRole::Operator`] [role] (not in any
4328 /// [namespace]) can be granted access to them.
4329 ///
4330 /// # Errors
4331 ///
4332 /// Returns an [`Error::Api`] if importing the key fails:
4333 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4334 /// * a key identified by ` key_id` exists already
4335 /// * the chosen `tags` option is not valid
4336 /// * the used [`Credentials`] are not correct
4337 /// * the used [`Credentials`] are not that of a user in the
4338 /// [`Administrator`][`UserRole::Administrator`] [role]
4339 ///
4340 /// Returns an [`Error::Key`] if the provided combination of `key_data` and `mechanisms` is not
4341 /// valid.
4342 ///
4343 /// # Examples
4344 ///
4345 /// ```no_run
4346 /// use nethsm::{Connection, ConnectionSecurity, Credentials, PrivateKeyImport, KeyMechanism, KeyType, NetHsm, Passphrase};
4347 /// use rsa::pkcs8::{DecodePrivateKey, EncodePrivateKey};
4348 /// use rsa::RsaPrivateKey;
4349 ///
4350 /// # fn main() -> testresult::TestResult {
4351 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4352 /// let nethsm = NetHsm::new(
4353 /// Connection::new(
4354 /// "https://example.org/api/v1".try_into()?,
4355 /// ConnectionSecurity::Unsafe,
4356 /// ),
4357 /// Some(Credentials::new(
4358 /// "admin".parse()?,
4359 /// Some(Passphrase::new("passphrase".to_string())),
4360 /// )),
4361 /// None,
4362 /// None,
4363 /// )?;
4364 ///
4365 /// // create a 4096 bit RSA private key and return it as PKCS#8 private key in ASN.1 DER-encoded format
4366 /// let private_key = {
4367 /// let mut rng = rand::thread_rng();
4368 /// let private_key = RsaPrivateKey::new(&mut rng, 4096)?;
4369 /// private_key.to_pkcs8_der()?
4370 /// };
4371 ///
4372 /// // import an RSA key for PKCS1 signatures
4373 /// nethsm.import_key(
4374 /// vec![KeyMechanism::RsaSignaturePkcs1],
4375 /// PrivateKeyImport::new(KeyType::Rsa, private_key.as_bytes())?,
4376 /// Some("signing2".parse()?),
4377 /// Some(vec!["signing_tag3".to_string()]),
4378 /// )?;
4379 /// # Ok(())
4380 /// # }
4381 /// ```
4382 /// [Imports an existing key]: https://docs.nitrokey.com/nethsm/operation#import-key
4383 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4384 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4385 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4386 pub fn import_key(
4387 &self,
4388 mechanisms: Vec<KeyMechanism>,
4389 key_data: PrivateKeyImport,
4390 key_id: Option<KeyId>,
4391 tags: Option<Vec<String>>,
4392 ) -> Result<KeyId, Error> {
4393 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
4394 // ensure the key_type - mechanisms combinations are valid
4395 let key_type = key_data.key_type();
4396 key_type_matches_mechanisms(key_type, &mechanisms)?;
4397
4398 let restrictions = tags.map(|tags| Box::new(KeyRestrictions { tags: Some(tags) }));
4399 let private = Box::new(key_data.into());
4400 let mechanisms = mechanisms
4401 .into_iter()
4402 .map(|mechanism| mechanism.into())
4403 .collect();
4404
4405 if let Some(key_id) = key_id {
4406 keys_key_id_put(
4407 &self.create_connection_config(),
4408 key_id.as_ref(),
4409 nethsm_sdk_rs::apis::default_api::KeysKeyIdPutBody::ApplicationJson(PrivateKey {
4410 mechanisms,
4411 r#type: key_type.into(),
4412 private,
4413 restrictions,
4414 }),
4415 )
4416 .map_err(|error| {
4417 Error::Api(format!(
4418 "Importing key failed: {}",
4419 NetHsmApiError::from(error)
4420 ))
4421 })?;
4422 Ok(key_id)
4423 } else {
4424 Ok(keys_post(
4425 &self.create_connection_config(),
4426 KeysPostBody::ApplicationJson(PrivateKey {
4427 mechanisms,
4428 r#type: key_type.into(),
4429 private,
4430 restrictions,
4431 }),
4432 )
4433 .map_err(|error| {
4434 Error::Api(format!(
4435 "Importing key failed: {}",
4436 NetHsmApiError::from(error)
4437 ))
4438 })?
4439 .entity
4440 .id
4441 .parse()?)
4442 }
4443 }
4444
4445 /// [Deletes a key] from the NetHSM.
4446 ///
4447 /// [Deletes a key] identified by `key_id` from the NetHSM.
4448 ///
4449 /// This call requires using [`Credentials`] of a user in the
4450 /// [`Administrator`][`UserRole::Administrator`] [role].
4451 ///
4452 /// ## Namespaces
4453 ///
4454 /// * Keys in a [namespace] can only be deleted by *N-Administrators*
4455 /// ([`Administrator`][`UserRole::Administrator`] users in a given [namespace]) of that
4456 /// [namespace] (*R-Administrators* have no access to keys in a [namespace]). **NOTE**:
4457 /// Calling [`delete_namespace`][`NetHsm::delete_namespace`] deletes **all keys** in a
4458 /// [namespace]!
4459 /// * System-wide keys can only be deleted by *R-Administrators* (system-wide
4460 /// [`Administrator`][`UserRole::Administrator`] users).
4461 ///
4462 /// # Errors
4463 ///
4464 /// Returns an [`Error::Api`] if deleting the key fails:
4465 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4466 /// * no key identified by `key_id` exists
4467 /// * the used [`Credentials`] are not correct
4468 /// * the used [`Credentials`] are not that of a user in the
4469 /// [`Administrator`][`UserRole::Administrator`] [role]
4470 ///
4471 /// # Examples
4472 ///
4473 /// ```no_run
4474 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
4475 ///
4476 /// # fn main() -> testresult::TestResult {
4477 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4478 /// let nethsm = NetHsm::new(
4479 /// Connection::new(
4480 /// "https://example.org/api/v1".try_into()?,
4481 /// ConnectionSecurity::Unsafe,
4482 /// ),
4483 /// Some(Credentials::new(
4484 /// "admin".parse()?,
4485 /// Some(Passphrase::new("passphrase".to_string())),
4486 /// )),
4487 /// None,
4488 /// None,
4489 /// )?;
4490 ///
4491 /// // delete a key with the Key ID "signing1"
4492 /// nethsm.delete_key(&"signing1".parse()?)?;
4493 /// # Ok(())
4494 /// # }
4495 /// ```
4496 /// [Deletes a key]: https://docs.nitrokey.com/nethsm/operation#delete-key
4497 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4498 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4499 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4500 pub fn delete_key(&self, key_id: &KeyId) -> Result<(), Error> {
4501 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
4502 keys_key_id_delete(&self.create_connection_config(), key_id.as_ref()).map_err(|error| {
4503 Error::Api(format!(
4504 "Deleting key failed: {}",
4505 NetHsmApiError::from(error)
4506 ))
4507 })?;
4508 Ok(())
4509 }
4510
4511 /// Gets [details about a key].
4512 ///
4513 /// Gets [details about a key] identified by `key_id`.
4514 ///
4515 /// This call requires using [`Credentials`] of a user in the
4516 /// [`Administrator`][`UserRole::Administrator`] or [`Operator`][`UserRole::Operator`]
4517 /// [role].
4518 ///
4519 /// ## Namespaces
4520 ///
4521 /// * Users in a [namespace] can only get details about keys in their own [namespace].
4522 /// * System-wide users (not in a [namespace]) can only get details about system-wide keys.
4523 ///
4524 /// # Errors
4525 ///
4526 /// Returns an [`Error::Api`] if getting the key details fails:
4527 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4528 /// * no key identified by `key_id` exists
4529 /// * the used [`Credentials`] are not correct
4530 /// * the used [`Credentials`] are not those of a user in the
4531 /// [`Administrator`][`UserRole::Administrator`] or [`Operator`][`UserRole::Operator`] [role]
4532 ///
4533 /// # Examples
4534 ///
4535 /// ```no_run
4536 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
4537 ///
4538 /// # fn main() -> testresult::TestResult {
4539 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4540 /// let nethsm = NetHsm::new(
4541 /// Connection::new(
4542 /// "https://example.org/api/v1".try_into()?,
4543 /// ConnectionSecurity::Unsafe,
4544 /// ),
4545 /// Some(Credentials::new(
4546 /// "admin".parse()?,
4547 /// Some(Passphrase::new("passphrase".to_string())),
4548 /// )),
4549 /// None,
4550 /// None,
4551 /// )?;
4552 ///
4553 /// // get details on a key with the Key ID "signing1"
4554 /// println!("{:?}", nethsm.get_key(&"signing1".parse()?)?);
4555 /// # Ok(())
4556 /// # }
4557 /// ```
4558 /// [details about a key]: https://docs.nitrokey.com/nethsm/operation#show-key-details
4559 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4560 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4561 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4562 pub fn get_key(&self, key_id: &KeyId) -> Result<PublicKey, Error> {
4563 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
4564 Ok(
4565 keys_key_id_get(&self.create_connection_config(), key_id.as_ref())
4566 .map_err(|error| {
4567 Error::Api(format!(
4568 "Getting key failed: {}",
4569 NetHsmApiError::from(error)
4570 ))
4571 })?
4572 .entity,
4573 )
4574 }
4575
4576 /// Gets a [list of Key IDs] on the NetHSM.
4577 ///
4578 /// Optionally `filter` can be provided for matching against Key IDs.
4579 ///
4580 /// This call requires using [`Credentials`] of a user in the
4581 /// [`Administrator`][`UserRole::Administrator`] or [`Operator`][`UserRole::Operator`]
4582 /// [role].
4583 ///
4584 /// ## Namespaces
4585 ///
4586 /// * Users in a [namespace] can only list key IDs of keys in their own [namespace].
4587 /// * System-wide users (not in a [namespace]) can only list key IDs of system-wide keys.
4588 ///
4589 /// # Errors
4590 ///
4591 /// Returns an [`Error::Api`] if getting the list of Key IDs fails:
4592 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4593 /// * the used [`Credentials`] are not correct
4594 /// * the used [`Credentials`] are not those of a user in the
4595 /// [`Administrator`][`UserRole::Administrator`] or [`Operator`][`UserRole::Operator`] [role]
4596 ///
4597 /// # Examples
4598 ///
4599 /// ```no_run
4600 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase};
4601 ///
4602 /// # fn main() -> testresult::TestResult {
4603 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4604 /// let nethsm = NetHsm::new(
4605 /// Connection::new(
4606 /// "https://example.org/api/v1".try_into()?,
4607 /// ConnectionSecurity::Unsafe,
4608 /// ),
4609 /// Some(Credentials::new(
4610 /// "admin".parse()?,
4611 /// Some(Passphrase::new("passphrase".to_string())),
4612 /// )),
4613 /// None,
4614 /// None,
4615 /// )?;
4616 ///
4617 /// // get all Key IDs
4618 /// println!("{:?}", nethsm.get_keys(None)?);
4619 ///
4620 /// // get all Key IDs that begin with "signing"
4621 /// println!("{:?}", nethsm.get_keys(Some("signing"))?);
4622 /// # Ok(())
4623 /// # }
4624 /// ```
4625 /// [list of Key IDs]: https://docs.nitrokey.com/nethsm/operation#list-keys
4626 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4627 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4628 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4629 pub fn get_keys(&self, filter: Option<&str>) -> Result<Vec<KeyId>, Error> {
4630 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
4631 let valid_keys = {
4632 let mut invalid_keys = Vec::new();
4633 let valid_keys = keys_get(&self.create_connection_config(), filter)
4634 .map_err(|error| {
4635 Error::Api(format!(
4636 "Getting keys failed: {}",
4637 NetHsmApiError::from(error)
4638 ))
4639 })?
4640 .entity
4641 .into_iter()
4642 .filter_map(|x| {
4643 if let Ok(key) = KeyId::new(x.id.clone()) {
4644 Some(key)
4645 } else {
4646 invalid_keys.push(x.id);
4647 None
4648 }
4649 })
4650 .collect::<Vec<KeyId>>();
4651
4652 if !invalid_keys.is_empty() {
4653 return Err(key::Error::InvalidKeyIds {
4654 key_ids: invalid_keys,
4655 }
4656 .into());
4657 }
4658
4659 valid_keys
4660 };
4661
4662 Ok(valid_keys)
4663 }
4664
4665 /// Gets the [public key of a key] on the NetHSM.
4666 ///
4667 /// Gets the [public key of a key] on the NetHSM, identified by `key_id`.
4668 /// The public key is returned in [X.509] Privacy-Enhanced Mail ([PEM]) format.
4669 ///
4670 /// This call requires using [`Credentials`] of a user in the
4671 /// [`Administrator`][`UserRole::Administrator`] or [`Operator`][`UserRole::Operator`]
4672 /// [role].
4673 ///
4674 /// ## Namespaces
4675 ///
4676 /// * Users in a [namespace] can only get public keys of keys in their own [namespace].
4677 /// * System-wide users (not in a [namespace]) can only get public keys of system-wide keys.
4678 ///
4679 /// # Errors
4680 ///
4681 /// Returns an [`Error::Api`] if getting the public key fails:
4682 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4683 /// * no key identified by `key_id` exists
4684 /// * the used [`Credentials`] are not correct
4685 /// * the used [`Credentials`] are not that of a user in the
4686 /// [`Administrator`][`UserRole::Administrator`] or [`Operator`][`UserRole::Operator`] [role]
4687 /// * the targeted key is a symmetric key (i.e. [`KeyType::Generic`]) and therefore can not
4688 /// provide a public key
4689 ///
4690 /// # Examples
4691 ///
4692 /// ```no_run
4693 /// use nethsm::{
4694 /// Connection,
4695 /// ConnectionSecurity,
4696 /// Credentials,
4697 /// KeyMechanism,
4698 /// KeyType,
4699 /// NetHsm,
4700 /// Passphrase,
4701 /// };
4702 ///
4703 /// # fn main() -> testresult::TestResult {
4704 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4705 /// let nethsm = NetHsm::new(
4706 /// Connection::new(
4707 /// "https://example.org/api/v1".try_into()?,
4708 /// ConnectionSecurity::Unsafe,
4709 /// ),
4710 /// Some(Credentials::new(
4711 /// "admin".parse()?,
4712 /// Some(Passphrase::new("passphrase".to_string())),
4713 /// )),
4714 /// None,
4715 /// None,
4716 /// )?;
4717 /// // generate system-wide key with tag
4718 /// nethsm.generate_key(
4719 /// KeyType::Curve25519,
4720 /// vec![KeyMechanism::EdDsaSignature],
4721 /// None,
4722 /// Some("signing1".parse()?),
4723 /// Some(vec!["tag1".to_string()]),
4724 /// )?;
4725 ///
4726 /// // get public key for a key with Key ID "signing1"
4727 /// println!("{:?}", nethsm.get_public_key(&"signing1".parse()?)?);
4728 /// # Ok(())
4729 /// # }
4730 /// ```
4731 /// [public key of a key]: https://docs.nitrokey.com/nethsm/operation#show-key-details
4732 /// [X.509]: https://en.wikipedia.org/wiki/X.509
4733 /// [PEM]: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail
4734 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4735 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4736 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4737 pub fn get_public_key(&self, key_id: &KeyId) -> Result<String, Error> {
4738 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
4739 Ok(
4740 keys_key_id_public_pem_get(&self.create_connection_config(), key_id.as_ref())
4741 .map_err(|error| {
4742 Error::Api(format!(
4743 "Getting public key failed: {}",
4744 NetHsmApiError::from(error)
4745 ))
4746 })?
4747 .entity,
4748 )
4749 }
4750
4751 /// Adds a [tag for a key].
4752 ///
4753 /// Adds `tag` for a key, identified by `key_id`.
4754 ///
4755 /// A [tag for a key] is prerequisite to adding the same tag to a user in the
4756 /// [`Operator`][`UserRole::Operator`] [role] and thus granting it access to the key.
4757 ///
4758 /// This call requires using [`Credentials`] of a user in the
4759 /// [`Administrator`][`UserRole::Administrator`] [role].
4760 ///
4761 /// ## Namespaces
4762 ///
4763 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
4764 /// [namespace]) are only able to tag keys in their own [namespace].
4765 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
4766 /// only able to tag system-wide keys.
4767 ///
4768 /// # Errors
4769 ///
4770 /// Returns an [`Error::Api`] if adding a tag to a key fails:
4771 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4772 /// * no key identified by `key_id` exists
4773 /// * `tag` is already associated with the key
4774 /// * `tag` is invalid
4775 /// * the used [`Credentials`] are not correct
4776 /// * the used [`Credentials`] are not that of a user in the
4777 /// [`Administrator`][`UserRole::Administrator`] [role]
4778 /// * a key in a [namespace] is attempted to be tagged by an *R-Administrator*
4779 /// * a system-wide key is attempted to be tagged by an *N-Administrator*
4780 ///
4781 /// # Examples
4782 ///
4783 /// ```no_run
4784 /// use nethsm::{
4785 /// Connection,
4786 /// ConnectionSecurity,
4787 /// Credentials,
4788 /// KeyMechanism,
4789 /// KeyType,
4790 /// NetHsm,
4791 /// Passphrase,
4792 /// };
4793 ///
4794 /// # fn main() -> testresult::TestResult {
4795 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4796 /// let nethsm = NetHsm::new(
4797 /// Connection::new(
4798 /// "https://example.org/api/v1".try_into()?,
4799 /// ConnectionSecurity::Unsafe,
4800 /// ),
4801 /// Some(Credentials::new(
4802 /// "admin".parse()?,
4803 /// Some(Passphrase::new("passphrase".to_string())),
4804 /// )),
4805 /// None,
4806 /// None,
4807 /// )?;
4808 /// // generate system-wide key with tag
4809 /// nethsm.generate_key(
4810 /// KeyType::Curve25519,
4811 /// vec![KeyMechanism::EdDsaSignature],
4812 /// None,
4813 /// Some("signing1".parse()?),
4814 /// Some(vec!["tag1".to_string()]),
4815 /// )?;
4816 ///
4817 /// // add the tag "important" to a key with Key ID "signing1"
4818 /// nethsm.add_key_tag(&"signing1".parse()?, "important")?;
4819 /// # Ok(())
4820 /// # }
4821 /// ```
4822 /// [tag for a key]: https://docs.nitrokey.com/nethsm/operation#tags-for-keys
4823 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4824 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4825 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4826 pub fn add_key_tag(&self, key_id: &KeyId, tag: &str) -> Result<(), Error> {
4827 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
4828 keys_key_id_restrictions_tags_tag_put(
4829 &self.create_connection_config(),
4830 tag,
4831 key_id.as_ref(),
4832 )
4833 .map_err(|error| {
4834 Error::Api(format!(
4835 "Adding tag for key failed: {}",
4836 NetHsmApiError::from(error)
4837 ))
4838 })?;
4839 Ok(())
4840 }
4841
4842 /// Deletes a [tag from a key].
4843 ///
4844 /// Deletes `tag` from a key, identified by `key_id` on the NetHSM.
4845 ///
4846 /// Deleting a [tag from a key] removes access to it for any user in the
4847 /// [`Operator`][`UserRole::Operator`] [role], that carries the same tag.
4848 ///
4849 /// This call requires using [`Credentials`] of a user in the
4850 /// [`Administrator`][`UserRole::Administrator`] [role].
4851 ///
4852 /// ## Namespaces
4853 ///
4854 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
4855 /// [namespace]) are only able to delete tags from keys in their own [namespace].
4856 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
4857 /// only able to delete tags from system-wide keys.
4858 ///
4859 /// # Errors
4860 ///
4861 /// Returns an [`Error::Api`] if adding a tag to a key fails:
4862 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4863 /// * no key identified by `key_id` exists
4864 /// * `tag` is not associated with the key
4865 /// * the used [`Credentials`] are not correct
4866 /// * the used [`Credentials`] are not that of a user in the
4867 /// [`Administrator`][`UserRole::Administrator`] [role]
4868 /// * the tag for a key in a [namespace] is attempted to be removed by an *R-Administrator*
4869 /// * the tag for a system-wide key is attempted to be removed by an *N-Administrator*
4870 ///
4871 /// # Examples
4872 ///
4873 /// ```no_run
4874 /// use nethsm::{
4875 /// Connection,
4876 /// ConnectionSecurity,
4877 /// Credentials,
4878 /// KeyMechanism,
4879 /// KeyType,
4880 /// NetHsm,
4881 /// Passphrase,
4882 /// };
4883 ///
4884 /// # fn main() -> testresult::TestResult {
4885 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4886 /// let nethsm = NetHsm::new(
4887 /// Connection::new(
4888 /// "https://example.org/api/v1".try_into()?,
4889 /// ConnectionSecurity::Unsafe,
4890 /// ),
4891 /// Some(Credentials::new(
4892 /// "admin".parse()?,
4893 /// Some(Passphrase::new("passphrase".to_string())),
4894 /// )),
4895 /// None,
4896 /// None,
4897 /// )?;
4898 /// // generate system-wide key with tag
4899 /// nethsm.generate_key(
4900 /// KeyType::Curve25519,
4901 /// vec![KeyMechanism::EdDsaSignature],
4902 /// None,
4903 /// Some("signing1".parse()?),
4904 /// Some(vec!["tag1".to_string(), "important".to_string()]),
4905 /// )?;
4906 ///
4907 /// // remove the tag "important" from a key with Key ID "signing1"
4908 /// nethsm.delete_key_tag(&"signing1".parse()?, "important")?;
4909 /// # Ok(())
4910 /// # }
4911 /// ```
4912 /// [tag from a key]: https://docs.nitrokey.com/nethsm/operation#tags-for-keys
4913 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
4914 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
4915 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
4916 pub fn delete_key_tag(&self, key_id: &KeyId, tag: &str) -> Result<(), Error> {
4917 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
4918 keys_key_id_restrictions_tags_tag_delete(
4919 &self.create_connection_config(),
4920 tag,
4921 key_id.as_ref(),
4922 )
4923 .map_err(|error| {
4924 Error::Api(format!(
4925 "Deleting tag for key failed: {}",
4926 NetHsmApiError::from(error)
4927 ))
4928 })?;
4929 Ok(())
4930 }
4931
4932 /// Imports a [certificate for a key].
4933 ///
4934 /// Imports a [certificate for a key] identified by `key_id`.
4935 /// Certificates up to 1 MiB in size are supported.
4936 /// **NOTE**: The imported bytes are not validated!
4937 ///
4938 /// This call requires using [`Credentials`] of a user in the
4939 /// [`Administrator`][`UserRole::Administrator`] [role].
4940 ///
4941 /// ## Namespaces
4942 ///
4943 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
4944 /// [namespace]) are only able to import certificates for keys in their own [namespace].
4945 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
4946 /// only able to import certificates for system-wide keys.
4947 ///
4948 /// # Errors
4949 ///
4950 /// Returns an [`Error::Api`] if importing a [certificate for a key] fails:
4951 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
4952 /// * no key identified by `key_id` exists
4953 /// * the `data` is invalid
4954 /// * the used [`Credentials`] are not correct
4955 /// * the used [`Credentials`] are not that of a user in the
4956 /// [`Administrator`][`UserRole::Administrator`] [role]
4957 ///
4958 /// # Examples
4959 ///
4960 /// ```no_run
4961 /// use std::time::SystemTime;
4962 /// use nethsm::{
4963 /// Connection,
4964 /// ConnectionSecurity,
4965 /// Credentials,
4966 /// KeyMechanism,
4967 /// KeyType,
4968 /// NetHsm,
4969 /// OpenPgpKeyUsageFlags,
4970 /// OpenPgpVersion,
4971 /// Passphrase,
4972 /// UserRole,
4973 /// };
4974 ///
4975 /// # fn main() -> testresult::TestResult {
4976 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
4977 /// let nethsm = NetHsm::new(
4978 /// Connection::new(
4979 /// "https://example.org/api/v1".try_into()?,
4980 /// ConnectionSecurity::Unsafe,
4981 /// ),
4982 /// Some(Credentials::new(
4983 /// "admin".parse()?,
4984 /// Some(Passphrase::new("passphrase".to_string())),
4985 /// )),
4986 /// None,
4987 /// None,
4988 /// )?;
4989 /// // add a system-wide user in the Operator role
4990 /// nethsm.add_user(
4991 /// "Operator1".to_string(),
4992 /// UserRole::Operator,
4993 /// Passphrase::new("operator-passphrase".to_string()),
4994 /// Some("operator1".parse()?),
4995 /// )?;
4996 /// // generate system-wide key with tag
4997 /// nethsm.generate_key(
4998 /// KeyType::Curve25519,
4999 /// vec![KeyMechanism::EdDsaSignature],
5000 /// None,
5001 /// Some("signing1".parse()?),
5002 /// Some(vec!["tag1".to_string()]),
5003 /// )?;
5004 /// // tag system-wide user in Operator role for access to signing key
5005 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
5006 /// // use the Operator credentials to create an OpenPGP certificate for a key
5007 /// nethsm.use_credentials(&"operator1".parse()?)?;
5008 /// let openpgp_cert = nethsm.create_openpgp_cert(
5009 /// &"signing1".parse()?,
5010 /// OpenPgpKeyUsageFlags::default(),
5011 /// "Test <test@example.org>".parse()?,
5012 /// SystemTime::now().into(),
5013 /// OpenPgpVersion::V4,
5014 /// )?;
5015 ///
5016 /// // use the Administrator credentials to import the OpenPGP certificate as certificate for the key
5017 /// nethsm.use_credentials(&"admin".parse()?)?;
5018 /// assert!(nethsm.get_key_certificate(&"signing1".parse()?).is_err());
5019 /// nethsm.import_key_certificate(&"signing1".parse()?, openpgp_cert)?;
5020 /// assert!(nethsm.get_key_certificate(&"signing1".parse()?).is_ok());
5021 /// # Ok(())
5022 /// # }
5023 /// ```
5024 /// [certificate for a key]: https://docs.nitrokey.com/nethsm/operation#key-certificates
5025 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
5026 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
5027 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
5028 pub fn import_key_certificate(&self, key_id: &KeyId, data: Vec<u8>) -> Result<(), Error> {
5029 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
5030 keys_key_id_cert_put(&self.create_connection_config(), key_id.as_ref(), data).map_err(
5031 |error| {
5032 Error::Api(format!(
5033 "Importing certificate for key failed: {}",
5034 NetHsmApiError::from(error)
5035 ))
5036 },
5037 )?;
5038 Ok(())
5039 }
5040
5041 /// Gets the [certificate for a key].
5042 ///
5043 /// Gets the [certificate for a key] identified by `key_id`.
5044 ///
5045 /// This call requires using [`Credentials`] of a user in the [`Operator`][`UserRole::Operator`]
5046 /// or [`Administrator`][`UserRole::Administrator`] [role].
5047 ///
5048 /// ## Namespaces
5049 ///
5050 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
5051 /// [namespace]) are only able to get certificates for keys in their own [namespace].
5052 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
5053 /// only able to get certificates for system-wide keys.
5054 ///
5055 /// # Errors
5056 ///
5057 /// Returns an [`Error::Api`] if getting the [certificate for a key] fails:
5058 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
5059 /// * no key identified by `key_id` exists
5060 /// * no certificate is associated with the key
5061 /// * the used [`Credentials`] are not correct
5062 /// * the used [`Credentials`] are not those of a user in the [`Operator`][`UserRole::Operator`]
5063 /// or [`Administrator`][`UserRole::Administrator`] [role]
5064 ///
5065 /// # Examples
5066 ///
5067 /// ```no_run
5068 /// use std::time::SystemTime;
5069 /// use nethsm::{
5070 /// Connection,
5071 /// ConnectionSecurity,
5072 /// Credentials,
5073 /// KeyMechanism,
5074 /// KeyType,
5075 /// NetHsm,
5076 /// OpenPgpKeyUsageFlags,
5077 /// OpenPgpVersion,
5078 /// Passphrase,
5079 /// UserRole,
5080 /// };
5081 ///
5082 /// # fn main() -> testresult::TestResult {
5083 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
5084 /// let nethsm = NetHsm::new(
5085 /// Connection::new(
5086 /// "https://example.org/api/v1".try_into()?,
5087 /// ConnectionSecurity::Unsafe,
5088 /// ),
5089 /// Some(Credentials::new(
5090 /// "admin".parse()?,
5091 /// Some(Passphrase::new("passphrase".to_string())),
5092 /// )),
5093 /// None,
5094 /// None,
5095 /// )?;
5096 /// // add a system-wide user in the Operator role
5097 /// nethsm.add_user(
5098 /// "Operator1".to_string(),
5099 /// UserRole::Operator,
5100 /// Passphrase::new("operator-passphrase".to_string()),
5101 /// Some("operator1".parse()?),
5102 /// )?;
5103 /// // generate system-wide key with tag
5104 /// nethsm.generate_key(
5105 /// KeyType::Curve25519,
5106 /// vec![KeyMechanism::EdDsaSignature],
5107 /// None,
5108 /// Some("signing1".parse()?),
5109 /// Some(vec!["tag1".to_string()]),
5110 /// )?;
5111 /// // tag system-wide user in Operator role for access to signing key
5112 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
5113 /// // use the Operator credentials to create an OpenPGP certificate for a key
5114 /// nethsm.use_credentials(&"operator1".parse()?)?;
5115 /// let openpgp_cert = nethsm.create_openpgp_cert(
5116 /// &"signing1".parse()?,
5117 /// OpenPgpKeyUsageFlags::default(),
5118 /// "Test <test@example.org>".parse()?,
5119 /// SystemTime::now().into(),
5120 /// OpenPgpVersion::V4,
5121 /// )?;
5122 /// // use the Administrator credentials to import the OpenPGP certificate as certificate for the key
5123 /// nethsm.use_credentials(&"admin".parse()?)?;
5124 /// nethsm.import_key_certificate(&"signing1".parse()?, openpgp_cert)?;
5125 ///
5126 /// // get the certificate associated with a key
5127 /// println!("{:?}", nethsm.get_key_certificate(&"signing1".parse()?)?);
5128 /// # Ok(())
5129 /// # }
5130 /// ```
5131 /// [key certificate]: https://docs.nitrokey.com/nethsm/operation#key-certificates
5132 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
5133 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
5134 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
5135 pub fn get_key_certificate(&self, key_id: &KeyId) -> Result<Vec<u8>, Error> {
5136 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
5137 Ok(
5138 keys_key_id_cert_get(&self.create_connection_config(), key_id.as_ref())
5139 .map_err(|error| {
5140 Error::Api(format!(
5141 "Getting certificate for key failed: {}",
5142 NetHsmApiError::from(error)
5143 ))
5144 })?
5145 .entity,
5146 )
5147 }
5148
5149 /// Deletes the [certificate for a key].
5150 ///
5151 /// Deletes the [certificate for a key] identified by `key_id`.
5152 ///
5153 /// This call requires using [`Credentials`] of a user in the
5154 /// [`Administrator`][`UserRole::Administrator`] [role].
5155 ///
5156 /// ## Namespaces
5157 ///
5158 /// * *N-Administrators* ([`Administrator`][`UserRole::Administrator`] users in a given
5159 /// [namespace]) are only able to delete certificates for keys in their own [namespace].
5160 /// * *R-Administrators* (system-wide [`Administrator`][`UserRole::Administrator`] users) are
5161 /// only able to delete certificates for system-wide keys.
5162 ///
5163 /// # Errors
5164 ///
5165 /// Returns an [`Error::Api`] if deleting the [certificate for a key] fails:
5166 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
5167 /// * no key identified by `key_id` exists
5168 /// * no certificate is associated with the key
5169 /// * the used [`Credentials`] are not correct
5170 /// * the used [`Credentials`] are not that of a user in the
5171 /// [`Administrator`][`UserRole::Administrator`] [role]
5172 ///
5173 /// # Examples
5174 ///
5175 /// ```no_run
5176 /// use std::time::SystemTime;
5177 /// use nethsm::{
5178 /// Connection,
5179 /// ConnectionSecurity,
5180 /// Credentials,
5181 /// KeyMechanism,
5182 /// KeyType,
5183 /// NetHsm,
5184 /// OpenPgpKeyUsageFlags,
5185 /// OpenPgpVersion,
5186 /// Passphrase,
5187 /// UserRole,
5188 /// };
5189 ///
5190 /// # fn main() -> testresult::TestResult {
5191 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
5192 /// let nethsm = NetHsm::new(
5193 /// Connection::new(
5194 /// "https://example.org/api/v1".try_into()?,
5195 /// ConnectionSecurity::Unsafe,
5196 /// ),
5197 /// Some(Credentials::new(
5198 /// "admin".parse()?,
5199 /// Some(Passphrase::new("passphrase".to_string())),
5200 /// )),
5201 /// None,
5202 /// None,
5203 /// )?;
5204 /// // add a system-wide user in the Operator role
5205 /// nethsm.add_user(
5206 /// "Operator1".to_string(),
5207 /// UserRole::Operator,
5208 /// Passphrase::new("operator-passphrase".to_string()),
5209 /// Some("operator1".parse()?),
5210 /// )?;
5211 /// // generate system-wide key with tag
5212 /// nethsm.generate_key(
5213 /// KeyType::Curve25519,
5214 /// vec![KeyMechanism::EdDsaSignature],
5215 /// None,
5216 /// Some("signing1".parse()?),
5217 /// Some(vec!["tag1".to_string()]),
5218 /// )?;
5219 /// // tag system-wide user in Operator role for access to signing key
5220 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
5221 /// // use the Operator credentials to create an OpenPGP certificate for a key
5222 /// nethsm.use_credentials(&"operator1".parse()?)?;
5223 /// let openpgp_cert = nethsm.create_openpgp_cert(
5224 /// &"signing1".parse()?,
5225 /// OpenPgpKeyUsageFlags::default(),
5226 /// "Test <test@example.org>".parse()?,
5227 /// SystemTime::now().into(),
5228 /// OpenPgpVersion::V4,
5229 /// )?;
5230 /// // use the Administrator credentials to import the OpenPGP certificate as certificate for the key
5231 /// nethsm.use_credentials(&"admin".parse()?)?;
5232 /// nethsm.import_key_certificate(&"signing1".parse()?, openpgp_cert)?;
5233 ///
5234 /// // delete a certificate for a key with Key ID "signing1"
5235 /// assert!(nethsm.delete_key_certificate(&"signing1".parse()?).is_ok());
5236 /// nethsm.delete_key_certificate(&"signing1".parse()?)?;
5237 /// assert!(nethsm.delete_key_certificate(&"signing1".parse()?).is_err());
5238 /// # Ok(())
5239 /// # }
5240 /// ```
5241 /// [certificate for a key]: https://docs.nitrokey.com/nethsm/operation#key-certificates
5242 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
5243 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
5244 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
5245 pub fn delete_key_certificate(&self, key_id: &KeyId) -> Result<(), Error> {
5246 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
5247 keys_key_id_cert_delete(&self.create_connection_config(), key_id.as_ref()).map_err(
5248 |error| {
5249 Error::Api(format!(
5250 "Deleting certificate for key failed: {}",
5251 NetHsmApiError::from(error)
5252 ))
5253 },
5254 )?;
5255 Ok(())
5256 }
5257
5258 /// Gets a [Certificate Signing Request for a key].
5259 ///
5260 /// Returns a Certificate Signing Request ([CSR]) for a key, identified by `key_id` in [PKCS#10]
5261 /// format based on a provided [`DistinguishedName`].
5262 ///
5263 /// This call requires using [`Credentials`] of a user in the [`Operator`][`UserRole::Operator`]
5264 /// or [`Administrator`][`UserRole::Administrator`] [role].
5265 ///
5266 /// ## Namespaces
5267 ///
5268 /// * Users in a [namespace] only have access to keys in their own [namespace]
5269 /// * System-wide users only have access to system-wide keys (not in a [namespace]).
5270 ///
5271 /// # Errors
5272 ///
5273 /// Returns an [`Error::Api`] if getting a CSR for a key fails:
5274 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
5275 /// * no key identified by `key_id` exists
5276 /// * the used [`Credentials`] are not correct
5277 /// * the used [`Credentials`] are not those of a user in the [`Operator`][`UserRole::Operator`]
5278 /// or [`Administrator`][`UserRole::Administrator`] [role]
5279 ///
5280 /// # Examples
5281 ///
5282 /// ```no_run
5283 /// use nethsm::{
5284 /// Connection,
5285 /// ConnectionSecurity,
5286 /// Credentials,
5287 /// DistinguishedName,
5288 /// KeyMechanism,
5289 /// KeyType,
5290 /// NetHsm,
5291 /// Passphrase,
5292 /// };
5293 ///
5294 /// # fn main() -> testresult::TestResult {
5295 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
5296 /// let nethsm = NetHsm::new(
5297 /// Connection::new(
5298 /// "https://example.org/api/v1".try_into()?,
5299 /// ConnectionSecurity::Unsafe,
5300 /// ),
5301 /// Some(Credentials::new(
5302 /// "admin".parse()?,
5303 /// Some(Passphrase::new("passphrase".to_string())),
5304 /// )),
5305 /// None,
5306 /// None,
5307 /// )?;
5308 /// // generate system-wide key with tag
5309 /// nethsm.generate_key(
5310 /// KeyType::Curve25519,
5311 /// vec![KeyMechanism::EdDsaSignature],
5312 /// None,
5313 /// Some("signing1".parse()?),
5314 /// Some(vec!["tag1".to_string()]),
5315 /// )?;
5316 ///
5317 /// // get a CSR for a key
5318 /// println!(
5319 /// "{}",
5320 /// nethsm.get_key_csr(
5321 /// &"signing1".parse()?,
5322 /// DistinguishedName {
5323 /// country_name: Some("DE".to_string()),
5324 /// state_or_province_name: Some("Berlin".to_string()),
5325 /// locality_name: Some("Berlin".to_string()),
5326 /// organization_name: Some("Foobar Inc".to_string()),
5327 /// organizational_unit_name: Some("Department of Foo".to_string()),
5328 /// common_name: "Foobar Inc".to_string(),
5329 /// email_address: Some("foobar@mcfooface.com".to_string()),
5330 /// }
5331 /// )?
5332 /// );
5333 /// # Ok(())
5334 /// # }
5335 /// ```
5336 /// [Certificate Signing Request for a key]: https://docs.nitrokey.com/nethsm/operation#key-certificate-signing-requests
5337 /// [CSR]: https://en.wikipedia.org/wiki/Certificate_signing_request
5338 /// [PKCS#10]: https://en.wikipedia.org/wiki/Certificate_signing_request#Structure_of_a_PKCS_#10_CSR
5339 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
5340 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
5341 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
5342 pub fn get_key_csr(
5343 &self,
5344 key_id: &KeyId,
5345 distinguished_name: DistinguishedName,
5346 ) -> Result<String, Error> {
5347 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
5348 Ok(keys_key_id_csr_pem_post(
5349 &self.create_connection_config(),
5350 key_id.as_ref(),
5351 distinguished_name,
5352 )
5353 .map_err(|error| {
5354 Error::Api(format!(
5355 "Getting CSR for key failed: {}",
5356 NetHsmApiError::from(error)
5357 ))
5358 })?
5359 .entity)
5360 }
5361
5362 /// [Signs] a digest using a key.
5363 ///
5364 /// [Signs] a `digest` using a key identified by `key_id`.
5365 ///
5366 /// **NOTE**: This function offers low-level access for signing [digests]. Use
5367 /// [`sign`][`NetHsm::sign`] for signing a message.
5368 ///
5369 /// The `digest` must be of appropriate type depending on `signature_type`:
5370 /// * [`SignatureType::Pkcs1`], [`SignatureType::PssSha256`] and [`SignatureType::EcdsaP256`]
5371 /// require a [SHA-256] digest
5372 /// * [`SignatureType::PssMd5`] requires an [MD5] digest
5373 /// * [`SignatureType::PssSha1`] requires a [SHA-1] digest
5374 /// * [`SignatureType::PssSha224`] and [`SignatureType::EcdsaP224`] require a [SHA-224] digest
5375 /// * [`SignatureType::PssSha384`] and [`SignatureType::EcdsaP384`] require a [SHA-384] digest
5376 /// * [`SignatureType::PssSha512`] and [`SignatureType::EcdsaP521`] require a [SHA-521] digest
5377 /// * [`SignatureType::EdDsa`] requires no digest (`digest` is the message)
5378 ///
5379 /// The returned data depends on the chosen [`SignatureType`]:
5380 ///
5381 /// * [`SignatureType::Pkcs1`] returns the [PKCS 1] padded signature (no signature algorithm OID
5382 /// prepended, since the used hash is not known).
5383 /// * [`SignatureType::PssMd5`], [`SignatureType::PssSha1`], [`SignatureType::PssSha224`],
5384 /// [`SignatureType::PssSha256`], [`SignatureType::PssSha384`] and
5385 /// [`SignatureType::PssSha512`] return the [EMSA-PSS] encoded signature.
5386 /// * [`SignatureType::EdDsa`] returns the encoding as specified in [RFC 8032 (5.1.6)] (`r`
5387 /// appended with `s` (each 32 bytes), in total 64 bytes).
5388 /// * [`SignatureType::EcdsaP224`], [`SignatureType::EcdsaP256`], [`SignatureType::EcdsaP384`]
5389 /// and [`SignatureType::EcdsaP521`] return the [ASN.1] [DER] encoded signature (a sequence of
5390 /// integer `r` and integer `s`).
5391 ///
5392 /// This call requires using [`Credentials`] of a user in the [`Operator`][`UserRole::Operator`]
5393 /// [role], which carries a tag (see [`add_user_tag`][`NetHsm::add_user_tag`]) matching one
5394 /// of the tags of the targeted key (see [`add_key_tag`][`NetHsm::add_key_tag`]).
5395 ///
5396 /// ## Namespaces
5397 ///
5398 /// * [`Operator`][`UserRole::Operator`] users in a [namespace] only have access to keys in
5399 /// their own [namespace].
5400 /// * System-wide [`Operator`][`UserRole::Operator`] users only have access to system-wide keys.
5401 ///
5402 /// # Errors
5403 ///
5404 /// Returns an [`Error::Api`] if signing the `digest` fails:
5405 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
5406 /// * no key identified by `key_id` exists on the NetHSM
5407 /// * the chosen [`SignatureType`] is incompatible with the targeted key
5408 /// * the chosen `digest` is incompatible with the [`SignatureType`]
5409 /// * the [`Operator`][`UserRole::Operator`] user does not have access to the key (e.g.
5410 /// different [namespace])
5411 /// * the [`Operator`][`UserRole::Operator`] user does not carry a tag matching one of the key
5412 /// tags
5413 /// * the used [`Credentials`] are not correct
5414 /// * the used [`Credentials`] are not that of a user in the [`Operator`][`UserRole::Operator`]
5415 /// [role]
5416 ///
5417 /// # Examples
5418 ///
5419 /// ```no_run
5420 /// use nethsm::{
5421 /// Connection,
5422 /// ConnectionSecurity,
5423 /// Credentials,
5424 /// KeyMechanism,
5425 /// KeyType,
5426 /// NetHsm,
5427 /// Passphrase,
5428 /// SignatureType,
5429 /// UserRole,
5430 /// };
5431 ///
5432 /// # fn main() -> testresult::TestResult {
5433 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
5434 /// let nethsm = NetHsm::new(
5435 /// Connection::new(
5436 /// "https://example.org/api/v1".try_into()?,
5437 /// ConnectionSecurity::Unsafe,
5438 /// ),
5439 /// Some(Credentials::new(
5440 /// "admin".parse()?,
5441 /// Some(Passphrase::new("passphrase".to_string())),
5442 /// )),
5443 /// None,
5444 /// None,
5445 /// )?;
5446 /// // add a system-wide user in the Operator role
5447 /// nethsm.add_user(
5448 /// "Operator1".to_string(),
5449 /// UserRole::Operator,
5450 /// Passphrase::new("operator-passphrase".to_string()),
5451 /// Some("operator1".parse()?),
5452 /// )?;
5453 /// // generate system-wide key with tag
5454 /// nethsm.generate_key(
5455 /// KeyType::Curve25519,
5456 /// vec![KeyMechanism::EdDsaSignature],
5457 /// None,
5458 /// Some("signing1".parse()?),
5459 /// Some(vec!["tag1".to_string()]),
5460 /// )?;
5461 /// // tag system-wide user in Operator role for access to signing key
5462 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
5463 ///
5464 /// // create an ed25519 signature
5465 /// nethsm.use_credentials(&"operator1".parse()?)?;
5466 /// println!(
5467 /// "{:?}",
5468 /// nethsm.sign_digest(&"signing1".parse()?, SignatureType::EdDsa, &[0, 1, 2])?
5469 /// );
5470 /// # Ok(())
5471 /// # }
5472 /// ```
5473 /// [Signs]: https://docs.nitrokey.com/nethsm/operation#sign
5474 /// [digests]: https://en.wikipedia.org/wiki/Cryptographic_hash_function
5475 /// [SHA-256]: https://en.wikipedia.org/wiki/SHA-2
5476 /// [MD5]: https://en.wikipedia.org/wiki/MD5
5477 /// [SHA-1]: https://en.wikipedia.org/wiki/SHA-1
5478 /// [SHA-224]: https://en.wikipedia.org/wiki/SHA-2
5479 /// [SHA-384]: https://en.wikipedia.org/wiki/SHA-2
5480 /// [SHA-521]: https://en.wikipedia.org/wiki/SHA-2
5481 /// [PKCS 1]: https://en.wikipedia.org/wiki/PKCS_1
5482 /// [EMSA-PSS]: https://en.wikipedia.org/wiki/PKCS_1
5483 /// [RFC 8032 (5.1.6)]: https://www.rfc-editor.org/rfc/rfc8032#section-5.1.6
5484 /// [ASN.1]: https://en.wikipedia.org/wiki/ASN.1
5485 /// [DER]: https://en.wikipedia.org/wiki/X.690#DER_encoding
5486 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
5487 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
5488 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
5489 pub fn sign_digest(
5490 &self,
5491 key_id: &KeyId,
5492 signature_type: SignatureType,
5493 digest: &[u8],
5494 ) -> Result<Vec<u8>, Error> {
5495 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
5496 // decode base64 encoded data from the API
5497 Base64::decode_vec(
5498 &keys_key_id_sign_post(
5499 &self.create_connection_config(),
5500 key_id.as_ref(),
5501 SignRequestData::new(signature_type.into(), Base64::encode_string(digest)),
5502 )
5503 .map_err(|error| {
5504 Error::Api(format!(
5505 "Signing message failed: {}",
5506 NetHsmApiError::from(error)
5507 ))
5508 })?
5509 .entity
5510 .signature,
5511 )
5512 .map_err(Error::Base64Decode)
5513 }
5514
5515 /// [Signs] a message using a key.
5516 ///
5517 /// [Signs] a `message` using a key identified by `key_id` based on a specific `signature_type`.
5518 ///
5519 /// The `message` should not be [hashed], as this function takes care of it based on the
5520 /// provided [`SignatureType`]. For lower level access, see
5521 /// [`sign_digest`][`NetHsm::sign_digest`].
5522 ///
5523 /// The returned data depends on the chosen [`SignatureType`]:
5524 ///
5525 /// * [`SignatureType::Pkcs1`] returns the [PKCS 1] padded signature (no signature algorithm OID
5526 /// prepended, since the used hash is not known).
5527 /// * [`SignatureType::PssMd5`], [`SignatureType::PssSha1`], [`SignatureType::PssSha224`],
5528 /// [`SignatureType::PssSha256`], [`SignatureType::PssSha384`] and
5529 /// [`SignatureType::PssSha512`] return the [EMSA-PSS] encoded signature.
5530 /// * [`SignatureType::EdDsa`] returns the encoding as specified in [RFC 8032 (5.1.6)] (`r`
5531 /// appended with `s` (each 32 bytes), in total 64 bytes).
5532 /// * [`SignatureType::EcdsaP224`], [`SignatureType::EcdsaP256`], [`SignatureType::EcdsaP384`]
5533 /// and [`SignatureType::EcdsaP521`] return the [ASN.1] [DER] encoded signature (a sequence of
5534 /// integer `r` and integer `s`).
5535 ///
5536 /// This call requires using [`Credentials`] of a user in the [`Operator`][`UserRole::Operator`]
5537 /// [role], which carries a tag (see [`add_user_tag`][`NetHsm::add_user_tag`]) matching one
5538 /// of the tags of the targeted key (see [`add_key_tag`][`NetHsm::add_key_tag`]).
5539 ///
5540 /// ## Namespaces
5541 ///
5542 /// * [`Operator`][`UserRole::Operator`] users in a [namespace] only have access to keys in
5543 /// their own [namespace].
5544 /// * System-wide [`Operator`][`UserRole::Operator`] users only have access to system-wide keys.
5545 ///
5546 /// # Errors
5547 ///
5548 /// Returns an [`Error::Api`] if signing the `message` fails:
5549 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
5550 /// * no key identified by `key_id` exists on the NetHSM
5551 /// * the chosen [`SignatureType`] is incompatible with the targeted key
5552 /// * the [`Operator`][`UserRole::Operator`] user does not have access to the key (e.g.
5553 /// different [namespace])
5554 /// * the [`Operator`][`UserRole::Operator`] user does not carry a tag matching one of the key
5555 /// tags
5556 /// * the used [`Credentials`] are not correct
5557 /// * the used [`Credentials`] are not that of a user in the [`Operator`][`UserRole::Operator`]
5558 /// [role]
5559 ///
5560 /// # Examples
5561 ///
5562 /// ```no_run
5563 /// use nethsm::{
5564 /// Connection,
5565 /// ConnectionSecurity,
5566 /// Credentials,
5567 /// KeyMechanism,
5568 /// KeyType,
5569 /// NetHsm,
5570 /// Passphrase,
5571 /// SignatureType,
5572 /// UserRole,
5573 /// };
5574 ///
5575 /// # fn main() -> testresult::TestResult {
5576 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
5577 /// let nethsm = NetHsm::new(
5578 /// Connection::new(
5579 /// "https://example.org/api/v1".try_into()?,
5580 /// ConnectionSecurity::Unsafe,
5581 /// ),
5582 /// Some(Credentials::new(
5583 /// "admin".parse()?,
5584 /// Some(Passphrase::new("passphrase".to_string())),
5585 /// )),
5586 /// None,
5587 /// None,
5588 /// )?;
5589 /// // add a system-wide user in the Operator role
5590 /// nethsm.add_user(
5591 /// "Operator1".to_string(),
5592 /// UserRole::Operator,
5593 /// Passphrase::new("operator-passphrase".to_string()),
5594 /// Some("operator1".parse()?),
5595 /// )?;
5596 /// // generate system-wide key with tag
5597 /// nethsm.generate_key(
5598 /// KeyType::Curve25519,
5599 /// vec![KeyMechanism::EdDsaSignature],
5600 /// None,
5601 /// Some("signing1".parse()?),
5602 /// Some(vec!["tag1".to_string()]),
5603 /// )?;
5604 /// // tag system-wide user in Operator role for access to signing key
5605 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
5606 ///
5607 /// // create an ed25519 signature
5608 /// println!(
5609 /// "{:?}",
5610 /// nethsm.sign(&"signing1".parse()?, SignatureType::EdDsa, b"message")?
5611 /// );
5612 /// # Ok(())
5613 /// # }
5614 /// ```
5615 /// [Signs]: https://docs.nitrokey.com/nethsm/operation#sign
5616 /// [hashed]: https://en.wikipedia.org/wiki/Cryptographic_hash_function
5617 /// [PKCS 1]: https://en.wikipedia.org/wiki/PKCS_1
5618 /// [EMSA-PSS]: https://en.wikipedia.org/wiki/PKCS_1
5619 /// [RFC 8032 (5.1.6)]: https://www.rfc-editor.org/rfc/rfc8032#section-5.1.6
5620 /// [ASN.1]: https://en.wikipedia.org/wiki/ASN.1
5621 /// [DER]: https://en.wikipedia.org/wiki/X.690#DER_encoding
5622 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
5623 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
5624 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
5625 pub fn sign(
5626 &self,
5627 key_id: &KeyId,
5628 signature_type: SignatureType,
5629 message: &[u8],
5630 ) -> Result<Vec<u8>, Error> {
5631 // Some algorithms require the data to be hashed first
5632 // The API requires data to be base64 encoded
5633 let message = match signature_type {
5634 SignatureType::Pkcs1 | SignatureType::PssSha256 | SignatureType::EcdsaP256 => {
5635 let mut hasher = Sha256::new();
5636 hasher.update(message);
5637 &hasher.finalize()[..]
5638 }
5639 SignatureType::PssMd5 => {
5640 let mut hasher = Md5::new();
5641 hasher.update(message);
5642 &hasher.finalize()[..]
5643 }
5644 SignatureType::PssSha1 => {
5645 let mut hasher = Sha1::new();
5646 hasher.update(message);
5647 &hasher.finalize()[..]
5648 }
5649 SignatureType::PssSha224 | SignatureType::EcdsaP224 => {
5650 let mut hasher = Sha224::new();
5651 hasher.update(message);
5652 &hasher.finalize()[..]
5653 }
5654 SignatureType::PssSha384 | SignatureType::EcdsaP384 => {
5655 let mut hasher = Sha384::new();
5656 hasher.update(message);
5657 &hasher.finalize()[..]
5658 }
5659 SignatureType::PssSha512 | SignatureType::EcdsaP521 => {
5660 let mut hasher = Sha512::new();
5661 hasher.update(message);
5662 &hasher.finalize()[..]
5663 }
5664 SignatureType::EdDsa => message,
5665 };
5666
5667 self.sign_digest(key_id, signature_type, message)
5668 }
5669
5670 /// [Encrypts] a message using a [symmetric key].
5671 ///
5672 /// [Encrypts] a `message` using a [symmetric key] identified by `key_id`, a specific
5673 /// [`EncryptMode`] `mode` and initialization vector `iv`.
5674 ///
5675 /// The targeted key must be of type [`KeyType::Generic`] and feature the mechanisms
5676 /// [`KeyMechanism::AesDecryptionCbc`] and [`KeyMechanism::AesEncryptionCbc`].
5677 ///
5678 /// This call requires using [`Credentials`] of a user in the [`Operator`][`UserRole::Operator`]
5679 /// [role], which carries a tag (see [`add_user_tag`][`NetHsm::add_user_tag`]) matching one
5680 /// of the tags of the targeted key (see [`add_key_tag`][`NetHsm::add_key_tag`]).
5681 ///
5682 /// ## Namespaces
5683 ///
5684 /// * [`Operator`][`UserRole::Operator`] users in a [namespace] only have access to keys in
5685 /// their own [namespace].
5686 /// * System-wide [`Operator`][`UserRole::Operator`] users only have access to system-wide keys.
5687 ///
5688 /// # Errors
5689 ///
5690 /// Returns an [`Error::Api`] if encrypting the `message` fails:
5691 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
5692 /// * no key identified by `key_id` exists on the NetHSM
5693 /// * the chosen `mode` is incompatible with the targeted key
5694 /// * the [`Operator`][`UserRole::Operator`] user does not have access to the key (e.g.
5695 /// different [namespace])
5696 /// * the [`Operator`][`UserRole::Operator`] user does not carry a tag matching one of the key
5697 /// tags
5698 /// * the used [`Credentials`] are not correct
5699 /// * the used [`Credentials`] are not that of a user in the [`Operator`][`UserRole::Operator`]
5700 /// [role]
5701 ///
5702 /// # Examples
5703 ///
5704 /// ```no_run
5705 /// use nethsm::{
5706 /// Connection,
5707 /// ConnectionSecurity,
5708 /// Credentials,
5709 /// EncryptMode,
5710 /// KeyMechanism,
5711 /// KeyType,
5712 /// NetHsm,
5713 /// Passphrase,
5714 /// UserRole,
5715 /// };
5716 ///
5717 /// # fn main() -> testresult::TestResult {
5718 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
5719 /// let nethsm = NetHsm::new(
5720 /// Connection::new(
5721 /// "https://example.org/api/v1".try_into()?,
5722 /// ConnectionSecurity::Unsafe,
5723 /// ),
5724 /// Some(Credentials::new(
5725 /// "admin".parse()?,
5726 /// Some(Passphrase::new("passphrase".to_string())),
5727 /// )),
5728 /// None,
5729 /// None,
5730 /// )?;
5731 /// // add a system-wide user in the Operator role
5732 /// nethsm.add_user(
5733 /// "Operator1".to_string(),
5734 /// UserRole::Operator,
5735 /// Passphrase::new("operator-passphrase".to_string()),
5736 /// Some("operator1".parse()?),
5737 /// )?;
5738 /// // generate system-wide key with tag
5739 /// nethsm.generate_key(
5740 /// KeyType::Generic,
5741 /// vec![KeyMechanism::AesDecryptionCbc, KeyMechanism::AesEncryptionCbc],
5742 /// Some(128),
5743 /// Some("encryption1".parse()?),
5744 /// Some(vec!["tag1".to_string()]),
5745 /// )?;
5746 /// // tag system-wide user in Operator role for access to signing key
5747 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
5748 ///
5749 /// // assuming we have an AES128 encryption key, the message must be a multiple of 32 bytes long
5750 /// let message = b"Hello World! This is a message!!";
5751 /// // we have an AES128 encryption key. the initialization vector must be a multiple of 16 bytes long
5752 /// let iv = b"This is unsafe!!";
5753 ///
5754 /// // encrypt message using
5755 /// println!(
5756 /// "{:?}",
5757 /// nethsm.encrypt(&"encryption1".parse()?, EncryptMode::AesCbc, message, Some(iv))?
5758 /// );
5759 /// # Ok(())
5760 /// # }
5761 /// ```
5762 /// [Encrypts]: https://docs.nitrokey.com/nethsm/operation#encrypt
5763 /// [symmetric key]: https://en.wikipedia.org/wiki/Symmetric-key_algorithm
5764 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
5765 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
5766 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
5767 pub fn encrypt(
5768 &self,
5769 key_id: &KeyId,
5770 mode: EncryptMode,
5771 message: &[u8],
5772 iv: Option<&[u8]>,
5773 ) -> Result<Vec<u8>, Error> {
5774 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
5775 // the API requires data to be base64 encoded
5776 let message = Base64::encode_string(message);
5777 let iv = iv.map(Base64::encode_string);
5778
5779 // decode base64 encoded data from the API
5780 Base64::decode_vec(
5781 &keys_key_id_encrypt_post(
5782 &self.create_connection_config(),
5783 key_id.as_ref(),
5784 EncryptRequestData {
5785 mode: mode.into(),
5786 message,
5787 iv,
5788 },
5789 )
5790 .map_err(|error| {
5791 Error::Api(format!(
5792 "Encrypting message failed: {}",
5793 NetHsmApiError::from(error)
5794 ))
5795 })?
5796 .entity
5797 .encrypted,
5798 )
5799 .map_err(Error::Base64Decode)
5800 }
5801
5802 /// [Decrypts] a message using a key.
5803 ///
5804 /// [Decrypts] a `message` using a key identified by `key_id`, a specific [`DecryptMode`] `mode`
5805 /// and initialization vector `iv`.
5806 ///
5807 /// This function can be used to decrypt messages encrypted using a [symmetric key] (e.g. using
5808 /// [`encrypt`][`NetHsm::encrypt`]) by providing [`DecryptMode::AesCbc`] as `mode`. The targeted
5809 /// key must be of type [`KeyType::Generic`] and feature the mechanisms
5810 /// [`KeyMechanism::AesDecryptionCbc`] and [`KeyMechanism::AesEncryptionCbc`].
5811 ///
5812 /// Decryption for messages encrypted using an [asymmetric key] is also possible. Foreign
5813 /// entities can use the public key of an [asymmetric key] (see
5814 /// [`get_public_key`][`NetHsm::get_public_key`]) to encrypt a message and the private key
5815 /// on the NetHSM is used for decryption.
5816 ///
5817 /// This call requires using [`Credentials`] of a user in the [`Operator`][`UserRole::Operator`]
5818 /// [role], which carries a tag (see [`add_user_tag`][`NetHsm::add_user_tag`]) matching one
5819 /// of the tags of the targeted key (see [`add_key_tag`][`NetHsm::add_key_tag`]).
5820 ///
5821 /// ## Namespaces
5822 ///
5823 /// * [`Operator`][`UserRole::Operator`] users in a [namespace] only have access to keys in
5824 /// their own [namespace].
5825 /// * System-wide [`Operator`][`UserRole::Operator`] users only have access to system-wide keys.
5826 ///
5827 /// # Errors
5828 ///
5829 /// Returns an [`Error::Api`] if decrypting the `message` fails:
5830 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
5831 /// * no key identified by `key_id` exists on the NetHSM
5832 /// * the chosen `mode` is incompatible with the targeted key
5833 /// * the encrypted message can not be decrypted
5834 /// * the [`Operator`][`UserRole::Operator`] user does not have access to the key (e.g.
5835 /// different [namespace])
5836 /// * the [`Operator`][`UserRole::Operator`] user does not carry a tag matching one of the key
5837 /// tags
5838 /// * the used [`Credentials`] are not correct
5839 /// * the used [`Credentials`] are not that of a user in the [`Operator`][`UserRole::Operator`]
5840 /// [role]
5841 ///
5842 /// # Examples
5843 ///
5844 /// ```no_run
5845 /// use nethsm::{
5846 /// Connection,
5847 /// ConnectionSecurity,
5848 /// Credentials,
5849 /// DecryptMode,
5850 /// EncryptMode,
5851 /// KeyMechanism,
5852 /// KeyType,
5853 /// NetHsm,
5854 /// Passphrase,
5855 /// UserRole
5856 /// };
5857 /// use rsa::{pkcs8::DecodePublicKey, Pkcs1v15Encrypt, RsaPublicKey};
5858 ///
5859 /// # fn main() -> testresult::TestResult {
5860 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
5861 /// let nethsm = NetHsm::new(
5862 /// Connection::new(
5863 /// "https://example.org/api/v1".try_into()?,
5864 /// ConnectionSecurity::Unsafe,
5865 /// ),
5866 /// Some(Credentials::new(
5867 /// "admin".parse()?,
5868 /// Some(Passphrase::new("passphrase".to_string())),
5869 /// )),
5870 /// None,
5871 /// None,
5872 /// )?;
5873 /// // add a system-wide user in the Operator role
5874 /// nethsm.add_user(
5875 /// "Operator1".to_string(),
5876 /// UserRole::Operator,
5877 /// Passphrase::new("operator-passphrase".to_string()),
5878 /// Some("operator1".parse()?),
5879 /// )?;
5880 /// // generate system-wide keys with the same tag
5881 /// nethsm.generate_key(
5882 /// KeyType::Generic,
5883 /// vec![KeyMechanism::AesDecryptionCbc, KeyMechanism::AesEncryptionCbc],
5884 /// Some(128),
5885 /// Some("encryption1".parse()?),
5886 /// Some(vec!["tag1".to_string()]),
5887 /// )?;
5888 /// nethsm.generate_key(
5889 /// KeyType::Rsa,
5890 /// vec![KeyMechanism::RsaDecryptionPkcs1],
5891 /// None,
5892 /// Some("encryption2".parse()?),
5893 /// Some(vec!["tag1".to_string()]),
5894 /// )?;
5895 /// // tag system-wide user in Operator role for access to signing key
5896 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
5897 ///
5898 /// // assuming we have an AES128 encryption key, the message must be a multiple of 32 bytes long
5899 /// let message = "Hello World! This is a message!!".to_string();
5900 /// // we have an AES128 encryption key. the initialization vector must be a multiple of 16 bytes long
5901 /// let iv = "This is unsafe!!".to_string();
5902 ///
5903 /// // encrypt message using a symmetric key
5904 /// nethsm.use_credentials(&"operator1".parse()?)?;
5905 /// let encrypted_message = nethsm.encrypt(&"encryption1".parse()?, EncryptMode::AesCbc, message.as_bytes(), Some(iv.as_bytes()))?;
5906 ///
5907 /// // decrypt message using the same symmetric key and the same initialization vector
5908 /// assert_eq!(
5909 /// message.as_bytes(),
5910 /// &nethsm.decrypt(&"encryption1".parse()?, DecryptMode::AesCbc, &encrypted_message, Some(iv.as_bytes()))?
5911 /// );
5912 ///
5913 /// // get the public key of an asymmetric key and encrypt the message with it
5914 /// let pubkey = RsaPublicKey::from_public_key_pem(&nethsm.get_public_key(&"encryption2".parse()?)?)?;
5915 /// let mut rng = rand::thread_rng();
5916 /// let encrypted_message = pubkey.encrypt(&mut rng, Pkcs1v15Encrypt, message.as_bytes())?;
5917 /// println!("raw encrypted message: {:?}", encrypted_message);
5918 ///
5919 /// let decrypted_message =
5920 /// nethsm.decrypt(&"encryption2".parse()?, DecryptMode::Pkcs1, &encrypted_message, None)?;
5921 /// println!("raw decrypted message: {:?}", decrypted_message);
5922 ///
5923 /// assert_eq!(&decrypted_message, message.as_bytes());
5924 /// # Ok(())
5925 /// # }
5926 /// ```
5927 /// [Decrypts]: https://docs.nitrokey.com/nethsm/operation#decrypt
5928 /// [symmetric key]: https://en.wikipedia.org/wiki/Symmetric-key_algorithm
5929 /// [asymmetric key]: https://en.wikipedia.org/wiki/Public-key_cryptography
5930 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
5931 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
5932 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
5933 pub fn decrypt(
5934 &self,
5935 key_id: &KeyId,
5936 mode: DecryptMode,
5937 message: &[u8],
5938 iv: Option<&[u8]>,
5939 ) -> Result<Vec<u8>, Error> {
5940 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
5941 // the API requires data to be base64 encoded
5942 let encrypted = Base64::encode_string(message);
5943 let iv = iv.map(Base64::encode_string);
5944
5945 // decode base64 encoded data from the API
5946 Base64::decode_vec(
5947 &keys_key_id_decrypt_post(
5948 &self.create_connection_config(),
5949 key_id.as_ref(),
5950 DecryptRequestData {
5951 mode: mode.into(),
5952 encrypted,
5953 iv,
5954 },
5955 )
5956 .map_err(|error| {
5957 Error::Api(format!(
5958 "Decrypting message failed: {}",
5959 NetHsmApiError::from(error)
5960 ))
5961 })?
5962 .entity
5963 .decrypted,
5964 )
5965 .map_err(Error::Base64Decode)
5966 }
5967
5968 /// Generates [random] bytes.
5969 ///
5970 /// Retrieves `length` [random] bytes from the NetHSM, if it is in
5971 /// [`Operational`][`SystemState::Operational`] [state].
5972 ///
5973 /// This call requires using [`Credentials`] of a user in the [`Operator`][`UserRole::Operator`]
5974 /// [role].
5975 ///
5976 /// # Errors
5977 ///
5978 /// Returns an [`Error::Api`] if retrieving random bytes fails:
5979 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
5980 /// * the used [`Credentials`] are not correct
5981 /// * the used [`Credentials`] are not that of a user in the [`Operator`][`UserRole::Operator`]
5982 /// [role]
5983 ///
5984 /// # Examples
5985 ///
5986 /// ```no_run
5987 /// use nethsm::{Connection, ConnectionSecurity, Credentials, NetHsm, Passphrase, UserRole};
5988 ///
5989 /// # fn main() -> testresult::TestResult {
5990 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
5991 /// let nethsm = NetHsm::new(
5992 /// Connection::new(
5993 /// "https://example.org/api/v1".try_into()?,
5994 /// ConnectionSecurity::Unsafe,
5995 /// ),
5996 /// Some(Credentials::new(
5997 /// "admin".parse()?,
5998 /// Some(Passphrase::new("passphrase".to_string())),
5999 /// )),
6000 /// None,
6001 /// None,
6002 /// )?;
6003 /// // add a system-wide user in the Operator role
6004 /// nethsm.add_user(
6005 /// "Operator1".to_string(),
6006 /// UserRole::Operator,
6007 /// Passphrase::new("operator-passphrase".to_string()),
6008 /// Some("operator1".parse()?),
6009 /// )?;
6010 /// nethsm.use_credentials(&"operator1".parse()?)?;
6011 ///
6012 /// // get 10 random bytes
6013 /// println!("{:#?}", nethsm.random(10)?);
6014 /// # Ok(())
6015 /// # }
6016 /// ```
6017 /// [random]: https://docs.nitrokey.com/nethsm/operation#random
6018 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
6019 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
6020 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
6021 pub fn random(&self, length: u32) -> Result<Vec<u8>, Error> {
6022 self.validate_namespace_access(NamespaceSupport::Supported, None, None)?;
6023 let base64_bytes = random_post(
6024 &self.create_connection_config(),
6025 RandomRequestData::new(length as i32),
6026 )
6027 .map_err(|error| {
6028 Error::Api(format!(
6029 "Getting random bytes failed: {}",
6030 NetHsmApiError::from(error)
6031 ))
6032 })?
6033 .entity
6034 .random;
6035 Base64::decode_vec(&base64_bytes).map_err(Error::Base64Decode)
6036 }
6037
6038 /// Creates an [OpenPGP certificate] for an existing key.
6039 ///
6040 /// The NetHSM key identified by `key_id` is used to issue required [binding signatures] (e.g.
6041 /// those for the [User ID] defined by `user_id`).
6042 /// Using `flags` it is possible to define the key's [capabilities] and with `created_at` to
6043 /// provide the certificate's creation time.
6044 /// Using `version` the OpenPGP version is provided (currently only [`OpenPgpVersion::V4`] is
6045 /// supported).
6046 /// The resulting [OpenPGP certificate] is returned as vector of bytes.
6047 ///
6048 /// To make use of the [OpenPGP certificate] (e.g. with
6049 /// [`openpgp_sign`][`NetHsm::openpgp_sign`]), it should be added as certificate for the key
6050 /// using [`import_key_certificate`][`NetHsm::import_key_certificate`].
6051 ///
6052 /// This call requires using a user in the [`Operator`][`UserRole::Operator`] [role], which
6053 /// carries a tag (see [`add_user_tag`][`NetHsm::add_user_tag`]) matching one of the tags of
6054 /// the targeted key (see [`add_key_tag`][`NetHsm::add_key_tag`]).
6055 ///
6056 /// ## Namespaces
6057 ///
6058 /// * [`Operator`][`UserRole::Operator`] users in a [namespace] only have access to keys in
6059 /// their own [namespace].
6060 /// * System-wide [`Operator`][`UserRole::Operator`] users only have access to system-wide keys.
6061 ///
6062 /// # Errors
6063 ///
6064 /// Returns an [`Error::Api`] if creating an [OpenPGP certificate] for a key fails:
6065 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
6066 /// * no key identified by `key_id` exists on the NetHSM
6067 /// * the [`Operator`][`UserRole::Operator`] user does not have access to the key (e.g.
6068 /// different [namespace])
6069 /// * the [`Operator`][`UserRole::Operator`] user does not carry a tag matching one of the key
6070 /// tags
6071 /// * the used [`Credentials`] are not correct
6072 /// * the used [`Credentials`] are not those of a user in the [`Operator`][`UserRole::Operator`]
6073 /// [role]
6074 ///
6075 /// # Panics
6076 ///
6077 /// Panics if the currently unimplemented [`OpenPgpVersion::V6`] is provided as `version`.
6078 ///
6079 /// # Examples
6080 ///
6081 /// ```no_run
6082 /// use std::time::SystemTime;
6083 ///
6084 /// use nethsm::{
6085 /// Connection,
6086 /// ConnectionSecurity,
6087 /// Credentials,
6088 /// KeyMechanism,
6089 /// KeyType,
6090 /// NetHsm,
6091 /// OpenPgpKeyUsageFlags,
6092 /// OpenPgpVersion,
6093 /// Passphrase,
6094 /// UserRole,
6095 /// };
6096 ///
6097 /// # fn main() -> testresult::TestResult {
6098 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
6099 /// let nethsm = NetHsm::new(
6100 /// Connection::new(
6101 /// "https://example.org/api/v1".try_into()?,
6102 /// ConnectionSecurity::Unsafe,
6103 /// ),
6104 /// Some(Credentials::new(
6105 /// "admin".parse()?,
6106 /// Some(Passphrase::new("passphrase".to_string())),
6107 /// )),
6108 /// None,
6109 /// None,
6110 /// )?;
6111 /// // add a system-wide user in the Operator role
6112 /// nethsm.add_user(
6113 /// "Operator1".to_string(),
6114 /// UserRole::Operator,
6115 /// Passphrase::new("operator-passphrase".to_string()),
6116 /// Some("operator1".parse()?),
6117 /// )?;
6118 /// // generate system-wide key with tag
6119 /// nethsm.generate_key(
6120 /// KeyType::Curve25519,
6121 /// vec![KeyMechanism::EdDsaSignature],
6122 /// None,
6123 /// Some("signing1".parse()?),
6124 /// Some(vec!["tag1".to_string()]),
6125 /// )?;
6126 /// // tag system-wide user in Operator role for access to signing key
6127 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
6128 ///
6129 /// // create an OpenPGP certificate for the key with ID "signing1"
6130 /// nethsm.use_credentials(&"operator1".parse()?)?;
6131 /// assert!(
6132 /// !nethsm
6133 /// .create_openpgp_cert(
6134 /// &"signing1".parse()?,
6135 /// OpenPgpKeyUsageFlags::default(),
6136 /// "Test <test@example.org>".parse()?,
6137 /// SystemTime::now().into(),
6138 /// OpenPgpVersion::V4,
6139 /// )?
6140 /// .is_empty()
6141 /// );
6142 /// # Ok(())
6143 /// # }
6144 /// ```
6145 /// [OpenPGP certificate]: https://openpgp.dev/book/certificates.html
6146 /// [binding signatures]: https://openpgp.dev/book/signing_components.html#binding-signatures
6147 /// [User ID]: https://openpgp.dev/book/glossary.html#term-User-ID
6148 /// [key certificate]: https://docs.nitrokey.com/nethsm/operation#key-certificates
6149 /// [capabilities]: https://openpgp.dev/book/glossary.html#term-Capability
6150 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
6151 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
6152 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
6153 pub fn create_openpgp_cert(
6154 &self,
6155 key_id: &KeyId,
6156 flags: OpenPgpKeyUsageFlags,
6157 user_id: OpenPgpUserId,
6158 created_at: DateTime<Utc>,
6159 version: OpenPgpVersion,
6160 ) -> Result<Vec<u8>, Error> {
6161 openpgp::add_certificate(self, flags, key_id, user_id, created_at, version)
6162 }
6163
6164 /// Creates an [OpenPGP signature] for a message.
6165 ///
6166 /// Signs the `message` using the key identified by `key_id` and returns a binary [OpenPGP data
6167 /// signature].
6168 ///
6169 /// This call requires using a user in the [`Operator`][`UserRole::Operator`] [role], which
6170 /// carries a tag (see [`add_user_tag`][`NetHsm::add_user_tag`]) matching one of the tags of
6171 /// the targeted key (see [`add_key_tag`][`NetHsm::add_key_tag`]).
6172 ///
6173 /// ## Namespaces
6174 ///
6175 /// * [`Operator`][`UserRole::Operator`] users in a [namespace] only have access to keys in
6176 /// their own [namespace].
6177 /// * System-wide [`Operator`][`UserRole::Operator`] users only have access to system-wide keys.
6178 ///
6179 /// # Errors
6180 ///
6181 /// Returns an [`Error::Api`] if creating an [OpenPGP signature] for the `message` fails:
6182 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
6183 /// * no key identified by `key_id` exists on the NetHSM
6184 /// * the [`Operator`][`UserRole::Operator`] user does not have access to the key (e.g.
6185 /// different [namespace])
6186 /// * the [`Operator`][`UserRole::Operator`] user does not carry a tag matching one of the key
6187 /// tags
6188 /// * the used [`Credentials`] are not correct
6189 /// * the used [`Credentials`] are not those of a user in the [`Operator`][`UserRole::Operator`]
6190 /// [role]
6191 ///
6192 /// # Examples
6193 ///
6194 /// ```no_run
6195 /// use std::time::SystemTime;
6196 ///
6197 /// use nethsm::{
6198 /// Connection,
6199 /// ConnectionSecurity,
6200 /// Credentials,
6201 /// KeyMechanism,
6202 /// KeyType,
6203 /// NetHsm,
6204 /// OpenPgpKeyUsageFlags,
6205 /// OpenPgpVersion,
6206 /// Passphrase,
6207 /// UserRole,
6208 /// };
6209 ///
6210 /// # fn main() -> testresult::TestResult {
6211 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
6212 /// let nethsm = NetHsm::new(
6213 /// Connection::new(
6214 /// "https://example.org/api/v1".try_into()?,
6215 /// ConnectionSecurity::Unsafe,
6216 /// ),
6217 /// Some(Credentials::new(
6218 /// "admin".parse()?,
6219 /// Some(Passphrase::new("passphrase".to_string())),
6220 /// )),
6221 /// None,
6222 /// None,
6223 /// )?;
6224 /// // add a system-wide user in the Operator role
6225 /// nethsm.add_user(
6226 /// "Operator1".to_string(),
6227 /// UserRole::Operator,
6228 /// Passphrase::new("operator-passphrase".to_string()),
6229 /// Some("operator1".parse()?),
6230 /// )?;
6231 /// // generate system-wide key with tag
6232 /// nethsm.generate_key(
6233 /// KeyType::Curve25519,
6234 /// vec![KeyMechanism::EdDsaSignature],
6235 /// None,
6236 /// Some("signing1".parse()?),
6237 /// Some(vec!["tag1".to_string()]),
6238 /// )?;
6239 /// // tag system-wide user in Operator role for access to signing key
6240 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
6241 /// // create an OpenPGP certificate for the key with ID "signing1"
6242 /// nethsm.use_credentials(&"operator1".parse()?)?;
6243 /// let openpgp_cert = nethsm.create_openpgp_cert(
6244 /// &"signing1".parse()?,
6245 /// OpenPgpKeyUsageFlags::default(),
6246 /// "Test <test@example.org>".parse()?,
6247 /// SystemTime::now().into(),
6248 /// OpenPgpVersion::V4,
6249 /// )?;
6250 /// // import the OpenPGP certificate as key certificate
6251 /// nethsm.use_credentials(&"admin".parse()?)?;
6252 /// nethsm.import_key_certificate(&"signing1".parse()?, openpgp_cert)?;
6253 ///
6254 /// // create OpenPGP signature
6255 /// nethsm.use_credentials(&"operator1".parse()?)?;
6256 /// assert!(
6257 /// !nethsm
6258 /// .openpgp_sign(&"signing1".parse()?, b"sample message")?
6259 /// .is_empty()
6260 /// );
6261 /// # Ok(()) }
6262 /// ```
6263 /// [OpenPGP signature]: https://openpgp.dev/book/signing_data.html
6264 /// [OpenPGP data signature]: https://openpgp.dev/book/signing_data.html
6265 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
6266 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
6267 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
6268 pub fn openpgp_sign(&self, key_id: &KeyId, message: &[u8]) -> Result<Vec<u8>, Error> {
6269 openpgp::sign(self, key_id, message)
6270 }
6271
6272 /// Generates an armored OpenPGP signature based on provided hasher state.
6273 ///
6274 /// Signs the hasher `state` using the key identified by `key_id`
6275 /// and returns a binary [OpenPGP data signature].
6276 ///
6277 /// This call requires using a user in the [`Operator`][`UserRole::Operator`] [role], which
6278 /// carries a tag (see [`add_user_tag`][`NetHsm::add_user_tag`]) matching one of the tags of
6279 /// the targeted key (see [`add_key_tag`][`NetHsm::add_key_tag`]).
6280 ///
6281 /// ## Namespaces
6282 ///
6283 /// * [`Operator`][`UserRole::Operator`] users in a [namespace] only have access to keys in
6284 /// their own [namespace].
6285 /// * System-wide [`Operator`][`UserRole::Operator`] users only have access to system-wide keys.
6286 ///
6287 /// # Errors
6288 ///
6289 /// Returns an [`Error::Api`] if creating an [OpenPGP signature] for the hasher state fails:
6290 /// * the NetHSM is not in [`Operational`][`SystemState::Operational`] [state]
6291 /// * no key identified by `key_id` exists on the NetHSM
6292 /// * the [`Operator`][`UserRole::Operator`] user does not have access to the key (e.g.
6293 /// different [namespace])
6294 /// * the [`Operator`][`UserRole::Operator`] user does not carry a tag matching one of the key
6295 /// tags
6296 /// * the used [`Credentials`] are not correct
6297 /// * the used [`Credentials`] are not those of a user in the [`Operator`][`UserRole::Operator`]
6298 /// [role]
6299 ///
6300 /// # Examples
6301 ///
6302 /// ```no_run
6303 /// use std::time::SystemTime;
6304 ///
6305 /// use nethsm::{
6306 /// Connection,
6307 /// ConnectionSecurity,
6308 /// Credentials,
6309 /// KeyMechanism,
6310 /// KeyType,
6311 /// NetHsm,
6312 /// OpenPgpKeyUsageFlags,
6313 /// OpenPgpVersion,
6314 /// Passphrase,
6315 /// UserRole,
6316 /// };
6317 /// use sha2::{Digest, Sha256};
6318 ///
6319 /// # fn main() -> testresult::TestResult {
6320 /// // create a connection with a system-wide user in the Administrator role (R-Administrator)
6321 /// let nethsm = NetHsm::new(
6322 /// Connection::new(
6323 /// "https://example.org/api/v1".try_into()?,
6324 /// ConnectionSecurity::Unsafe,
6325 /// ),
6326 /// Some(Credentials::new(
6327 /// "admin".parse()?,
6328 /// Some(Passphrase::new("passphrase".to_string())),
6329 /// )),
6330 /// None,
6331 /// None,
6332 /// )?;
6333 /// // add a system-wide user in the Operator role
6334 /// nethsm.add_user(
6335 /// "Operator1".to_string(),
6336 /// UserRole::Operator,
6337 /// Passphrase::new("operator-passphrase".to_string()),
6338 /// Some("operator1".parse()?),
6339 /// )?;
6340 /// // generate system-wide key with tag
6341 /// nethsm.generate_key(
6342 /// KeyType::Curve25519,
6343 /// vec![KeyMechanism::EdDsaSignature],
6344 /// None,
6345 /// Some("signing1".parse()?),
6346 /// Some(vec!["tag1".to_string()]),
6347 /// )?;
6348 /// // tag system-wide user in Operator role for access to signing key
6349 /// nethsm.add_user_tag(&"operator1".parse()?, "tag1")?;
6350 /// // create an OpenPGP certificate for the key with ID "signing1"
6351 /// nethsm.use_credentials(&"operator1".parse()?)?;
6352 /// let openpgp_cert = nethsm.create_openpgp_cert(
6353 /// &"signing1".parse()?,
6354 /// OpenPgpKeyUsageFlags::default(),
6355 /// "Test <test@example.org>".parse()?,
6356 /// SystemTime::now().into(),
6357 /// OpenPgpVersion::V4,
6358 /// )?;
6359 /// // import the OpenPGP certificate as key certificate
6360 /// nethsm.use_credentials(&"admin".parse()?)?;
6361 /// nethsm.import_key_certificate(&"signing1".parse()?, openpgp_cert)?;
6362 ///
6363 /// let mut state = Sha256::new();
6364 /// state.update(b"Hello world!");
6365 ///
6366 /// // create OpenPGP signature
6367 /// nethsm.use_credentials(&"operator1".parse()?)?;
6368 /// assert!(
6369 /// !nethsm
6370 /// .openpgp_sign_state(&"signing1".parse()?, state)?
6371 /// .is_empty()
6372 /// );
6373 /// # Ok(()) }
6374 /// ```
6375 /// [OpenPGP signature]: https://openpgp.dev/book/signing_data.html
6376 /// [OpenPGP data signature]: https://openpgp.dev/book/signing_data.html
6377 /// [namespace]: https://docs.nitrokey.com/nethsm/administration#namespaces
6378 /// [role]: https://docs.nitrokey.com/nethsm/administration#roles
6379 /// [state]: https://docs.nitrokey.com/nethsm/administration#state
6380 pub fn openpgp_sign_state(
6381 &self,
6382 key_id: &KeyId,
6383 state: impl sha2::Digest + Clone + std::io::Write,
6384 ) -> Result<String, crate::Error> {
6385 openpgp::sign_hasher_state(self, key_id, state)
6386 }
6387}