1use std::{
4 collections::HashSet,
5 fs::{File, Permissions, create_dir_all, read_to_string, set_permissions},
6 io::Write,
7 os::unix::fs::{PermissionsExt, chown},
8 path::{Path, PathBuf},
9 process::{Command, Stdio},
10};
11
12use log::info;
13use nethsm::{FullCredentials, KeyId, NamespaceId, Passphrase, SystemWideUserId, UserId, UserRole};
14use serde::{Deserialize, Serialize};
15use signstar_common::{
16 common::SECRET_FILE_MODE,
17 system_user::{
18 get_home_base_dir_path,
19 get_plaintext_secret_file,
20 get_systemd_creds_secret_file,
21 get_user_secrets_dir,
22 },
23};
24use signstar_crypto::{key::SigningKeySetup, traits::UserWithPassphrase};
25#[cfg(feature = "yubihsm2")]
26use signstar_yubihsm2::object::Id;
27
28use crate::{
29 AdministrativeSecretHandling,
30 AuthorizedKeyEntry,
31 CredentialsLoading,
32 CredentialsLoadingError,
33 CredentialsLoadingErrors,
34 Error,
35 NonAdministrativeSecretHandling,
36 SignstarConfig,
37 SystemUserId,
38 config::base::BackendConnection,
39 nethsm::{FilterUserKeys, NetHsmMetricsUsers},
40 utils::{
41 fail_if_not_root,
42 fail_if_root,
43 get_command,
44 get_current_system_user,
45 get_system_user_pair,
46 match_current_system_user,
47 },
48};
49
50#[derive(Clone, Copy, Debug, Default)]
55pub enum BackendUserKind {
56 Admin,
58 #[default]
60 NonAdmin,
61}
62
63#[derive(Clone, Debug, Default)]
65pub struct UserMappingFilter {
66 pub backend_user_kind: BackendUserKind,
68}
69
70#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
72pub enum UserMapping {
73 #[serde(rename = "nethsm_only_admin")]
75 NetHsmOnlyAdmin(UserId),
76
77 #[serde(rename = "system_nethsm_backup")]
79 SystemNetHsmBackup {
80 nethsm_user: SystemWideUserId,
82 ssh_authorized_key: AuthorizedKeyEntry,
84 system_user: SystemUserId,
86 },
87
88 #[cfg(feature = "yubihsm2")]
101 #[serde(rename = "system_yubihsm2_backup")]
102 SystemYubiHsm2Backup {
103 authentication_key_id: Id,
105 wrapping_key_id: Id,
110 ssh_authorized_key: AuthorizedKeyEntry,
112 system_user: SystemUserId,
114 },
115
116 #[serde(rename = "system_nethsm_metrics")]
120 SystemNetHsmMetrics {
121 nethsm_users: NetHsmMetricsUsers,
124 ssh_authorized_key: AuthorizedKeyEntry,
126 system_user: SystemUserId,
128 },
129
130 #[cfg(feature = "yubihsm2")]
139 #[serde(rename = "system_yubihsm2_metrics")]
140 SystemYubiHsm2Metrics {
141 authentication_key_id: Id,
143 ssh_authorized_key: AuthorizedKeyEntry,
145 system_user: SystemUserId,
147 },
148
149 #[serde(rename = "system_nethsm_operator_signing")]
154 SystemNetHsmOperatorSigning {
155 nethsm_user: UserId,
157 key_id: KeyId,
159 nethsm_key_setup: SigningKeySetup,
161 ssh_authorized_key: AuthorizedKeyEntry,
163 system_user: SystemUserId,
165 tag: String,
167 },
168
169 #[cfg(feature = "yubihsm2")]
181 #[serde(rename = "system_yubihsm2_operator_signing")]
182 SystemYubiHsm2OperatorSigning {
183 authentication_key_id: Id,
185 backend_key_setup: SigningKeySetup,
187 backend_key_id: Id,
189 backend_key_domain: usize,
191 ssh_authorized_key: AuthorizedKeyEntry,
193 system_user: SystemUserId,
195 },
196
197 #[serde(rename = "hermetic_system_nethsm_metrics")]
201 HermeticSystemNetHsmMetrics {
202 nethsm_users: NetHsmMetricsUsers,
205 system_user: SystemUserId,
207 },
208
209 #[cfg(feature = "yubihsm2")]
218 #[serde(rename = "hermetic_system_yubihsm2_metrics")]
219 HermeticSystemYubiHsm2Metrics {
220 authentication_key_id: Id,
222 system_user: SystemUserId,
224 },
225
226 #[serde(rename = "system_only_share_download")]
229 SystemOnlyShareDownload {
230 system_user: SystemUserId,
232 ssh_authorized_key: AuthorizedKeyEntry,
234 },
235
236 #[serde(rename = "system_only_share_upload")]
239 SystemOnlyShareUpload {
240 system_user: SystemUserId,
242 ssh_authorized_key: AuthorizedKeyEntry,
244 },
245
246 #[serde(rename = "system_only_wireguard_download")]
249 SystemOnlyWireGuardDownload {
250 system_user: SystemUserId,
252 ssh_authorized_key: AuthorizedKeyEntry,
254 },
255
256 #[cfg(feature = "yubihsm2")]
302 #[serde(rename = "yubihsm2_only_admin")]
303 YubiHsm2OnlyAdmin(Id),
304}
305
306impl UserMapping {
307 pub fn get_system_user(&self) -> Option<&SystemUserId> {
327 match self {
328 UserMapping::NetHsmOnlyAdmin(_) => None,
329 UserMapping::SystemNetHsmBackup {
330 nethsm_user: _,
331 ssh_authorized_key: _,
332 system_user,
333 }
334 | UserMapping::SystemNetHsmOperatorSigning {
335 nethsm_user: _,
336 key_id: _,
337 nethsm_key_setup: _,
338 ssh_authorized_key: _,
339 system_user,
340 ..
341 }
342 | UserMapping::SystemNetHsmMetrics {
343 nethsm_users: _,
344 ssh_authorized_key: _,
345 system_user,
346 }
347 | UserMapping::HermeticSystemNetHsmMetrics {
348 nethsm_users: _,
349 system_user,
350 }
351 | UserMapping::SystemOnlyShareDownload { system_user, .. }
352 | UserMapping::SystemOnlyShareUpload { system_user, .. }
353 | UserMapping::SystemOnlyWireGuardDownload {
354 system_user,
355 ssh_authorized_key: _,
356 } => Some(system_user),
357 #[cfg(feature = "yubihsm2")]
358 UserMapping::YubiHsm2OnlyAdmin(_) => None,
359 #[cfg(feature = "yubihsm2")]
360 UserMapping::SystemYubiHsm2OperatorSigning { system_user, .. }
361 | UserMapping::SystemYubiHsm2Backup { system_user, .. }
362 | UserMapping::SystemYubiHsm2Metrics { system_user, .. }
363 | UserMapping::HermeticSystemYubiHsm2Metrics { system_user, .. } => Some(system_user),
364 }
365 }
366
367 pub fn backend_users(&self, filter: UserMappingFilter) -> Vec<String> {
403 match self {
404 UserMapping::NetHsmOnlyAdmin(user_id) => match filter.backend_user_kind {
405 BackendUserKind::Admin => vec![user_id.to_string()],
406 BackendUserKind::NonAdmin => Vec::new(),
407 },
408 UserMapping::SystemNetHsmBackup { nethsm_user, .. } => match filter.backend_user_kind {
409 BackendUserKind::Admin => Vec::new(),
410 BackendUserKind::NonAdmin => vec![nethsm_user.to_string()],
411 },
412 UserMapping::HermeticSystemNetHsmMetrics { nethsm_users, .. }
413 | UserMapping::SystemNetHsmMetrics { nethsm_users, .. } => {
414 match filter.backend_user_kind {
415 BackendUserKind::Admin => Vec::new(),
416 BackendUserKind::NonAdmin => nethsm_users
417 .get_users()
418 .iter()
419 .map(|user| user.to_string())
420 .collect(),
421 }
422 }
423 UserMapping::SystemNetHsmOperatorSigning { nethsm_user, .. } => {
424 match filter.backend_user_kind {
425 BackendUserKind::Admin => Vec::new(),
426 BackendUserKind::NonAdmin => vec![nethsm_user.to_string()],
427 }
428 }
429 UserMapping::SystemOnlyShareDownload { .. }
430 | UserMapping::SystemOnlyShareUpload { .. }
431 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
432 #[cfg(feature = "yubihsm2")]
433 UserMapping::YubiHsm2OnlyAdmin(admin) => match filter.backend_user_kind {
434 BackendUserKind::Admin => vec![admin.to_string()],
435 BackendUserKind::NonAdmin => Vec::new(),
436 },
437 #[cfg(feature = "yubihsm2")]
438 UserMapping::SystemYubiHsm2OperatorSigning {
439 authentication_key_id,
440 ..
441 }
442 | UserMapping::SystemYubiHsm2Backup {
443 authentication_key_id,
444 ..
445 }
446 | UserMapping::SystemYubiHsm2Metrics {
447 authentication_key_id,
448 ..
449 }
450 | UserMapping::HermeticSystemYubiHsm2Metrics {
451 authentication_key_id,
452 ..
453 } => match filter.backend_user_kind {
454 BackendUserKind::Admin => Vec::new(),
455 BackendUserKind::NonAdmin => vec![authentication_key_id.to_string()],
456 },
457 }
458 }
459
460 pub fn backend_users_with_new_passphrase(
502 &self,
503 filter: UserMappingFilter,
504 ) -> Vec<Box<dyn UserWithPassphrase>> {
505 match self {
506 UserMapping::NetHsmOnlyAdmin(user_id) => match filter.backend_user_kind {
507 BackendUserKind::Admin => vec![Box::new(nethsm::FullCredentials::new(
508 user_id.clone(),
509 Passphrase::generate(None),
510 ))],
511 BackendUserKind::NonAdmin => Vec::new(),
512 },
513 UserMapping::SystemNetHsmBackup { nethsm_user, .. } => match filter.backend_user_kind {
514 BackendUserKind::Admin => Vec::new(),
515 BackendUserKind::NonAdmin => vec![Box::new(nethsm::FullCredentials::new(
516 nethsm_user.as_ref().clone(),
517 Passphrase::generate(None),
518 ))],
519 },
520 UserMapping::HermeticSystemNetHsmMetrics { nethsm_users, .. }
521 | UserMapping::SystemNetHsmMetrics { nethsm_users, .. } => {
522 match filter.backend_user_kind {
523 BackendUserKind::Admin => Vec::new(),
524 BackendUserKind::NonAdmin => nethsm_users
525 .get_users()
526 .iter()
527 .map(|user| {
528 Box::new(FullCredentials::new(
529 user.clone(),
530 Passphrase::generate(None),
531 )) as Box<dyn UserWithPassphrase>
532 })
533 .collect(),
534 }
535 }
536 UserMapping::SystemNetHsmOperatorSigning { nethsm_user, .. } => {
537 match filter.backend_user_kind {
538 BackendUserKind::Admin => Vec::new(),
539 BackendUserKind::NonAdmin => vec![Box::new(nethsm::FullCredentials::new(
540 nethsm_user.clone(),
541 Passphrase::generate(None),
542 ))],
543 }
544 }
545 UserMapping::SystemOnlyShareDownload { .. }
546 | UserMapping::SystemOnlyShareUpload { .. }
547 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
548 #[cfg(feature = "yubihsm2")]
549 UserMapping::YubiHsm2OnlyAdmin(admin) => match filter.backend_user_kind {
550 BackendUserKind::Admin => vec![Box::new(signstar_yubihsm2::Credentials::new(
551 *admin,
552 Passphrase::generate(None),
553 ))],
554 BackendUserKind::NonAdmin => Vec::new(),
555 },
556 #[cfg(feature = "yubihsm2")]
557 UserMapping::SystemYubiHsm2OperatorSigning {
558 authentication_key_id,
559 ..
560 }
561 | UserMapping::SystemYubiHsm2Backup {
562 authentication_key_id,
563 ..
564 }
565 | UserMapping::SystemYubiHsm2Metrics {
566 authentication_key_id,
567 ..
568 }
569 | UserMapping::HermeticSystemYubiHsm2Metrics {
570 authentication_key_id,
571 ..
572 } => match filter.backend_user_kind {
573 BackendUserKind::Admin => Vec::new(),
574 BackendUserKind::NonAdmin => vec![Box::new(signstar_yubihsm2::Credentials::new(
575 *authentication_key_id,
576 Passphrase::generate(None),
577 ))],
578 },
579 }
580 }
581
582 pub fn get_nethsm_users(&self) -> Vec<UserId> {
603 match self {
604 UserMapping::SystemNetHsmBackup { nethsm_user, .. } => vec![nethsm_user.clone().into()],
605 UserMapping::NetHsmOnlyAdmin(nethsm_user)
606 | UserMapping::SystemNetHsmOperatorSigning { nethsm_user, .. } => {
607 vec![nethsm_user.clone()]
608 }
609 UserMapping::SystemNetHsmMetrics { nethsm_users, .. }
610 | UserMapping::HermeticSystemNetHsmMetrics { nethsm_users, .. } => {
611 nethsm_users.get_users()
612 }
613 UserMapping::SystemOnlyShareDownload { .. }
614 | UserMapping::SystemOnlyShareUpload { .. }
615 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
616 #[cfg(feature = "yubihsm2")]
617 UserMapping::YubiHsm2OnlyAdmin(_)
618 | UserMapping::SystemYubiHsm2Backup { .. }
619 | UserMapping::SystemYubiHsm2Metrics { .. }
620 | UserMapping::HermeticSystemYubiHsm2Metrics { .. }
621 | UserMapping::SystemYubiHsm2OperatorSigning { .. } => Vec::new(),
622 }
623 }
624
625 pub fn get_nethsm_users_and_roles(&self) -> Vec<(UserId, UserRole)> {
646 match self {
647 UserMapping::SystemNetHsmBackup { nethsm_user, .. } => {
648 vec![(nethsm_user.clone().into(), UserRole::Backup)]
649 }
650 UserMapping::NetHsmOnlyAdmin(nethsm_user) => {
651 vec![(nethsm_user.clone(), UserRole::Administrator)]
652 }
653 UserMapping::SystemNetHsmOperatorSigning { nethsm_user, .. } => {
654 vec![(nethsm_user.clone(), UserRole::Operator)]
655 }
656 UserMapping::SystemNetHsmMetrics { nethsm_users, .. }
657 | UserMapping::HermeticSystemNetHsmMetrics { nethsm_users, .. } => {
658 nethsm_users.get_users_and_roles()
659 }
660 UserMapping::SystemOnlyShareDownload { .. }
661 | UserMapping::SystemOnlyShareUpload { .. }
662 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
663 #[cfg(feature = "yubihsm2")]
664 UserMapping::YubiHsm2OnlyAdmin(_)
665 | UserMapping::SystemYubiHsm2Backup { .. }
666 | UserMapping::SystemYubiHsm2Metrics { .. }
667 | UserMapping::HermeticSystemYubiHsm2Metrics { .. }
668 | UserMapping::SystemYubiHsm2OperatorSigning { .. } => Vec::new(),
669 }
670 }
671
672 pub fn get_nethsm_user_role_and_tags(&self) -> Vec<(UserId, UserRole, Vec<String>)> {
712 match self {
713 UserMapping::SystemNetHsmOperatorSigning {
714 nethsm_user,
715 key_id: _,
716 nethsm_key_setup: _,
717 system_user: _,
718 ssh_authorized_key: _,
719 tag,
720 } => vec![(
721 nethsm_user.clone(),
722 UserRole::Operator,
723 vec![tag.to_string()],
724 )],
725 UserMapping::SystemNetHsmBackup { nethsm_user, .. } => {
726 vec![(nethsm_user.clone().into(), UserRole::Backup, Vec::new())]
727 }
728 UserMapping::NetHsmOnlyAdmin(user_id) => {
729 vec![(user_id.clone(), UserRole::Administrator, Vec::new())]
730 }
731 UserMapping::SystemNetHsmMetrics { nethsm_users, .. } => nethsm_users
732 .get_users_and_roles()
733 .iter()
734 .map(|(user, role)| (user.clone(), *role, Vec::new()))
735 .collect(),
736 UserMapping::HermeticSystemNetHsmMetrics { nethsm_users, .. } => nethsm_users
737 .get_users_and_roles()
738 .iter()
739 .map(|(user, role)| (user.clone(), *role, Vec::new()))
740 .collect(),
741 UserMapping::SystemOnlyShareDownload { .. }
742 | UserMapping::SystemOnlyShareUpload { .. }
743 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
744 #[cfg(feature = "yubihsm2")]
745 UserMapping::YubiHsm2OnlyAdmin(_)
746 | UserMapping::SystemYubiHsm2Backup { .. }
747 | UserMapping::SystemYubiHsm2Metrics { .. }
748 | UserMapping::HermeticSystemYubiHsm2Metrics { .. }
749 | UserMapping::SystemYubiHsm2OperatorSigning { .. } => Vec::new(),
750 }
751 }
752
753 pub fn get_ssh_authorized_key(&self) -> Option<&AuthorizedKeyEntry> {
777 match self {
778 UserMapping::NetHsmOnlyAdmin(_) | UserMapping::HermeticSystemNetHsmMetrics { .. } => {
779 None
780 }
781 UserMapping::SystemNetHsmBackup {
782 nethsm_user: _,
783 system_user: _,
784 ssh_authorized_key,
785 }
786 | UserMapping::SystemNetHsmMetrics {
787 nethsm_users: _,
788 system_user: _,
789 ssh_authorized_key,
790 }
791 | UserMapping::SystemOnlyShareDownload {
792 system_user: _,
793 ssh_authorized_key,
794 }
795 | UserMapping::SystemOnlyShareUpload {
796 system_user: _,
797 ssh_authorized_key,
798 }
799 | UserMapping::SystemOnlyWireGuardDownload {
800 system_user: _,
801 ssh_authorized_key,
802 }
803 | UserMapping::SystemNetHsmOperatorSigning {
804 nethsm_user: _,
805 key_id: _,
806 nethsm_key_setup: _,
807 system_user: _,
808 ssh_authorized_key,
809 ..
810 } => Some(ssh_authorized_key),
811 #[cfg(feature = "yubihsm2")]
812 UserMapping::YubiHsm2OnlyAdmin(_)
813 | UserMapping::HermeticSystemYubiHsm2Metrics { .. } => None,
814 #[cfg(feature = "yubihsm2")]
815 UserMapping::SystemYubiHsm2OperatorSigning {
816 ssh_authorized_key, ..
817 }
818 | UserMapping::SystemYubiHsm2Backup {
819 ssh_authorized_key, ..
820 }
821 | UserMapping::SystemYubiHsm2Metrics {
822 ssh_authorized_key, ..
823 } => Some(ssh_authorized_key),
824 }
825 }
826
827 pub fn get_nethsm_key_ids(&self, namespace: Option<&NamespaceId>) -> Vec<KeyId> {
865 match self {
866 UserMapping::SystemNetHsmOperatorSigning {
867 nethsm_user,
868 key_id,
869 ..
870 } => {
871 if nethsm_user.namespace() == namespace {
872 vec![key_id.clone()]
873 } else {
874 Vec::new()
875 }
876 }
877 UserMapping::SystemNetHsmMetrics { .. }
878 | UserMapping::NetHsmOnlyAdmin(_)
879 | UserMapping::HermeticSystemNetHsmMetrics { .. }
880 | UserMapping::SystemNetHsmBackup { .. }
881 | UserMapping::SystemOnlyShareDownload { .. }
882 | UserMapping::SystemOnlyShareUpload { .. }
883 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
884 #[cfg(feature = "yubihsm2")]
885 UserMapping::YubiHsm2OnlyAdmin(_)
886 | UserMapping::SystemYubiHsm2Backup { .. }
887 | UserMapping::SystemYubiHsm2Metrics { .. }
888 | UserMapping::HermeticSystemYubiHsm2Metrics { .. }
889 | UserMapping::SystemYubiHsm2OperatorSigning { .. } => Vec::new(),
890 }
891 }
892
893 pub fn get_nethsm_tags(&self, namespace: Option<&NamespaceId>) -> Vec<&str> {
938 match self {
939 UserMapping::SystemNetHsmOperatorSigning {
940 nethsm_user,
941 key_id: _,
942 nethsm_key_setup: _,
943 system_user: _,
944 ssh_authorized_key: _,
945 tag,
946 } => {
947 if nethsm_user.namespace() == namespace {
948 vec![tag.as_str()]
949 } else {
950 Vec::new()
951 }
952 }
953 UserMapping::SystemNetHsmMetrics { .. }
954 | UserMapping::NetHsmOnlyAdmin(_)
955 | UserMapping::HermeticSystemNetHsmMetrics { .. }
956 | UserMapping::SystemNetHsmBackup { .. }
957 | UserMapping::SystemOnlyShareDownload { .. }
958 | UserMapping::SystemOnlyShareUpload { .. }
959 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
960 #[cfg(feature = "yubihsm2")]
961 UserMapping::YubiHsm2OnlyAdmin(_)
962 | UserMapping::SystemYubiHsm2Backup { .. }
963 | UserMapping::SystemYubiHsm2Metrics { .. }
964 | UserMapping::HermeticSystemYubiHsm2Metrics { .. }
965 | UserMapping::SystemYubiHsm2OperatorSigning { .. } => Vec::new(),
966 }
967 }
968
969 pub fn get_nethsm_user_key_and_tag(
1037 &self,
1038 filter: FilterUserKeys,
1039 ) -> Vec<(UserId, KeyId, SigningKeySetup, String)> {
1040 match self {
1041 UserMapping::SystemNetHsmOperatorSigning {
1042 nethsm_user,
1043 key_id,
1044 nethsm_key_setup,
1045 system_user: _,
1046 ssh_authorized_key: _,
1047 tag,
1048 } => match filter {
1049 FilterUserKeys::All => {
1050 vec![(
1051 nethsm_user.clone(),
1052 key_id.clone(),
1053 nethsm_key_setup.clone(),
1054 tag.clone(),
1055 )]
1056 }
1057 FilterUserKeys::Namespaced => {
1058 if nethsm_user.is_namespaced() {
1059 vec![(
1060 nethsm_user.clone(),
1061 key_id.clone(),
1062 nethsm_key_setup.clone(),
1063 tag.clone(),
1064 )]
1065 } else {
1066 Vec::new()
1067 }
1068 }
1069 FilterUserKeys::Namespace(namespace) => {
1070 if Some(&namespace) == nethsm_user.namespace() {
1071 vec![(
1072 nethsm_user.clone(),
1073 key_id.clone(),
1074 nethsm_key_setup.clone(),
1075 tag.clone(),
1076 )]
1077 } else {
1078 Vec::new()
1079 }
1080 }
1081 FilterUserKeys::SystemWide => {
1082 if !nethsm_user.is_namespaced() {
1083 vec![(
1084 nethsm_user.clone(),
1085 key_id.clone(),
1086 nethsm_key_setup.clone(),
1087 tag.clone(),
1088 )]
1089 } else {
1090 Vec::new()
1091 }
1092 }
1093 FilterUserKeys::Tag(filter_tag) => {
1094 if &filter_tag == tag {
1095 vec![(
1096 nethsm_user.clone(),
1097 key_id.clone(),
1098 nethsm_key_setup.clone(),
1099 tag.clone(),
1100 )]
1101 } else {
1102 Vec::new()
1103 }
1104 }
1105 },
1106 UserMapping::SystemNetHsmMetrics { .. }
1107 | UserMapping::NetHsmOnlyAdmin(_)
1108 | UserMapping::HermeticSystemNetHsmMetrics { .. }
1109 | UserMapping::SystemNetHsmBackup { .. }
1110 | UserMapping::SystemOnlyShareDownload { .. }
1111 | UserMapping::SystemOnlyShareUpload { .. }
1112 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
1113 #[cfg(feature = "yubihsm2")]
1114 UserMapping::YubiHsm2OnlyAdmin(_)
1115 | UserMapping::SystemYubiHsm2Backup { .. }
1116 | UserMapping::SystemYubiHsm2Metrics { .. }
1117 | UserMapping::HermeticSystemYubiHsm2Metrics { .. }
1118 | UserMapping::SystemYubiHsm2OperatorSigning { .. } => Vec::new(),
1119 }
1120 }
1121
1122 pub fn get_nethsm_namespaces(&self) -> Vec<NamespaceId> {
1163 match self {
1164 UserMapping::NetHsmOnlyAdmin(nethsm_user)
1165 | UserMapping::SystemNetHsmOperatorSigning { nethsm_user, .. } => {
1166 if let Some(namespace) = nethsm_user.namespace() {
1167 vec![namespace.clone()]
1168 } else {
1169 Vec::new()
1170 }
1171 }
1172 UserMapping::HermeticSystemNetHsmMetrics { nethsm_users, .. }
1173 | UserMapping::SystemNetHsmMetrics { nethsm_users, .. } => nethsm_users
1174 .get_users()
1175 .iter()
1176 .filter_map(|user_id| user_id.namespace())
1177 .cloned()
1178 .collect(),
1179 UserMapping::SystemOnlyShareDownload { .. }
1180 | UserMapping::SystemNetHsmBackup { .. }
1181 | UserMapping::SystemOnlyShareUpload { .. }
1182 | UserMapping::SystemOnlyWireGuardDownload { .. } => Vec::new(),
1183 #[cfg(feature = "yubihsm2")]
1184 UserMapping::YubiHsm2OnlyAdmin(_)
1185 | UserMapping::SystemYubiHsm2Backup { .. }
1186 | UserMapping::SystemYubiHsm2Metrics { .. }
1187 | UserMapping::HermeticSystemYubiHsm2Metrics { .. }
1188 | UserMapping::SystemYubiHsm2OperatorSigning { .. } => Vec::new(),
1189 }
1190 }
1191
1192 pub fn has_system_and_backend_user(&self) -> bool {
1197 match self {
1198 UserMapping::SystemNetHsmOperatorSigning { .. }
1199 | UserMapping::HermeticSystemNetHsmMetrics { .. }
1200 | UserMapping::SystemNetHsmMetrics { .. }
1201 | UserMapping::SystemNetHsmBackup { .. } => true,
1202 #[cfg(feature = "yubihsm2")]
1203 UserMapping::YubiHsm2OnlyAdmin(_) => false,
1204 #[cfg(feature = "yubihsm2")]
1205 UserMapping::SystemYubiHsm2Backup { .. }
1206 | UserMapping::SystemYubiHsm2Metrics { .. }
1207 | UserMapping::HermeticSystemYubiHsm2Metrics { .. }
1208 | UserMapping::SystemYubiHsm2OperatorSigning { .. } => true,
1209 UserMapping::SystemOnlyShareDownload { .. }
1210 | UserMapping::SystemOnlyShareUpload { .. }
1211 | UserMapping::SystemOnlyWireGuardDownload { .. }
1212 | UserMapping::NetHsmOnlyAdmin(_) => false,
1213 }
1214 }
1215}
1216
1217pub(crate) fn check_secrets_file(path: impl AsRef<Path>) -> Result<(), Error> {
1235 let path = path.as_ref();
1236
1237 if !path.exists() {
1239 return Err(crate::non_admin_credentials::Error::SecretsFileMissing {
1240 path: path.to_path_buf(),
1241 }
1242 .into());
1243 }
1244
1245 if !path.is_file() {
1247 return Err(Error::NonAdminSecretHandling(
1248 crate::non_admin_credentials::Error::SecretsFileNotAFile {
1249 path: path.to_path_buf(),
1250 },
1251 ));
1252 }
1253
1254 match path.metadata() {
1256 Ok(metadata) => {
1257 let mode = metadata.permissions().mode();
1258 if mode != SECRET_FILE_MODE {
1259 return Err(Error::NonAdminSecretHandling(
1260 crate::non_admin_credentials::Error::SecretsFilePermissions {
1261 path: path.to_path_buf(),
1262 mode,
1263 },
1264 ));
1265 }
1266 }
1267 Err(source) => {
1268 return Err(Error::NonAdminSecretHandling(
1269 crate::non_admin_credentials::Error::SecretsFileMetadata {
1270 path: path.to_path_buf(),
1271 source,
1272 },
1273 ));
1274 }
1275 }
1276
1277 Ok(())
1278}
1279
1280#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1285pub struct ExtendedUserMapping {
1286 admin_secret_handling: AdministrativeSecretHandling,
1287 non_admin_secret_handling: NonAdministrativeSecretHandling,
1288 connections: HashSet<BackendConnection>,
1289 user_mapping: UserMapping,
1290}
1291
1292impl ExtendedUserMapping {
1293 pub fn new(
1295 admin_secret_handling: AdministrativeSecretHandling,
1296 non_admin_secret_handling: NonAdministrativeSecretHandling,
1297 connections: HashSet<BackendConnection>,
1298 user_mapping: UserMapping,
1299 ) -> Self {
1300 Self {
1301 admin_secret_handling,
1302 non_admin_secret_handling,
1303 connections,
1304 user_mapping,
1305 }
1306 }
1307
1308 pub fn get_admin_secret_handling(&self) -> AdministrativeSecretHandling {
1310 self.admin_secret_handling
1311 }
1312
1313 pub fn get_connections(&self) -> HashSet<BackendConnection> {
1315 self.connections.clone()
1316 }
1317
1318 pub fn get_non_admin_secret_handling(&self) -> NonAdministrativeSecretHandling {
1320 self.non_admin_secret_handling
1321 }
1322
1323 pub fn get_user_mapping(&self) -> &UserMapping {
1325 &self.user_mapping
1326 }
1327
1328 pub fn load_credentials(&self) -> Result<CredentialsLoading, Error> {
1353 let (system_user, user) = get_system_user_pair(self)?;
1355 let current_system_user = get_current_system_user()?;
1356
1357 fail_if_root(¤t_system_user)?;
1359 match_current_system_user(¤t_system_user, &user)?;
1360
1361 let secret_handling = self.get_non_admin_secret_handling();
1362 let mut credentials: Vec<Box<dyn UserWithPassphrase>> = Vec::new();
1363 let mut errors = Vec::new();
1364
1365 for name in self.get_user_mapping().backend_users(UserMappingFilter {
1367 backend_user_kind: BackendUserKind::NonAdmin,
1368 }) {
1369 let secrets_file = match secret_handling {
1370 NonAdministrativeSecretHandling::Plaintext => {
1371 get_plaintext_secret_file(system_user.as_ref(), &name)
1372 }
1373 NonAdministrativeSecretHandling::SystemdCreds => {
1374 get_systemd_creds_secret_file(system_user.as_ref(), &name)
1375 }
1376 };
1377 info!(
1378 "Load secret for system user {system_user} and backend user {name} from file: {secrets_file:?}"
1379 );
1380 if let Err(error) = check_secrets_file(secrets_file.as_path()) {
1382 errors.push(CredentialsLoadingError::new(name.clone(), error));
1383 continue;
1384 };
1385
1386 let passphrase = match secret_handling {
1387 NonAdministrativeSecretHandling::Plaintext => {
1389 match read_to_string(&secrets_file).map_err(|source| {
1391 Error::NonAdminSecretHandling(
1392 crate::non_admin_credentials::Error::SecretsFileRead {
1393 path: secrets_file,
1394 source,
1395 },
1396 )
1397 }) {
1398 Ok(passphrase) => Passphrase::new(passphrase),
1399 Err(error) => {
1400 errors.push(CredentialsLoadingError::new(name.clone(), error));
1401 continue;
1402 }
1403 }
1404 }
1405 NonAdministrativeSecretHandling::SystemdCreds => {
1407 let creds_command = get_command("systemd-creds")?;
1409 let mut command = Command::new(creds_command);
1410 let command = command
1411 .arg("--user")
1412 .arg("decrypt")
1413 .arg(&secrets_file)
1414 .arg("-");
1415 match command.output().map_err(|source| Error::CommandExec {
1416 command: format!("{command:?}"),
1417 source,
1418 }) {
1419 Ok(command_output) => {
1420 if !command_output.status.success() {
1422 errors.push(CredentialsLoadingError::new(
1423 name.clone(),
1424 Error::CommandNonZero {
1425 command: format!("{command:?}"),
1426 exit_status: command_output.status,
1427 stderr: String::from_utf8_lossy(&command_output.stderr)
1428 .into_owned(),
1429 },
1430 ));
1431 continue;
1432 }
1433
1434 let creds = match String::from_utf8(command_output.stdout) {
1435 Ok(creds) => creds,
1436 Err(source) => {
1437 errors.push(CredentialsLoadingError::new(
1438 name.clone(),
1439 Error::Utf8String {
1440 path: secrets_file,
1441 context: format!(
1442 "converting stdout of {command:?} to string"
1443 ),
1444 source,
1445 },
1446 ));
1447 continue;
1448 }
1449 };
1450
1451 Passphrase::new(creds)
1452 }
1453 Err(error) => {
1454 errors.push(CredentialsLoadingError::new(name.clone(), error));
1455 continue;
1456 }
1457 }
1458 }
1459 };
1460
1461 match self.get_user_mapping() {
1466 UserMapping::NetHsmOnlyAdmin(_) => {}
1469 UserMapping::SystemOnlyShareDownload { .. }
1471 | UserMapping::SystemOnlyShareUpload { .. }
1472 | UserMapping::SystemOnlyWireGuardDownload { .. } => {}
1473 UserMapping::SystemNetHsmBackup { .. }
1474 | UserMapping::SystemNetHsmMetrics { .. }
1475 | UserMapping::SystemNetHsmOperatorSigning { .. }
1476 | UserMapping::HermeticSystemNetHsmMetrics { .. } => {
1477 credentials.push(Box::new(FullCredentials::new(
1478 UserId::new(name)
1481 .map_err(|source| Error::NetHsm(nethsm::Error::User(source)))?,
1482 passphrase,
1483 )));
1484 }
1485 #[cfg(feature = "yubihsm2")]
1486 UserMapping::YubiHsm2OnlyAdmin(_) => {}
1487 #[cfg(feature = "yubihsm2")]
1488 UserMapping::SystemYubiHsm2OperatorSigning {
1489 authentication_key_id,
1490 ..
1491 }
1492 | UserMapping::SystemYubiHsm2Backup {
1493 authentication_key_id,
1494 ..
1495 }
1496 | UserMapping::SystemYubiHsm2Metrics {
1497 authentication_key_id,
1498 ..
1499 }
1500 | UserMapping::HermeticSystemYubiHsm2Metrics {
1501 authentication_key_id,
1502 ..
1503 } => credentials.push(Box::new(signstar_yubihsm2::Credentials::new(
1504 *authentication_key_id,
1505 passphrase,
1506 ))),
1507 }
1508 }
1509
1510 Ok(CredentialsLoading::new(
1511 self.clone(),
1512 credentials,
1513 CredentialsLoadingErrors::new(errors),
1514 ))
1515 }
1516
1517 pub fn create_secrets_dir(&self) -> Result<(), Error> {
1532 let (system_user, user) = get_system_user_pair(self)?;
1534
1535 fail_if_not_root(&get_current_system_user()?)?;
1537
1538 let secrets_dir = get_user_secrets_dir(system_user.as_ref());
1540 create_dir_all(&secrets_dir).map_err(|source| {
1541 crate::non_admin_credentials::Error::SecretsDirCreate {
1542 path: secrets_dir.clone(),
1543 system_user: system_user.clone(),
1544 source,
1545 }
1546 })?;
1547
1548 let home_dir = get_home_base_dir_path().join(PathBuf::from(system_user.as_ref()));
1551 let mut chown_dir = secrets_dir.clone();
1552 while chown_dir != home_dir {
1553 chown(&chown_dir, Some(user.uid.as_raw()), Some(user.gid.as_raw())).map_err(
1554 |source| Error::Chown {
1555 path: chown_dir.to_path_buf(),
1556 user: system_user.to_string(),
1557 source,
1558 },
1559 )?;
1560 if let Some(parent) = &chown_dir.parent() {
1561 chown_dir = parent.to_path_buf()
1562 } else {
1563 break;
1564 }
1565 }
1566
1567 Ok(())
1568 }
1569
1570 pub fn create_non_administrative_secrets(
1596 &self,
1597 ) -> Result<Vec<Box<dyn UserWithPassphrase>>, Error> {
1598 let (system_user, user) = get_system_user_pair(self)?;
1600
1601 fail_if_not_root(&get_current_system_user()?)?;
1603
1604 let secret_handling = self.get_non_admin_secret_handling();
1605 let credentials =
1607 self.get_user_mapping()
1608 .backend_users_with_new_passphrase(UserMappingFilter {
1609 backend_user_kind: BackendUserKind::NonAdmin,
1610 });
1611
1612 for creds in credentials.iter() {
1614 let secrets_file = match secret_handling {
1615 NonAdministrativeSecretHandling::Plaintext => {
1616 get_plaintext_secret_file(system_user.as_ref(), &creds.user())
1617 }
1618 NonAdministrativeSecretHandling::SystemdCreds => {
1619 get_systemd_creds_secret_file(system_user.as_ref(), &creds.user())
1620 }
1621 };
1622
1623 info!(
1624 "Create secret for system user {system_user} and backend user {} in file: {secrets_file:?}",
1625 creds.user()
1626 );
1627 let secret = {
1628 match secret_handling {
1630 NonAdministrativeSecretHandling::Plaintext => {
1631 creds.passphrase().expose_borrowed().as_bytes().to_vec()
1632 }
1633 NonAdministrativeSecretHandling::SystemdCreds => {
1634 let creds_command = get_command("systemd-creds")?;
1636 let mut command = Command::new(creds_command);
1637 let command = command
1638 .arg("--user")
1639 .arg("--name=")
1640 .arg("--uid")
1641 .arg(system_user.as_ref())
1642 .arg("encrypt")
1643 .arg("-")
1644 .arg("-")
1645 .stdin(Stdio::piped())
1646 .stdout(Stdio::piped())
1647 .stderr(Stdio::piped());
1648 let mut command_child =
1649 command.spawn().map_err(|source| Error::CommandBackground {
1650 command: format!("{command:?}"),
1651 source,
1652 })?;
1653
1654 command_child
1656 .stdin
1657 .take()
1658 .ok_or(Error::CommandAttachToStdin {
1659 command: format!("{command:?}"),
1660 })?
1661 .write_all(creds.passphrase().expose_borrowed().as_bytes())
1662 .map_err(|source| Error::CommandWriteToStdin {
1663 command: format!("{command:?}"),
1664 source,
1665 })?;
1666
1667 let command_output =
1668 command_child.wait_with_output().map_err(|source| {
1669 Error::CommandExec {
1670 command: format!("{command:?}"),
1671 source,
1672 }
1673 })?;
1674
1675 if !command_output.status.success() {
1676 return Err(Error::CommandNonZero {
1677 command: format!("{command:?}"),
1678 exit_status: command_output.status,
1679 stderr: String::from_utf8_lossy(&command_output.stderr)
1680 .into_owned(),
1681 });
1682 }
1683 command_output.stdout
1684 }
1685 }
1686 };
1687
1688 let mut file = File::create(secrets_file.as_path()).map_err(|source| {
1690 {
1691 crate::non_admin_credentials::Error::SecretsFileCreate {
1692 path: secrets_file.clone(),
1693 system_user: system_user.clone(),
1694 source,
1695 }
1696 }
1697 })?;
1698 file.write_all(&secret).map_err(|source| {
1699 crate::non_admin_credentials::Error::SecretsFileWrite {
1700 path: secrets_file.clone(),
1701 system_user: system_user.clone(),
1702 source,
1703 }
1704 })?;
1705 chown(
1706 &secrets_file,
1707 Some(user.uid.as_raw()),
1708 Some(user.gid.as_raw()),
1709 )
1710 .map_err(|source| Error::Chown {
1711 path: secrets_file.clone(),
1712 user: system_user.to_string(),
1713 source,
1714 })?;
1715 set_permissions(
1716 secrets_file.as_path(),
1717 Permissions::from_mode(SECRET_FILE_MODE),
1718 )
1719 .map_err(|source| Error::ApplyPermissions {
1720 path: secrets_file.clone(),
1721 mode: SECRET_FILE_MODE,
1722 source,
1723 })?;
1724 }
1725
1726 Ok(credentials)
1727 }
1728}
1729
1730impl From<SignstarConfig> for Vec<ExtendedUserMapping> {
1731 fn from(value: SignstarConfig) -> Self {
1738 value
1739 .iter_user_mappings()
1740 .filter_map(|mapping| {
1741 if mapping.has_system_and_backend_user() {
1742 Some(ExtendedUserMapping {
1743 admin_secret_handling: value.get_administrative_secret_handling(),
1744 non_admin_secret_handling: value.get_non_administrative_secret_handling(),
1745 connections: value.iter_connections().cloned().collect(),
1746 user_mapping: mapping.clone(),
1747 })
1748 } else {
1749 None
1750 }
1751 })
1752 .collect()
1753 }
1754}
1755
1756#[cfg(test)]
1757mod tests {
1758 use log::{LevelFilter, debug};
1759 use rstest::rstest;
1760 use signstar_common::logging::setup_logging;
1761 use signstar_crypto::{key::CryptographicKeyContext, openpgp::OpenPgpUserIdList};
1762 use tempfile::{NamedTempFile, TempDir};
1763 use testresult::TestResult;
1764
1765 use super::*;
1766
1767 mod nethsm {
1768 use super::*;
1769
1770 #[rstest]
1773 #[case::admin(UserMapping::NetHsmOnlyAdmin("test".parse()?), None)]
1774 #[case::metrics(
1775 UserMapping::SystemNetHsmMetrics {
1776 nethsm_users: NetHsmMetricsUsers::new(
1777 SystemWideUserId::new("metrics".to_string())?,
1778 vec![
1779 UserId::new("operator".to_string())?,
1780 ],
1781 )?,
1782 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1783 system_user: "system-metrics".parse()?,
1784 },
1785 Some("system-metrics".parse()?),
1786 )]
1787 #[case::backup(
1788 UserMapping::SystemNetHsmBackup {
1789 nethsm_user: "backup".parse()?,
1790 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1791 system_user: "system-backup".parse()?,
1792 },
1793 Some("system-backup".parse()?),
1794 )]
1795 #[case::operator(
1796 UserMapping::SystemNetHsmOperatorSigning {
1797 nethsm_user: "operator".parse()?,
1798 key_id: "key1".parse()?,
1799 nethsm_key_setup: SigningKeySetup::new(
1800 "Curve25519".parse()?,
1801 vec!["EdDsaSignature".parse()?],
1802 None,
1803 "EdDsa".parse()?,
1804 CryptographicKeyContext::OpenPgp{
1805 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
1806 version: "v4".parse()?,
1807 },
1808 )?,
1809 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1810 system_user: "system-operator".parse()?,
1811 tag: "tag1".to_string(),
1812 },
1813 Some("system-operator".parse()?),
1814 )]
1815 #[case::hermetic_system_metrics(
1816 UserMapping::HermeticSystemNetHsmMetrics {
1817 nethsm_users: NetHsmMetricsUsers::new(
1818 "metrics".parse()?,
1819 vec!["operator".parse()?],
1820 )?,
1821 system_user: "system-metrics".parse()?,
1822 },
1823 Some("system-metrics".parse()?),
1824 )]
1825 fn user_mapping_get_system_user(
1826 #[case] mapping: UserMapping,
1827 #[case] result: Option<SystemUserId>,
1828 ) -> TestResult {
1829 assert_eq!(mapping.get_system_user(), result.as_ref());
1830 Ok(())
1831 }
1832
1833 #[rstest]
1836 #[case::admin_filter_default(
1837 UserMapping::NetHsmOnlyAdmin("admin".parse()?),
1838 UserMappingFilter::default(),
1839 &[],
1840 )]
1841 #[case::admin_filter_admin(
1842 UserMapping::NetHsmOnlyAdmin("admin".parse()?),
1843 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
1844 &["admin"],
1845 )]
1846 #[case::metrics_filter_default(
1847 UserMapping::SystemNetHsmMetrics {
1848 nethsm_users: NetHsmMetricsUsers::new(
1849 SystemWideUserId::new("metrics".to_string())?,
1850 vec![
1851 UserId::new("operator".to_string())?,
1852 ],
1853 )?,
1854 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1855 system_user: "system-metrics".parse()?,
1856 },
1857 UserMappingFilter::default(),
1858 &["metrics", "operator"],
1859 )]
1860 #[case::metrics_filter_admin(
1861 UserMapping::SystemNetHsmMetrics {
1862 nethsm_users: NetHsmMetricsUsers::new(
1863 SystemWideUserId::new("metrics".to_string())?,
1864 vec![
1865 UserId::new("operator".to_string())?,
1866 ],
1867 )?,
1868 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1869 system_user: "system-metrics".parse()?,
1870 },
1871 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
1872 &[],
1873 )]
1874 #[case::backup_filter_default(
1875 UserMapping::SystemNetHsmBackup {
1876 nethsm_user: "backup".parse()?,
1877 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1878 system_user: "system-backup".parse()?,
1879 },
1880 UserMappingFilter::default(),
1881 &["backup"],
1882 )]
1883 #[case::backup_filter_admin(
1884 UserMapping::SystemNetHsmBackup {
1885 nethsm_user: "backup".parse()?,
1886 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1887 system_user: "system-backup".parse()?,
1888 },
1889 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
1890 &[],
1891 )]
1892 #[case::operator_filter_default(
1893 UserMapping::SystemNetHsmOperatorSigning {
1894 nethsm_user: "operator".parse()?,
1895 key_id: "key1".parse()?,
1896 nethsm_key_setup: SigningKeySetup::new(
1897 "Curve25519".parse()?,
1898 vec!["EdDsaSignature".parse()?],
1899 None,
1900 "EdDsa".parse()?,
1901 CryptographicKeyContext::OpenPgp{
1902 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
1903 version: "v4".parse()?,
1904 },
1905 )?,
1906 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1907 system_user: "system-operator".parse()?,
1908 tag: "tag1".to_string(),
1909 },
1910 UserMappingFilter::default(),
1911 &["operator"],
1912 )]
1913 #[case::operator_filter_admin(
1914 UserMapping::SystemNetHsmOperatorSigning {
1915 nethsm_user: "operator".parse()?,
1916 key_id: "key1".parse()?,
1917 nethsm_key_setup: SigningKeySetup::new(
1918 "Curve25519".parse()?,
1919 vec!["EdDsaSignature".parse()?],
1920 None,
1921 "EdDsa".parse()?,
1922 CryptographicKeyContext::OpenPgp{
1923 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
1924 version: "v4".parse()?,
1925 },
1926 )?,
1927 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1928 system_user: "system-operator".parse()?,
1929 tag: "tag1".to_string(),
1930 },
1931 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
1932 &[],
1933 )]
1934 #[case::hermetic_system_metrics_filter_default(
1935 UserMapping::HermeticSystemNetHsmMetrics {
1936 nethsm_users: NetHsmMetricsUsers::new(
1937 "metrics".parse()?,
1938 vec!["operator".parse()?],
1939 )?,
1940 system_user: "system-metrics".parse()?,
1941 },
1942 UserMappingFilter::default(),
1943 &["metrics", "operator"],
1944 )]
1945 #[case::hermetic_system_metrics_filter_admin(
1946 UserMapping::HermeticSystemNetHsmMetrics {
1947 nethsm_users: NetHsmMetricsUsers::new(
1948 "metrics".parse()?,
1949 vec!["operator".parse()?],
1950 )?,
1951 system_user: "system-metrics".parse()?,
1952 },
1953 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
1954 &[],
1955 )]
1956 fn user_mapping_backend_users(
1957 #[case] mapping: UserMapping,
1958 #[case] filter: UserMappingFilter,
1959 #[case] expected_names: &[&str],
1960 ) -> TestResult {
1961 assert_eq!(mapping.backend_users(filter), expected_names);
1962 Ok(())
1963 }
1964
1965 #[rstest]
1968 #[case::admin_filter_default(
1969 UserMapping::NetHsmOnlyAdmin("admin".parse()?),
1970 UserMappingFilter::default(),
1971 0
1972 )]
1973 #[case::admin_filter_admin(
1974 UserMapping::NetHsmOnlyAdmin("admin".parse()?),
1975 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
1976 1
1977 )]
1978 #[case::metrics_filter_default(
1979 UserMapping::SystemNetHsmMetrics {
1980 nethsm_users: NetHsmMetricsUsers::new(
1981 SystemWideUserId::new("metrics".to_string())?,
1982 vec![
1983 UserId::new("operator".to_string())?,
1984 ],
1985 )?,
1986 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
1987 system_user: "system-metrics".parse()?,
1988 },
1989 UserMappingFilter::default(),
1990 2
1991 )]
1992 #[case::metrics_filter_admin(
1993 UserMapping::SystemNetHsmMetrics {
1994 nethsm_users: NetHsmMetricsUsers::new(
1995 SystemWideUserId::new("metrics".to_string())?,
1996 vec![
1997 UserId::new("operator".to_string())?,
1998 ],
1999 )?,
2000 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2001 system_user: "system-metrics".parse()?,
2002 },
2003 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
2004 0
2005 )]
2006 #[case::backup_filter_default(
2007 UserMapping::SystemNetHsmBackup {
2008 nethsm_user: "backup".parse()?,
2009 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2010 system_user: "system-backup".parse()?,
2011 },
2012 UserMappingFilter::default(),
2013 1
2014 )]
2015 #[case::backup_filter_admin(
2016 UserMapping::SystemNetHsmBackup {
2017 nethsm_user: "backup".parse()?,
2018 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2019 system_user: "system-backup".parse()?,
2020 },
2021 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
2022 0
2023 )]
2024 #[case::operator_filter_default(
2025 UserMapping::SystemNetHsmOperatorSigning {
2026 nethsm_user: "operator".parse()?,
2027 key_id: "key1".parse()?,
2028 nethsm_key_setup: SigningKeySetup::new(
2029 "Curve25519".parse()?,
2030 vec!["EdDsaSignature".parse()?],
2031 None,
2032 "EdDsa".parse()?,
2033 CryptographicKeyContext::OpenPgp{
2034 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2035 version: "v4".parse()?,
2036 },
2037 )?,
2038 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2039 system_user: "system-operator".parse()?,
2040 tag: "tag1".to_string(),
2041 },
2042 UserMappingFilter::default(),
2043 1
2044 )]
2045 #[case::operator_filter_admin(
2046 UserMapping::SystemNetHsmOperatorSigning {
2047 nethsm_user: "operator".parse()?,
2048 key_id: "key1".parse()?,
2049 nethsm_key_setup: SigningKeySetup::new(
2050 "Curve25519".parse()?,
2051 vec!["EdDsaSignature".parse()?],
2052 None,
2053 "EdDsa".parse()?,
2054 CryptographicKeyContext::OpenPgp{
2055 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2056 version: "v4".parse()?,
2057 },
2058 )?,
2059 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2060 system_user: "system-operator".parse()?,
2061 tag: "tag1".to_string(),
2062 },
2063 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
2064 0
2065 )]
2066 #[case::hermetic_system_metrics_filter_default(
2067 UserMapping::HermeticSystemNetHsmMetrics {
2068 nethsm_users: NetHsmMetricsUsers::new(
2069 "metrics".parse()?,
2070 vec!["operator".parse()?],
2071 )?,
2072 system_user: "system-metrics".parse()?,
2073 },
2074 UserMappingFilter::default(),
2075 2
2076 )]
2077 #[case::hermetic_system_metrics_filter_admin(
2078 UserMapping::HermeticSystemNetHsmMetrics {
2079 nethsm_users: NetHsmMetricsUsers::new(
2080 "metrics".parse()?,
2081 vec!["operator".parse()?],
2082 )?,
2083 system_user: "system-metrics".parse()?,
2084 },
2085 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
2086 0
2087 )]
2088 fn user_mapping_backend_users_with_new_passphrase(
2089 #[case] mapping: UserMapping,
2090 #[case] filter: UserMappingFilter,
2091 #[case] expected_length: usize,
2092 ) -> TestResult {
2093 assert_eq!(
2094 mapping.backend_users_with_new_passphrase(filter).len(),
2095 expected_length
2096 );
2097 Ok(())
2098 }
2099
2100 #[rstest]
2103 #[case::admin(UserMapping::NetHsmOnlyAdmin("test".parse()?), vec!["test".parse()?])]
2104 #[case::metrics(
2105 UserMapping::SystemNetHsmMetrics {
2106 nethsm_users: NetHsmMetricsUsers::new(
2107 SystemWideUserId::new("metrics".to_string())?,
2108 vec![
2109 UserId::new("operator".to_string())?,
2110 ],
2111 )?,
2112 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2113 system_user: "system-metrics".parse()?,
2114 },
2115 vec!["metrics".parse()?, "operator".parse()?],
2116 )]
2117 #[case::backup(
2118 UserMapping::SystemNetHsmBackup {
2119 nethsm_user: "backup".parse()?,
2120 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2121 system_user: "system-backup".parse()?,
2122 },
2123 vec!["backup".parse()?],
2124 )]
2125 #[case::operator(
2126 UserMapping::SystemNetHsmOperatorSigning {
2127 nethsm_user: "operator".parse()?,
2128 key_id: "key1".parse()?,
2129 nethsm_key_setup: SigningKeySetup::new(
2130 "Curve25519".parse()?,
2131 vec!["EdDsaSignature".parse()?],
2132 None,
2133 "EdDsa".parse()?,
2134 CryptographicKeyContext::OpenPgp{
2135 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2136 version: "v4".parse()?,
2137 },
2138 )?,
2139 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2140 system_user: "system-operator".parse()?,
2141 tag: "tag1".to_string(),
2142 },
2143 vec!["operator".parse()?],
2144 )]
2145 #[case::hermetic_system_metrics(
2146 UserMapping::HermeticSystemNetHsmMetrics {
2147 nethsm_users: NetHsmMetricsUsers::new(
2148 "metrics".parse()?,
2149 vec!["operator".parse()?],
2150 )?,
2151 system_user: "system-metrics".parse()?,
2152 },
2153 vec!["metrics".parse()?, "operator".parse()?],
2154 )]
2155 fn user_mapping_get_nethsm_users(
2156 #[case] mapping: UserMapping,
2157 #[case] expected: Vec<UserId>,
2158 ) -> TestResult {
2159 assert_eq!(mapping.get_nethsm_users(), expected);
2160 Ok(())
2161 }
2162
2163 #[rstest]
2166 #[case::systemwide_admin(
2167 UserMapping::NetHsmOnlyAdmin("admin".parse()?),
2168 vec![("admin".parse()?, UserRole::Administrator)],
2169 )]
2170 #[case::namespace_admin(
2171 UserMapping::NetHsmOnlyAdmin("ns1~admin".parse()?),
2172 vec![("ns1~admin".parse()?, UserRole::Administrator)],
2173 )]
2174 #[case::metrics(
2175 UserMapping::SystemNetHsmMetrics {
2176 nethsm_users: NetHsmMetricsUsers::new(
2177 SystemWideUserId::new("metrics".to_string())?,
2178 vec![
2179 UserId::new("operator".to_string())?,
2180 ],
2181 )?,
2182 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2183 system_user: "system-metrics".parse()?,
2184 },
2185 vec![("metrics".parse()?, UserRole::Metrics), ("operator".parse()?, UserRole::Operator)],
2186 )]
2187 #[case::backup(
2188 UserMapping::SystemNetHsmBackup {
2189 nethsm_user: "backup".parse()?,
2190 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2191 system_user: "system-backup".parse()?,
2192 },
2193 vec![("backup".parse()?, UserRole::Backup)],
2194 )]
2195 #[case::systemwide_operator(
2196 UserMapping::SystemNetHsmOperatorSigning {
2197 nethsm_user: "operator".parse()?,
2198 key_id: "key1".parse()?,
2199 nethsm_key_setup: SigningKeySetup::new(
2200 "Curve25519".parse()?,
2201 vec!["EdDsaSignature".parse()?],
2202 None,
2203 "EdDsa".parse()?,
2204 CryptographicKeyContext::OpenPgp{
2205 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2206 version: "v4".parse()?,
2207 },
2208 )?,
2209 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2210 system_user: "system-operator".parse()?,
2211 tag: "tag1".to_string(),
2212 },
2213 vec![(
2214 "operator".parse()?,
2215 UserRole::Operator,
2216 )],
2217 )]
2218 #[case::namespace_operator(
2219 UserMapping::SystemNetHsmOperatorSigning {
2220 nethsm_user: "ns1~operator".parse()?,
2221 key_id: "key1".parse()?,
2222 nethsm_key_setup: SigningKeySetup::new(
2223 "Curve25519".parse()?,
2224 vec!["EdDsaSignature".parse()?],
2225 None,
2226 "EdDsa".parse()?,
2227 CryptographicKeyContext::OpenPgp{
2228 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2229 version: "v4".parse()?,
2230 },
2231 )?,
2232 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2233 system_user: "system-operator".parse()?,
2234 tag: "tag1".to_string(),
2235 },
2236 vec![(
2237 "ns1~operator".parse()?,
2238 UserRole::Operator,
2239 )],
2240 )]
2241 #[case::hermetic_system_metrics(
2242 UserMapping::HermeticSystemNetHsmMetrics {
2243 nethsm_users: NetHsmMetricsUsers::new(
2244 "metrics".parse()?,
2245 vec!["operator".parse()?],
2246 )?,
2247 system_user: "system-metrics".parse()?,
2248 },
2249 vec![
2250 ("metrics".parse()?, UserRole::Metrics),
2251 ("operator".parse()?, UserRole::Operator),
2252 ],
2253 )]
2254 fn usermapping_get_nethsm_users_and_roles(
2255 #[case] mapping: UserMapping,
2256 #[case] output: Vec<(UserId, UserRole)>,
2257 ) -> TestResult {
2258 assert_eq!(mapping.get_nethsm_users_and_roles(), output);
2259 Ok(())
2260 }
2261
2262 #[rstest]
2265 #[case::admin_filter_all(UserMapping::NetHsmOnlyAdmin("test".parse()?), FilterUserKeys::All, Vec::new())]
2266 #[case::metrics(
2267 UserMapping::SystemNetHsmMetrics {
2268 nethsm_users: NetHsmMetricsUsers::new(
2269 SystemWideUserId::new("metrics".to_string())?,
2270 vec![
2271 UserId::new("operator".to_string())?,
2272 ],
2273 )?,
2274 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2275 system_user: "system-metrics".parse()?,
2276 },
2277 FilterUserKeys::All,
2278 Vec::new(),
2279 )]
2280 #[case::backup_filter_all(
2281 UserMapping::SystemNetHsmBackup {
2282 nethsm_user: "backup".parse()?,
2283 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2284 system_user: "system-backup".parse()?,
2285 },
2286 FilterUserKeys::All,
2287 Vec::new(),
2288 )]
2289 #[case::operator_signing_filter_all(
2290 UserMapping::SystemNetHsmOperatorSigning {
2291 nethsm_user: "operator".parse()?,
2292 key_id: "key1".parse()?,
2293 nethsm_key_setup: SigningKeySetup::new(
2294 "Curve25519".parse()?,
2295 vec!["EdDsaSignature".parse()?],
2296 None,
2297 "EdDsa".parse()?,
2298 CryptographicKeyContext::OpenPgp{
2299 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2300 version: "v4".parse()?,
2301 },
2302 )?,
2303 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2304 system_user: "system-operator".parse()?,
2305 tag: "tag1".to_string(),
2306 },
2307 FilterUserKeys::All,
2308 vec![(
2309 "operator".parse()?,
2310 "key1".parse()?,
2311 SigningKeySetup::new(
2312 "Curve25519".parse()?,
2313 vec!["EdDsaSignature".parse()?],
2314 None,
2315 "EdDsa".parse()?,
2316 CryptographicKeyContext::OpenPgp{
2317 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2318 version: "v4".parse()?,
2319 },
2320 )?,
2321 "tag1".to_string(),
2322 )],
2323 )]
2324 #[case::systemwide_operator_filter_namespaced(
2325 UserMapping::SystemNetHsmOperatorSigning {
2326 nethsm_user: "operator".parse()?,
2327 key_id: "key1".parse()?,
2328 nethsm_key_setup: SigningKeySetup::new(
2329 "Curve25519".parse()?,
2330 vec!["EdDsaSignature".parse()?],
2331 None,
2332 "EdDsa".parse()?,
2333 CryptographicKeyContext::OpenPgp{
2334 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2335 version: "v4".parse()?,
2336 },
2337 )?,
2338 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2339 system_user: "system-operator".parse()?,
2340 tag: "tag1".to_string(),
2341 },
2342 FilterUserKeys::Namespaced,
2343 Vec::new(),
2344 )]
2345 #[case::systemwide_operator_filter_namespace(
2346 UserMapping::SystemNetHsmOperatorSigning {
2347 nethsm_user: "operator".parse()?,
2348 key_id: "key1".parse()?,
2349 nethsm_key_setup: SigningKeySetup::new(
2350 "Curve25519".parse()?,
2351 vec!["EdDsaSignature".parse()?],
2352 None,
2353 "EdDsa".parse()?,
2354 CryptographicKeyContext::OpenPgp{
2355 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2356 version: "v4".parse()?,
2357 },
2358 )?,
2359 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2360 system_user: "system-operator".parse()?,
2361 tag: "tag1".to_string(),
2362 },
2363 FilterUserKeys::Namespace("ns1".parse()?),
2364 Vec::new(),
2365 )]
2366 #[case::namespace_operator_filter_namespaced(
2367 UserMapping::SystemNetHsmOperatorSigning {
2368 nethsm_user: "ns1~operator".parse()?,
2369 key_id: "key1".parse()?,
2370 nethsm_key_setup: SigningKeySetup::new(
2371 "Curve25519".parse()?,
2372 vec!["EdDsaSignature".parse()?],
2373 None,
2374 "EdDsa".parse()?,
2375 CryptographicKeyContext::OpenPgp{
2376 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2377 version: "v4".parse()?,
2378 },
2379 )?,
2380 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2381 system_user: "system-operator".parse()?,
2382 tag: "tag1".to_string(),
2383 },
2384 FilterUserKeys::Namespaced,
2385 vec![(
2386 "ns1~operator".parse()?,
2387 "key1".parse()?,
2388 SigningKeySetup::new(
2389 "Curve25519".parse()?,
2390 vec!["EdDsaSignature".parse()?],
2391 None,
2392 "EdDsa".parse()?,
2393 CryptographicKeyContext::OpenPgp{
2394 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2395 version: "v4".parse()?,
2396 },
2397 )?,
2398 "tag1".to_string(),
2399 )],
2400 )]
2401 #[case::namespace_operator_filter_matching_namespace(
2402 UserMapping::SystemNetHsmOperatorSigning {
2403 nethsm_user: "ns1~operator".parse()?,
2404 key_id: "key1".parse()?,
2405 nethsm_key_setup: SigningKeySetup::new(
2406 "Curve25519".parse()?,
2407 vec!["EdDsaSignature".parse()?],
2408 None,
2409 "EdDsa".parse()?,
2410 CryptographicKeyContext::OpenPgp{
2411 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2412 version: "v4".parse()?,
2413 },
2414 )?,
2415 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2416 system_user: "system-operator".parse()?,
2417 tag: "tag1".to_string(),
2418 },
2419 FilterUserKeys::Namespace("ns1".parse()?),
2420 vec![(
2421 "ns1~operator".parse()?,
2422 "key1".parse()?,
2423 SigningKeySetup::new(
2424 "Curve25519".parse()?,
2425 vec!["EdDsaSignature".parse()?],
2426 None,
2427 "EdDsa".parse()?,
2428 CryptographicKeyContext::OpenPgp{
2429 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2430 version: "v4".parse()?,
2431 },
2432 )?,
2433 "tag1".to_string(),
2434 )],
2435 )]
2436 #[case::namespace_operator_filter_matching_tag(
2437 UserMapping::SystemNetHsmOperatorSigning {
2438 nethsm_user: "ns1~operator".parse()?,
2439 key_id: "key1".parse()?,
2440 nethsm_key_setup: SigningKeySetup::new(
2441 "Curve25519".parse()?,
2442 vec!["EdDsaSignature".parse()?],
2443 None,
2444 "EdDsa".parse()?,
2445 CryptographicKeyContext::OpenPgp{
2446 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2447 version: "v4".parse()?,
2448 },
2449 )?,
2450 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2451 system_user: "system-operator".parse()?,
2452 tag: "tag1".to_string(),
2453 },
2454 FilterUserKeys::Tag("tag1".parse()?),
2455 vec![(
2456 "ns1~operator".parse()?,
2457 "key1".parse()?,
2458 SigningKeySetup::new(
2459 "Curve25519".parse()?,
2460 vec!["EdDsaSignature".parse()?],
2461 None,
2462 "EdDsa".parse()?,
2463 CryptographicKeyContext::OpenPgp{
2464 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2465 version: "v4".parse()?,
2466 },
2467 )?,
2468 "tag1".to_string(),
2469 )],
2470 )]
2471 #[case::namespace_operator_filter_mismatching_tag(
2472 UserMapping::SystemNetHsmOperatorSigning {
2473 nethsm_user: "ns1~operator".parse()?,
2474 key_id: "key1".parse()?,
2475 nethsm_key_setup: SigningKeySetup::new(
2476 "Curve25519".parse()?,
2477 vec!["EdDsaSignature".parse()?],
2478 None,
2479 "EdDsa".parse()?,
2480 CryptographicKeyContext::OpenPgp{
2481 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2482 version: "v4".parse()?,
2483 },
2484 )?,
2485 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2486 system_user: "system-operator".parse()?,
2487 tag: "tag2".to_string(),
2488 },
2489 FilterUserKeys::Tag("tag1".parse()?),
2490 Vec::new(),
2491 )]
2492 #[case::hermetic_system_metrics_filter_all(
2493 UserMapping::HermeticSystemNetHsmMetrics {
2494 nethsm_users: NetHsmMetricsUsers::new(
2495 "metrics".parse()?,
2496 vec!["operator".parse()?],
2497 )?,
2498 system_user: "system-metrics".parse()?,
2499 },
2500 FilterUserKeys::All,
2501 Vec::new(),
2502 )]
2503 fn user_mapping_get_nethsm_user_key_and_tag(
2504 #[case] mapping: UserMapping,
2505 #[case] filter: FilterUserKeys,
2506 #[case] output: Vec<(UserId, KeyId, SigningKeySetup, String)>,
2507 ) -> TestResult {
2508 assert_eq!(mapping.get_nethsm_user_key_and_tag(filter), output);
2509 Ok(())
2510 }
2511
2512 #[rstest]
2515 #[case::system_wide_admin(
2516 UserMapping::NetHsmOnlyAdmin("test".parse()?),
2517 vec![("test".parse()?, UserRole::Administrator, Vec::new())],
2518 )]
2519 #[case::metrics(
2520 UserMapping::SystemNetHsmMetrics {
2521 nethsm_users: NetHsmMetricsUsers::new(
2522 SystemWideUserId::new("metrics".to_string())?,
2523 vec![
2524 UserId::new("operator".to_string())?,
2525 ],
2526 )?,
2527 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2528 system_user: "system-metrics".parse()?,
2529 },
2530 vec![("metrics".parse()?, UserRole::Metrics, Vec::new()), ("operator".parse()?, UserRole::Operator, Vec::new())],
2531 )]
2532 #[case::backup(
2533 UserMapping::SystemNetHsmBackup {
2534 nethsm_user: "backup".parse()?,
2535 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2536 system_user: "system-backup".parse()?,
2537 },
2538 vec![("backup".parse()?, UserRole::Backup, Vec::new())],
2539 )]
2540 #[case::system_wide_operator(
2541 UserMapping::SystemNetHsmOperatorSigning {
2542 nethsm_user: "operator".parse()?,
2543 key_id: "key1".parse()?,
2544 nethsm_key_setup: SigningKeySetup::new(
2545 "Curve25519".parse()?,
2546 vec!["EdDsaSignature".parse()?],
2547 None,
2548 "EdDsa".parse()?,
2549 CryptographicKeyContext::OpenPgp{
2550 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2551 version: "v4".parse()?,
2552 },
2553 )?,
2554 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2555 system_user: "system-operator".parse()?,
2556 tag: "tag1".to_string(),
2557 },
2558 vec![("operator".parse()?, UserRole::Operator, vec!["tag1".to_string()])],
2559 )]
2560 #[case::namespace_operator(
2561 UserMapping::SystemNetHsmOperatorSigning {
2562 nethsm_user: "ns1~operator".parse()?,
2563 key_id: "key1".parse()?,
2564 nethsm_key_setup: SigningKeySetup::new(
2565 "Curve25519".parse()?,
2566 vec!["EdDsaSignature".parse()?],
2567 None,
2568 "EdDsa".parse()?,
2569 CryptographicKeyContext::OpenPgp{
2570 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2571 version: "v4".parse()?,
2572 },
2573 )?,
2574 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2575 system_user: "system-operator".parse()?,
2576 tag: "tag1".to_string(),
2577 },
2578 vec![("ns1~operator".parse()?, UserRole::Operator, vec!["tag1".to_string()])],
2579 )]
2580 #[case::hermetic_system_metrics_filter_all(
2581 UserMapping::HermeticSystemNetHsmMetrics {
2582 nethsm_users: NetHsmMetricsUsers::new(
2583 "metrics".parse()?,
2584 vec!["operator".parse()?],
2585 )?,
2586 system_user: "system-metrics".parse()?,
2587 },
2588 vec![("metrics".parse()?, UserRole::Metrics, Vec::new()), ("operator".parse()?, UserRole::Operator, Vec::new())],
2589 )]
2590 fn user_mapping_get_nethsm_user_role_and_tags(
2591 #[case] mapping: UserMapping,
2592 #[case] expected: Vec<(UserId, UserRole, Vec<String>)>,
2593 ) -> TestResult {
2594 assert_eq!(mapping.get_nethsm_user_role_and_tags(), expected);
2595 Ok(())
2596 }
2597
2598 #[rstest]
2601 #[case::system_wide_admin(UserMapping::NetHsmOnlyAdmin("test".parse()?), None)]
2602 #[case::metrics(
2603 UserMapping::SystemNetHsmMetrics {
2604 nethsm_users: NetHsmMetricsUsers::new(
2605 SystemWideUserId::new("metrics".to_string())?,
2606 vec![
2607 UserId::new("operator".to_string())?,
2608 ],
2609 )?,
2610 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2611 system_user: "system-metrics".parse()?,
2612 },
2613 Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?),
2614 )]
2615 #[case::backup(
2616 UserMapping::SystemNetHsmBackup {
2617 nethsm_user: "backup".parse()?,
2618 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2619 system_user: "system-backup".parse()?,
2620 },
2621 Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?),
2622 )]
2623 #[case::system_wide_operator(
2624 UserMapping::SystemNetHsmOperatorSigning {
2625 nethsm_user: "operator".parse()?,
2626 key_id: "key1".parse()?,
2627 nethsm_key_setup: SigningKeySetup::new(
2628 "Curve25519".parse()?,
2629 vec!["EdDsaSignature".parse()?],
2630 None,
2631 "EdDsa".parse()?,
2632 CryptographicKeyContext::OpenPgp{
2633 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2634 version: "v4".parse()?,
2635 },
2636 )?,
2637 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2638 system_user: "system-operator".parse()?,
2639 tag: "tag1".to_string(),
2640 },
2641 Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?),
2642 )]
2643 #[case::namespace_operator(
2644 UserMapping::SystemNetHsmOperatorSigning {
2645 nethsm_user: "ns1~operator".parse()?,
2646 key_id: "key1".parse()?,
2647 nethsm_key_setup: SigningKeySetup::new(
2648 "Curve25519".parse()?,
2649 vec!["EdDsaSignature".parse()?],
2650 None,
2651 "EdDsa".parse()?,
2652 CryptographicKeyContext::OpenPgp{
2653 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2654 version: "v4".parse()?,
2655 },
2656 )?,
2657 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2658 system_user: "system-operator".parse()?,
2659 tag: "tag1".to_string(),
2660 },
2661 Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?),
2662 )]
2663 #[case::hermetic_system_metrics_filter_all(
2664 UserMapping::HermeticSystemNetHsmMetrics {
2665 nethsm_users: NetHsmMetricsUsers::new(
2666 "metrics".parse()?,
2667 vec!["operator".parse()?],
2668 )?,
2669 system_user: "system-metrics".parse()?,
2670 },
2671 None,
2672 )]
2673 fn user_mapping_get_ssh_authorized_key(
2674 #[case] mapping: UserMapping,
2675 #[case] output: Option<AuthorizedKeyEntry>,
2676 ) -> TestResult {
2677 assert_eq!(mapping.get_ssh_authorized_key(), output.as_ref());
2678 Ok(())
2679 }
2680
2681 #[rstest]
2684 #[case::system_wide_admin(UserMapping::NetHsmOnlyAdmin("test".parse()?), None, Vec::new())]
2685 #[case::metrics(
2686 UserMapping::SystemNetHsmMetrics {
2687 nethsm_users: NetHsmMetricsUsers::new(
2688 SystemWideUserId::new("metrics".to_string())?,
2689 vec![
2690 UserId::new("operator".to_string())?,
2691 ],
2692 )?,
2693 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2694 system_user: "system-metrics".parse()?,
2695 },
2696 None,
2697 Vec::new()
2698 )]
2699 #[case::backup(
2700 UserMapping::SystemNetHsmBackup {
2701 nethsm_user: "backup".parse()?,
2702 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2703 system_user: "system-backup".parse()?,
2704 },
2705 None,
2706 Vec::new()
2707 )]
2708 #[case::system_wide_operator_target_system_wide(
2709 UserMapping::SystemNetHsmOperatorSigning {
2710 nethsm_user: "operator".parse()?,
2711 key_id: "key1".parse()?,
2712 nethsm_key_setup: SigningKeySetup::new(
2713 "Curve25519".parse()?,
2714 vec!["EdDsaSignature".parse()?],
2715 None,
2716 "EdDsa".parse()?,
2717 CryptographicKeyContext::OpenPgp{
2718 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2719 version: "v4".parse()?,
2720 },
2721 )?,
2722 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2723 system_user: "system-operator".parse()?,
2724 tag: "tag1".to_string(),
2725 },
2726 None,
2727 vec!["key1".parse()?],
2728 )]
2729 #[case::system_wide_operator_target_namespace(
2730 UserMapping::SystemNetHsmOperatorSigning {
2731 nethsm_user: "operator".parse()?,
2732 key_id: "key1".parse()?,
2733 nethsm_key_setup: SigningKeySetup::new(
2734 "Curve25519".parse()?,
2735 vec!["EdDsaSignature".parse()?],
2736 None,
2737 "EdDsa".parse()?,
2738 CryptographicKeyContext::OpenPgp{
2739 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2740 version: "v4".parse()?,
2741 },
2742 )?,
2743 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2744 system_user: "system-operator".parse()?,
2745 tag: "tag1".to_string(),
2746 },
2747 Some("ns1".parse()?),
2748 Vec::new(),
2749 )]
2750 #[case::namespace_operator_target_system_wide(
2751 UserMapping::SystemNetHsmOperatorSigning {
2752 nethsm_user: "ns1~operator".parse()?,
2753 key_id: "key1".parse()?,
2754 nethsm_key_setup: SigningKeySetup::new(
2755 "Curve25519".parse()?,
2756 vec!["EdDsaSignature".parse()?],
2757 None,
2758 "EdDsa".parse()?,
2759 CryptographicKeyContext::OpenPgp{
2760 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2761 version: "v4".parse()?,
2762 },
2763 )?,
2764 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2765 system_user: "system-operator".parse()?,
2766 tag: "tag1".to_string(),
2767 },
2768 None,
2769 Vec::new(),
2770 )]
2771 #[case::namespace_operator_target_namespace(
2772 UserMapping::SystemNetHsmOperatorSigning {
2773 nethsm_user: "ns1~operator".parse()?,
2774 key_id: "key1".parse()?,
2775 nethsm_key_setup: SigningKeySetup::new(
2776 "Curve25519".parse()?,
2777 vec!["EdDsaSignature".parse()?],
2778 None,
2779 "EdDsa".parse()?,
2780 CryptographicKeyContext::OpenPgp{
2781 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2782 version: "v4".parse()?,
2783 },
2784 )?,
2785 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2786 system_user: "system-operator".parse()?,
2787 tag: "tag1".to_string(),
2788 },
2789 Some("ns1".parse()?),
2790 vec!["key1".parse()?],
2791 )]
2792 #[case::hermetic_system_metrics_filter_all(
2793 UserMapping::HermeticSystemNetHsmMetrics {
2794 nethsm_users: NetHsmMetricsUsers::new(
2795 "metrics".parse()?,
2796 vec!["operator".parse()?],
2797 )?,
2798 system_user: "system-metrics".parse()?,
2799 },
2800 None,
2801 Vec::new()
2802 )]
2803 fn user_mapping_get_nethsm_key_ids(
2804 #[case] mapping: UserMapping,
2805 #[case] namespace: Option<NamespaceId>,
2806 #[case] output: Vec<KeyId>,
2807 ) -> TestResult {
2808 assert_eq!(mapping.get_nethsm_key_ids(namespace.as_ref()), output);
2809 Ok(())
2810 }
2811
2812 #[rstest]
2815 #[case::system_wide_admin(UserMapping::NetHsmOnlyAdmin("test".parse()?), None, Vec::new())]
2816 #[case::metrics(
2817 UserMapping::SystemNetHsmMetrics {
2818 nethsm_users: NetHsmMetricsUsers::new(
2819 SystemWideUserId::new("metrics".to_string())?,
2820 vec![
2821 UserId::new("operator".to_string())?,
2822 ],
2823 )?,
2824 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2825 system_user: "system-metrics".parse()?,
2826 },
2827 None,
2828 Vec::new()
2829 )]
2830 #[case::backup(
2831 UserMapping::SystemNetHsmBackup {
2832 nethsm_user: "backup".parse()?,
2833 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2834 system_user: "system-backup".parse()?,
2835 },
2836 None,
2837 Vec::new()
2838 )]
2839 #[case::system_wide_operator_target_system_wide(
2840 UserMapping::SystemNetHsmOperatorSigning {
2841 nethsm_user: "operator".parse()?,
2842 key_id: "key1".parse()?,
2843 nethsm_key_setup: SigningKeySetup::new(
2844 "Curve25519".parse()?,
2845 vec!["EdDsaSignature".parse()?],
2846 None,
2847 "EdDsa".parse()?,
2848 CryptographicKeyContext::OpenPgp{
2849 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2850 version: "v4".parse()?,
2851 },
2852 )?,
2853 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2854 system_user: "system-operator".parse()?,
2855 tag: "tag1".to_string(),
2856 },
2857 None,
2858 vec!["tag1"],
2859 )]
2860 #[case::system_wide_operator_target_namespace(
2861 UserMapping::SystemNetHsmOperatorSigning {
2862 nethsm_user: "operator".parse()?,
2863 key_id: "key1".parse()?,
2864 nethsm_key_setup: SigningKeySetup::new(
2865 "Curve25519".parse()?,
2866 vec!["EdDsaSignature".parse()?],
2867 None,
2868 "EdDsa".parse()?,
2869 CryptographicKeyContext::OpenPgp{
2870 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2871 version: "v4".parse()?,
2872 },
2873 )?,
2874 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2875 system_user: "system-operator".parse()?,
2876 tag: "tag1".to_string(),
2877 },
2878 Some("ns1".parse()?),
2879 Vec::new(),
2880 )]
2881 #[case::namespace_operator_target_system_wide(
2882 UserMapping::SystemNetHsmOperatorSigning {
2883 nethsm_user: "ns1~operator".parse()?,
2884 key_id: "key1".parse()?,
2885 nethsm_key_setup: SigningKeySetup::new(
2886 "Curve25519".parse()?,
2887 vec!["EdDsaSignature".parse()?],
2888 None,
2889 "EdDsa".parse()?,
2890 CryptographicKeyContext::OpenPgp{
2891 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2892 version: "v4".parse()?,
2893 },
2894 )?,
2895 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2896 system_user: "system-operator".parse()?,
2897 tag: "tag1".to_string(),
2898 },
2899 None,
2900 Vec::new(),
2901 )]
2902 #[case::namespace_operator_target_namespace(
2903 UserMapping::SystemNetHsmOperatorSigning {
2904 nethsm_user: "ns1~operator".parse()?,
2905 key_id: "key1".parse()?,
2906 nethsm_key_setup: SigningKeySetup::new(
2907 "Curve25519".parse()?,
2908 vec!["EdDsaSignature".parse()?],
2909 None,
2910 "EdDsa".parse()?,
2911 CryptographicKeyContext::OpenPgp{
2912 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2913 version: "v4".parse()?,
2914 },
2915 )?,
2916 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2917 system_user: "system-operator".parse()?,
2918 tag: "tag1".to_string(),
2919 },
2920 Some("ns1".parse()?),
2921 vec!["tag1"],
2922 )]
2923 #[case::hermetic_system_metrics_filter_all(
2924 UserMapping::HermeticSystemNetHsmMetrics {
2925 nethsm_users: NetHsmMetricsUsers::new(
2926 "metrics".parse()?,
2927 vec!["operator".parse()?],
2928 )?,
2929 system_user: "system-metrics".parse()?,
2930 },
2931 None,
2932 Vec::new()
2933 )]
2934 fn user_mapping_get_nethsm_tags(
2935 #[case] mapping: UserMapping,
2936 #[case] namespace: Option<NamespaceId>,
2937 #[case] output: Vec<&str>,
2938 ) -> TestResult {
2939 assert_eq!(mapping.get_nethsm_tags(namespace.as_ref()), output);
2940 Ok(())
2941 }
2942
2943 #[rstest]
2946 #[case::system_wide_admin(UserMapping::NetHsmOnlyAdmin("test".parse()?), Vec::new())]
2947 #[case::namespace_admin(UserMapping::NetHsmOnlyAdmin("ns1~test".parse()?), vec!["ns1".parse()?])]
2948 #[case::metrics(
2949 UserMapping::SystemNetHsmMetrics {
2950 nethsm_users: NetHsmMetricsUsers::new(
2951 SystemWideUserId::new("metrics".to_string())?,
2952 vec![
2953 UserId::new("operator".to_string())?,
2954 ],
2955 )?,
2956 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2957 system_user: "system-metrics".parse()?,
2958 },
2959 Vec::new(),
2960 )]
2961 #[case::backup(
2962 UserMapping::SystemNetHsmBackup {
2963 nethsm_user: "backup".parse()?,
2964 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2965 system_user: "system-backup".parse()?,
2966 },
2967 Vec::new(),
2968 )]
2969 #[case::system_wide_operator(
2970 UserMapping::SystemNetHsmOperatorSigning {
2971 nethsm_user: "operator".parse()?,
2972 key_id: "key1".parse()?,
2973 nethsm_key_setup: SigningKeySetup::new(
2974 "Curve25519".parse()?,
2975 vec!["EdDsaSignature".parse()?],
2976 None,
2977 "EdDsa".parse()?,
2978 CryptographicKeyContext::OpenPgp{
2979 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
2980 version: "v4".parse()?,
2981 },
2982 )?,
2983 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
2984 system_user: "system-operator".parse()?,
2985 tag: "tag1".to_string(),
2986 },
2987 Vec::new(),
2988 )]
2989 #[case::namespace_operator(
2990 UserMapping::SystemNetHsmOperatorSigning {
2991 nethsm_user: "ns1~operator".parse()?,
2992 key_id: "key1".parse()?,
2993 nethsm_key_setup: SigningKeySetup::new(
2994 "Curve25519".parse()?,
2995 vec!["EdDsaSignature".parse()?],
2996 None,
2997 "EdDsa".parse()?,
2998 CryptographicKeyContext::OpenPgp{
2999 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3000 version: "v4".parse()?,
3001 },
3002 )?,
3003 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3004 system_user: "system-operator".parse()?,
3005 tag: "tag1".to_string(),
3006 },
3007 vec!["ns1".parse()?],
3008 )]
3009 #[case::hermetic_system_metrics_filter_all(
3010 UserMapping::HermeticSystemNetHsmMetrics {
3011 nethsm_users: NetHsmMetricsUsers::new(
3012 "metrics".parse()?,
3013 vec!["operator".parse()?],
3014 )?,
3015 system_user: "system-metrics".parse()?,
3016 },
3017 Vec::new(),
3018 )]
3019 fn user_mapping_get_nethsm_namespaces(
3020 #[case] mapping: UserMapping,
3021 #[case] output: Vec<NamespaceId>,
3022 ) -> TestResult {
3023 assert_eq!(mapping.get_nethsm_namespaces(), output);
3024 Ok(())
3025 }
3026
3027 #[rstest]
3030 #[case::system_wide_admin(UserMapping::NetHsmOnlyAdmin("test".parse()?), false)]
3031 #[case::namespace_admin(UserMapping::NetHsmOnlyAdmin("ns1~test".parse()?), false)]
3032 #[case::metrics(
3033 UserMapping::SystemNetHsmMetrics {
3034 nethsm_users: NetHsmMetricsUsers::new(
3035 SystemWideUserId::new("metrics".to_string())?,
3036 vec![
3037 UserId::new("operator".to_string())?,
3038 ],
3039 )?,
3040 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3041 system_user: "system-metrics".parse()?,
3042 },
3043 true,
3044 )]
3045 #[case::backup(
3046 UserMapping::SystemNetHsmBackup {
3047 nethsm_user: "backup".parse()?,
3048 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3049 system_user: "system-backup".parse()?,
3050 },
3051 true,
3052 )]
3053 #[case::system_wide_operator(
3054 UserMapping::SystemNetHsmOperatorSigning {
3055 nethsm_user: "operator".parse()?,
3056 key_id: "key1".parse()?,
3057 nethsm_key_setup: SigningKeySetup::new(
3058 "Curve25519".parse()?,
3059 vec!["EdDsaSignature".parse()?],
3060 None,
3061 "EdDsa".parse()?,
3062 CryptographicKeyContext::OpenPgp{
3063 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3064 version: "v4".parse()?,
3065 },
3066 )?,
3067 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3068 system_user: "system-operator".parse()?,
3069 tag: "tag1".to_string(),
3070 },
3071 true,
3072 )]
3073 #[case::namespace_operator(
3074 UserMapping::SystemNetHsmOperatorSigning {
3075 nethsm_user: "ns1~operator".parse()?,
3076 key_id: "key1".parse()?,
3077 nethsm_key_setup: SigningKeySetup::new(
3078 "Curve25519".parse()?,
3079 vec!["EdDsaSignature".parse()?],
3080 None,
3081 "EdDsa".parse()?,
3082 CryptographicKeyContext::OpenPgp{
3083 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3084 version: "v4".parse()?,
3085 },
3086 )?,
3087 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3088 system_user: "system-operator".parse()?,
3089 tag: "tag1".to_string(),
3090 },
3091 true,
3092 )]
3093 #[case::hermetic_system_metrics_filter_all(
3094 UserMapping::HermeticSystemNetHsmMetrics {
3095 nethsm_users: NetHsmMetricsUsers::new(
3096 "metrics".parse()?,
3097 vec!["operator".parse()?],
3098 )?,
3099 system_user: "system-metrics".parse()?,
3100 },
3101 true,
3102 )]
3103 fn user_mapping_has_system_and_backend_user(
3104 #[case] mapping: UserMapping,
3105 #[case] output: bool,
3106 ) -> TestResult {
3107 assert_eq!(mapping.has_system_and_backend_user(), output);
3108 Ok(())
3109 }
3110 }
3111
3112 mod system {
3113 use super::*;
3114
3115 #[rstest]
3118 #[case::share_download(
3119 UserMapping::SystemOnlyShareDownload {
3120 system_user: "system-share".parse()?,
3121 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3122 },
3123 Some("system-share".parse()?),
3124 )]
3125 #[case::share_upload(
3126 UserMapping::SystemOnlyShareUpload {
3127 system_user: "system-share".parse()?,
3128 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3129 },
3130 Some("system-share".parse()?),
3131 )]
3132 #[case::wireguard_download(
3133 UserMapping::SystemOnlyWireGuardDownload {
3134 system_user: "system-wireguard".parse()?,
3135 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3136 },
3137 Some("system-wireguard".parse()?),
3138 )]
3139 fn user_mapping_get_system_user(
3140 #[case] mapping: UserMapping,
3141 #[case] result: Option<SystemUserId>,
3142 ) -> TestResult {
3143 assert_eq!(mapping.get_system_user(), result.as_ref());
3144 Ok(())
3145 }
3146
3147 #[rstest]
3150 #[case::share_download_filter_default(
3151 UserMapping::SystemOnlyShareDownload {
3152 system_user: "system-share".parse()?,
3153 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3154 },
3155 UserMappingFilter::default(),
3156 )]
3157 #[case::share_download_filter_admin(
3158 UserMapping::SystemOnlyShareDownload {
3159 system_user: "system-share".parse()?,
3160 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3161 },
3162 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3163 )]
3164 #[case::share_upload_filter_default(
3165 UserMapping::SystemOnlyShareUpload {
3166 system_user: "system-share".parse()?,
3167 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3168 },
3169 UserMappingFilter::default(),
3170 )]
3171 #[case::share_upload_filter_admin(
3172 UserMapping::SystemOnlyShareUpload {
3173 system_user: "system-share".parse()?,
3174 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3175 },
3176 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3177 )]
3178 #[case::wireguard_download_filter_default(
3179 UserMapping::SystemOnlyWireGuardDownload {
3180 system_user: "system-wireguard".parse()?,
3181 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3182 },
3183 UserMappingFilter::default(),
3184 )]
3185 #[case::wireguard_download_filter_admin(
3186 UserMapping::SystemOnlyWireGuardDownload {
3187 system_user: "system-wireguard".parse()?,
3188 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3189 },
3190 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3191 )]
3192 fn user_mapping_backend_users(
3193 #[case] mapping: UserMapping,
3194 #[case] filter: UserMappingFilter,
3195 ) -> TestResult {
3196 assert_eq!(mapping.backend_users(filter).len(), 0);
3197 Ok(())
3198 }
3199
3200 #[rstest]
3203 #[case::share_download_filter_default(
3204 UserMapping::SystemOnlyShareDownload {
3205 system_user: "system-share".parse()?,
3206 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3207 },
3208 UserMappingFilter::default(),
3209 )]
3210 #[case::share_download_filter_admin(
3211 UserMapping::SystemOnlyShareDownload {
3212 system_user: "system-share".parse()?,
3213 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3214 },
3215 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3216 )]
3217 #[case::share_upload_filter_default(
3218 UserMapping::SystemOnlyShareUpload {
3219 system_user: "system-share".parse()?,
3220 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3221 },
3222 UserMappingFilter::default(),
3223 )]
3224 #[case::share_upload_filter_admin(
3225 UserMapping::SystemOnlyShareUpload {
3226 system_user: "system-share".parse()?,
3227 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3228 },
3229 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3230 )]
3231 #[case::wireguard_download_filter_default(
3232 UserMapping::SystemOnlyWireGuardDownload {
3233 system_user: "system-wireguard".parse()?,
3234 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3235 },
3236 UserMappingFilter::default(),
3237 )]
3238 #[case::wireguard_download_filter_admin(
3239 UserMapping::SystemOnlyWireGuardDownload {
3240 system_user: "system-wireguard".parse()?,
3241 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3242 },
3243 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3244 )]
3245 fn user_mapping_backend_users_with_new_passphrase(
3246 #[case] mapping: UserMapping,
3247 #[case] filter: UserMappingFilter,
3248 ) -> TestResult {
3249 assert!(mapping.backend_users_with_new_passphrase(filter).is_empty());
3250 Ok(())
3251 }
3252
3253 #[rstest]
3256 #[case::share_download(
3257 UserMapping::SystemOnlyShareDownload {
3258 system_user: "system-share".parse()?,
3259 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3260 },
3261 Vec::new(),
3262 )]
3263 #[case::share_upload(
3264 UserMapping::SystemOnlyShareUpload {
3265 system_user: "system-share".parse()?,
3266 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3267 },
3268 Vec::new(),
3269 )]
3270 #[case::wireguard_download(
3271 UserMapping::SystemOnlyWireGuardDownload {
3272 system_user: "system-wireguard".parse()?,
3273 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3274 },
3275 Vec::new(),
3276 )]
3277 fn user_mapping_get_nethsm_users(
3278 #[case] mapping: UserMapping,
3279 #[case] expected: Vec<UserId>,
3280 ) -> TestResult {
3281 assert_eq!(mapping.get_nethsm_users(), expected);
3282 Ok(())
3283 }
3284
3285 #[rstest]
3288 #[case::share_download(
3289 UserMapping::SystemOnlyShareDownload {
3290 system_user: "system-share".parse()?,
3291 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3292 },
3293 )]
3294 #[case::share_upload(
3295 UserMapping::SystemOnlyShareUpload {
3296 system_user: "system-share".parse()?,
3297 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3298 },
3299 )]
3300 #[case::wireguard_download(
3301 UserMapping::SystemOnlyWireGuardDownload {
3302 system_user: "system-wireguard".parse()?,
3303 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3304 },
3305 )]
3306 fn usermapping_get_nethsm_users_and_roles(#[case] mapping: UserMapping) -> TestResult {
3307 let expected: Vec<(UserId, UserRole)> = Vec::new();
3308 assert_eq!(mapping.get_nethsm_users_and_roles(), expected);
3309 Ok(())
3310 }
3311
3312 #[rstest]
3315 #[case::share_download(
3316 UserMapping::SystemOnlyShareDownload {
3317 system_user: "system-share".parse()?,
3318 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3319 },
3320 FilterUserKeys::All,
3321 )]
3322 #[case::share_upload(
3323 UserMapping::SystemOnlyShareUpload {
3324 system_user: "system-share".parse()?,
3325 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3326 },
3327 FilterUserKeys::All,
3328 )]
3329 #[case::wireguard_download(
3330 UserMapping::SystemOnlyWireGuardDownload {
3331 system_user: "system-wireguard".parse()?,
3332 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3333 },
3334 FilterUserKeys::All,
3335 )]
3336 fn user_mapping_get_nethsm_user_key_and_tag(
3337 #[case] mapping: UserMapping,
3338 #[case] filter: FilterUserKeys,
3339 ) -> TestResult {
3340 let expected: Vec<(UserId, KeyId, SigningKeySetup, String)> = Vec::new();
3341 assert_eq!(mapping.get_nethsm_user_key_and_tag(filter), expected);
3342 Ok(())
3343 }
3344
3345 #[rstest]
3348 #[case::share_download(
3349 UserMapping::SystemOnlyShareDownload {
3350 system_user: "system-share".parse()?,
3351 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3352 },
3353 )]
3354 #[case::share_upload(
3355 UserMapping::SystemOnlyShareUpload {
3356 system_user: "system-share".parse()?,
3357 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3358 },
3359 )]
3360 #[case::wireguard_download(
3361 UserMapping::SystemOnlyWireGuardDownload {
3362 system_user: "system-wireguard".parse()?,
3363 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3364 },
3365 )]
3366 fn user_mapping_get_nethsm_user_role_and_tags(#[case] mapping: UserMapping) -> TestResult {
3367 let expected: Vec<(UserId, UserRole, Vec<String>)> = Vec::new();
3368 assert_eq!(mapping.get_nethsm_user_role_and_tags(), expected);
3369 Ok(())
3370 }
3371
3372 #[rstest]
3375 #[case::share_download(
3376 UserMapping::SystemOnlyShareDownload {
3377 system_user: "system-share".parse()?,
3378 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3379 },
3380 )]
3381 #[case::share_upload(
3382 UserMapping::SystemOnlyShareUpload {
3383 system_user: "system-share".parse()?,
3384 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3385 },
3386 )]
3387 #[case::wireguard_download(
3388 UserMapping::SystemOnlyWireGuardDownload {
3389 system_user: "system-wireguard".parse()?,
3390 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3391 },
3392 )]
3393 fn user_mapping_get_ssh_authorized_key(#[case] mapping: UserMapping) -> TestResult {
3394 let expected: Option<AuthorizedKeyEntry> = Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?);
3395 assert_eq!(mapping.get_ssh_authorized_key(), expected.as_ref());
3396 Ok(())
3397 }
3398
3399 #[rstest]
3402 #[case::share_download_target_system_wide(
3403 UserMapping::SystemOnlyShareDownload {
3404 system_user: "system-share".parse()?,
3405 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3406 },
3407 None,
3408 )]
3409 #[case::share_download_target_namespace(
3410 UserMapping::SystemOnlyShareDownload {
3411 system_user: "system-share".parse()?,
3412 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3413 },
3414 Some("ns1".parse()?),
3415 )]
3416 #[case::share_upload_target_system_wide(
3417 UserMapping::SystemOnlyShareUpload {
3418 system_user: "system-share".parse()?,
3419 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3420 },
3421 None,
3422 )]
3423 #[case::share_upload_target_namespace(
3424 UserMapping::SystemOnlyShareUpload {
3425 system_user: "system-share".parse()?,
3426 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3427 },
3428 Some("ns1".parse()?),
3429 )]
3430 #[case::wireguard_download_target_system_wide(
3431 UserMapping::SystemOnlyWireGuardDownload {
3432 system_user: "system-wireguard".parse()?,
3433 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3434 },
3435 None,
3436 )]
3437 #[case::wireguard_download_target_namespace(
3438 UserMapping::SystemOnlyWireGuardDownload {
3439 system_user: "system-wireguard".parse()?,
3440 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3441 },
3442 Some("ns1".parse()?),
3443 )]
3444 fn user_mapping_get_nethsm_key_ids(
3445 #[case] mapping: UserMapping,
3446 #[case] namespace: Option<NamespaceId>,
3447 ) -> TestResult {
3448 let expected: Vec<KeyId> = Vec::new();
3449 assert_eq!(mapping.get_nethsm_key_ids(namespace.as_ref()), expected);
3450 Ok(())
3451 }
3452
3453 #[rstest]
3456 #[case::share_download_target_system_wide(
3457 UserMapping::SystemOnlyShareDownload {
3458 system_user: "system-share".parse()?,
3459 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3460 },
3461 None,
3462 )]
3463 #[case::share_download_target_namespace(
3464 UserMapping::SystemOnlyShareDownload {
3465 system_user: "system-share".parse()?,
3466 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3467 },
3468 Some("ns1".parse()?),
3469 )]
3470 #[case::share_upload_target_system_wide(
3471 UserMapping::SystemOnlyShareUpload {
3472 system_user: "system-share".parse()?,
3473 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3474 },
3475 None,
3476 )]
3477 #[case::share_upload_target_namespace(
3478 UserMapping::SystemOnlyShareUpload {
3479 system_user: "system-share".parse()?,
3480 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3481 },
3482 Some("ns1".parse()?),
3483 )]
3484 #[case::wireguard_download_target_system_wide(
3485 UserMapping::SystemOnlyWireGuardDownload {
3486 system_user: "system-wireguard".parse()?,
3487 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3488 },
3489 None,
3490 )]
3491 #[case::wireguard_download_target_namespace(
3492 UserMapping::SystemOnlyWireGuardDownload {
3493 system_user: "system-wireguard".parse()?,
3494 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3495 },
3496 Some("ns1".parse()?),
3497 )]
3498 fn user_mapping_get_nethsm_tags(
3499 #[case] mapping: UserMapping,
3500 #[case] namespace: Option<NamespaceId>,
3501 ) -> TestResult {
3502 let expected: Vec<&str> = Vec::new();
3503 assert_eq!(mapping.get_nethsm_tags(namespace.as_ref()), expected);
3504 Ok(())
3505 }
3506
3507 #[rstest]
3510 #[case::share_download(
3511 UserMapping::SystemOnlyShareDownload {
3512 system_user: "system-share".parse()?,
3513 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3514 },
3515 Vec::new(),
3516 )]
3517 #[case::share_upload(
3518 UserMapping::SystemOnlyShareUpload {
3519 system_user: "system-share".parse()?,
3520 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3521 },
3522 Vec::new(),
3523 )]
3524 #[case::wireguard_download(
3525 UserMapping::SystemOnlyWireGuardDownload {
3526 system_user: "system-wireguard".parse()?,
3527 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3528 },
3529 Vec::new(),
3530 )]
3531 fn user_mapping_get_nethsm_namespaces(
3532 #[case] mapping: UserMapping,
3533 #[case] output: Vec<NamespaceId>,
3534 ) -> TestResult {
3535 assert_eq!(mapping.get_nethsm_namespaces(), output);
3536 Ok(())
3537 }
3538
3539 #[rstest]
3542 #[case::share_download(
3543 UserMapping::SystemOnlyShareDownload {
3544 system_user: "system-share".parse()?,
3545 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3546 },
3547 false,
3548 )]
3549 #[case::share_upload(
3550 UserMapping::SystemOnlyShareUpload {
3551 system_user: "system-share".parse()?,
3552 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3553 },
3554 false,
3555 )]
3556 #[case::wireguard_download(
3557 UserMapping::SystemOnlyWireGuardDownload {
3558 system_user: "system-wireguard".parse()?,
3559 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3560 },
3561 false,
3562 )]
3563 fn user_mapping_has_system_and_backend_user(
3564 #[case] mapping: UserMapping,
3565 #[case] output: bool,
3566 ) -> TestResult {
3567 assert_eq!(mapping.has_system_and_backend_user(), output);
3568 Ok(())
3569 }
3570 }
3571
3572 #[cfg(feature = "yubihsm2")]
3573 mod yubihsm {
3574 use super::*;
3575
3576 #[rstest]
3579 #[case::admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), None)]
3580 #[case::backup(
3581 UserMapping::SystemYubiHsm2Backup{
3582 authentication_key_id: "1".parse()?,
3583 wrapping_key_id: "2".parse()?,
3584 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3585 system_user: "backup".parse()?,
3586 },
3587 Some("backup".parse()?),
3588 )]
3589 #[case::metrics(
3590 UserMapping::SystemYubiHsm2Metrics {
3591 authentication_key_id: "1".parse()?,
3592 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3593 system_user: "metrics".parse()?,
3594 },
3595 Some("metrics".parse()?),
3596 )]
3597 #[case::hermetic_metrics(
3598 UserMapping::HermeticSystemYubiHsm2Metrics {
3599 authentication_key_id: "1".parse()?,
3600 system_user: "metrics".parse()?,
3601 },
3602 Some("metrics".parse()?),
3603 )]
3604 #[case::operator_signing(
3605 UserMapping::SystemYubiHsm2OperatorSigning {
3606 authentication_key_id: "1".parse()?,
3607 backend_key_setup: SigningKeySetup::new(
3608 "Curve25519".parse()?,
3609 vec!["EdDsaSignature".parse()?],
3610 None,
3611 "EdDsa".parse()?,
3612 CryptographicKeyContext::OpenPgp{
3613 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3614 version: "v4".parse()?,
3615 },
3616 )?,
3617 backend_key_id: "1".parse()?,
3618 backend_key_domain: 1,
3619 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3620 system_user: "system-operator".parse()?,
3621 },
3622 Some("system-operator".parse()?),
3623 )]
3624 fn user_mapping_get_system_user(
3625 #[case] mapping: UserMapping,
3626 #[case] result: Option<SystemUserId>,
3627 ) -> TestResult {
3628 assert_eq!(mapping.get_system_user(), result.as_ref());
3629 Ok(())
3630 }
3631
3632 #[rstest]
3635 #[case::admin_filter_default(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), UserMappingFilter::default(), &[])]
3636 #[case::admin_filter_admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), UserMappingFilter{backend_user_kind: BackendUserKind::Admin}, &["1"])]
3637 #[case::backup_filter_default(
3638 UserMapping::SystemYubiHsm2Backup{
3639 authentication_key_id: "1".parse()?,
3640 wrapping_key_id: "2".parse()?,
3641 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3642 system_user: "backup".parse()?,
3643 },
3644 UserMappingFilter::default(),
3645 &["1"]
3646 )]
3647 #[case::backup_filter_admin(
3648 UserMapping::SystemYubiHsm2Backup{
3649 authentication_key_id: "1".parse()?,
3650 wrapping_key_id: "2".parse()?,
3651 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3652 system_user: "backup".parse()?,
3653 },
3654 UserMappingFilter{ backend_user_kind: BackendUserKind::Admin },
3655 &[]
3656 )]
3657 #[case::metrics_filter_default(
3658 UserMapping::SystemYubiHsm2Metrics {
3659 authentication_key_id: "1".parse()?,
3660 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3661 system_user: "metrics".parse()?,
3662 },
3663 UserMappingFilter::default(),
3664 &["1"]
3665 )]
3666 #[case::metrics_filter_admin(
3667 UserMapping::SystemYubiHsm2Metrics {
3668 authentication_key_id: "1".parse()?,
3669 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3670 system_user: "metrics".parse()?,
3671 },
3672 UserMappingFilter{ backend_user_kind: BackendUserKind::Admin },
3673 &[]
3674 )]
3675 #[case::hermetic_metrics_filter_default(
3676 UserMapping::HermeticSystemYubiHsm2Metrics {
3677 authentication_key_id: "1".parse()?,
3678 system_user: "metrics".parse()?,
3679 },
3680 UserMappingFilter::default(),
3681 &["1"]
3682 )]
3683 #[case::hermetic_metrics_filter_admin(
3684 UserMapping::HermeticSystemYubiHsm2Metrics {
3685 authentication_key_id: "1".parse()?,
3686 system_user: "metrics".parse()?,
3687 },
3688 UserMappingFilter{ backend_user_kind: BackendUserKind::Admin },
3689 &[]
3690 )]
3691 #[case::operator_filter_default(
3692 UserMapping::SystemYubiHsm2OperatorSigning {
3693 backend_key_id: "1".parse()?,
3694 backend_key_setup: SigningKeySetup::new(
3695 "Curve25519".parse()?,
3696 vec!["EdDsaSignature".parse()?],
3697 None,
3698 "EdDsa".parse()?,
3699 CryptographicKeyContext::OpenPgp{
3700 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3701 version: "v4".parse()?,
3702 },
3703 )?,
3704 authentication_key_id: "1".parse()?,
3705 backend_key_domain: 1,
3706 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3707 system_user: "system-operator".parse()?,
3708 },
3709 UserMappingFilter::default(),
3710 &["1"]
3711 )]
3712 #[case::operator_filter_admin(
3713 UserMapping::SystemYubiHsm2OperatorSigning {
3714 backend_key_id: "1".parse()?,
3715 backend_key_setup: SigningKeySetup::new(
3716 "Curve25519".parse()?,
3717 vec!["EdDsaSignature".parse()?],
3718 None,
3719 "EdDsa".parse()?,
3720 CryptographicKeyContext::OpenPgp{
3721 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3722 version: "v4".parse()?,
3723 },
3724 )?,
3725 authentication_key_id: "1".parse()?,
3726 backend_key_domain: 1,
3727 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3728 system_user: "system-operator".parse()?,
3729 },
3730 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3731 &[]
3732 )]
3733 fn user_mapping_backend_users(
3734 #[case] mapping: UserMapping,
3735 #[case] filter: UserMappingFilter,
3736 #[case] expected_names: &[&str],
3737 ) -> TestResult {
3738 assert_eq!(mapping.backend_users(filter), expected_names);
3739 Ok(())
3740 }
3741
3742 #[rstest]
3745 #[case::admin_filter_default(
3746 UserMapping::YubiHsm2OnlyAdmin("1".parse()?),
3747 UserMappingFilter::default(),
3748 0
3749 )]
3750 #[case::admin_filter_admin(
3751 UserMapping::YubiHsm2OnlyAdmin("1".parse()?),
3752 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3753 1
3754 )]
3755 #[case::backup_filter_default(
3756 UserMapping::SystemYubiHsm2Backup{
3757 authentication_key_id: "1".parse()?,
3758 wrapping_key_id: "2".parse()?,
3759 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3760 system_user: "backup".parse()?,
3761 },
3762 UserMappingFilter::default(),
3763 1
3764 )]
3765 #[case::backup_filter_admin(
3766 UserMapping::SystemYubiHsm2Backup{
3767 authentication_key_id: "1".parse()?,
3768 wrapping_key_id: "2".parse()?,
3769 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3770 system_user: "backup".parse()?,
3771 },
3772 UserMappingFilter{ backend_user_kind: BackendUserKind::Admin },
3773 0
3774 )]
3775 #[case::metrics_filter_default(
3776 UserMapping::SystemYubiHsm2Metrics {
3777 authentication_key_id: "1".parse()?,
3778 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3779 system_user: "metrics".parse()?,
3780 },
3781 UserMappingFilter::default(),
3782 1
3783 )]
3784 #[case::metrics_filter_admin(
3785 UserMapping::SystemYubiHsm2Metrics {
3786 authentication_key_id: "1".parse()?,
3787 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3788 system_user: "metrics".parse()?,
3789 },
3790 UserMappingFilter{ backend_user_kind: BackendUserKind::Admin },
3791 0
3792 )]
3793 #[case::hermetic_metrics_filter_default(
3794 UserMapping::HermeticSystemYubiHsm2Metrics {
3795 authentication_key_id: "1".parse()?,
3796 system_user: "metrics".parse()?,
3797 },
3798 UserMappingFilter::default(),
3799 1
3800 )]
3801 #[case::hermetic_metrics_filter_admin(
3802 UserMapping::HermeticSystemYubiHsm2Metrics {
3803 authentication_key_id: "1".parse()?,
3804 system_user: "metrics".parse()?,
3805 },
3806 UserMappingFilter{ backend_user_kind: BackendUserKind::Admin },
3807 0
3808 )]
3809 #[case::operator_filter_default(
3810 UserMapping::SystemYubiHsm2OperatorSigning {
3811 backend_key_id: "1".parse()?,
3812 backend_key_setup: SigningKeySetup::new(
3813 "Curve25519".parse()?,
3814 vec!["EdDsaSignature".parse()?],
3815 None,
3816 "EdDsa".parse()?,
3817 CryptographicKeyContext::OpenPgp{
3818 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3819 version: "v4".parse()?,
3820 },
3821 )?,
3822 authentication_key_id: "1".parse()?,
3823 backend_key_domain: 1,
3824 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3825 system_user: "system-operator".parse()?,
3826 },
3827 UserMappingFilter::default(),
3828 1
3829 )]
3830 #[case::operator_filter_admin(
3831 UserMapping::SystemYubiHsm2OperatorSigning {
3832 backend_key_id: "1".parse()?,
3833 backend_key_setup: SigningKeySetup::new(
3834 "Curve25519".parse()?,
3835 vec!["EdDsaSignature".parse()?],
3836 None,
3837 "EdDsa".parse()?,
3838 CryptographicKeyContext::OpenPgp{
3839 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3840 version: "v4".parse()?,
3841 },
3842 )?,
3843 authentication_key_id: "1".parse()?,
3844 backend_key_domain: 1,
3845 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3846 system_user: "system-operator".parse()?,
3847 },
3848 UserMappingFilter{backend_user_kind: BackendUserKind::Admin},
3849 0
3850 )]
3851 fn usermapping_yubihsm_backend_users_with_new_passphrase(
3852 #[case] mapping: UserMapping,
3853 #[case] filter: UserMappingFilter,
3854 #[case] expected_length: usize,
3855 ) -> TestResult {
3856 assert_eq!(
3857 mapping.backend_users_with_new_passphrase(filter).len(),
3858 expected_length
3859 );
3860 Ok(())
3861 }
3862
3863 #[rstest]
3866 #[case::admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?))]
3867 #[case::backup(
3868 UserMapping::SystemYubiHsm2Backup{
3869 authentication_key_id: "1".parse()?,
3870 wrapping_key_id: "2".parse()?,
3871 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3872 system_user: "backup".parse()?,
3873 }
3874 )]
3875 #[case::metrics(
3876 UserMapping::SystemYubiHsm2Metrics {
3877 authentication_key_id: "1".parse()?,
3878 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3879 system_user: "metrics".parse()?,
3880 },
3881 )]
3882 #[case::hermetic_metrics(
3883 UserMapping::HermeticSystemYubiHsm2Metrics {
3884 authentication_key_id: "1".parse()?,
3885 system_user: "metrics".parse()?,
3886 },
3887 )]
3888 #[case::operator_signing(
3889 UserMapping::SystemYubiHsm2OperatorSigning {
3890 authentication_key_id: "1".parse()?,
3891 backend_key_setup: SigningKeySetup::new(
3892 "Curve25519".parse()?,
3893 vec!["EdDsaSignature".parse()?],
3894 None,
3895 "EdDsa".parse()?,
3896 CryptographicKeyContext::OpenPgp{
3897 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3898 version: "v4".parse()?,
3899 },
3900 )?,
3901 backend_key_id: "1".parse()?,
3902 backend_key_domain: 1,
3903 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3904 system_user: "system-operator".parse()?,
3905 },
3906 )]
3907 fn user_mapping_get_nethsm_users(#[case] mapping: UserMapping) -> TestResult {
3908 let expected: Vec<UserId> = Vec::new();
3909 assert_eq!(mapping.get_nethsm_users(), expected);
3910 Ok(())
3911 }
3912
3913 #[rstest]
3916 #[case::admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?))]
3917 #[case::backup(
3918 UserMapping::SystemYubiHsm2Backup{
3919 authentication_key_id: "1".parse()?,
3920 wrapping_key_id: "2".parse()?,
3921 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3922 system_user: "backup".parse()?,
3923 }
3924 )]
3925 #[case::metrics(
3926 UserMapping::SystemYubiHsm2Metrics {
3927 authentication_key_id: "1".parse()?,
3928 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3929 system_user: "metrics".parse()?,
3930 },
3931 )]
3932 #[case::hermetic_metrics(
3933 UserMapping::HermeticSystemYubiHsm2Metrics {
3934 authentication_key_id: "1".parse()?,
3935 system_user: "metrics".parse()?,
3936 },
3937 )]
3938 #[case::operator_signing(
3939 UserMapping::SystemYubiHsm2OperatorSigning {
3940 authentication_key_id: "1".parse()?,
3941 backend_key_setup: SigningKeySetup::new(
3942 "Curve25519".parse()?,
3943 vec!["EdDsaSignature".parse()?],
3944 None,
3945 "EdDsa".parse()?,
3946 CryptographicKeyContext::OpenPgp{
3947 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
3948 version: "v4".parse()?,
3949 },
3950 )?,
3951 backend_key_id: "1".parse()?,
3952 backend_key_domain: 1,
3953 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3954 system_user: "system-operator".parse()?,
3955 },
3956 )]
3957 fn usermapping_get_nethsm_users_and_roles(#[case] mapping: UserMapping) -> TestResult {
3958 let expected: Vec<(UserId, UserRole)> = Vec::new();
3959 assert_eq!(mapping.get_nethsm_users_and_roles(), expected);
3960 Ok(())
3961 }
3962
3963 #[rstest]
3966 #[case::admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), FilterUserKeys::All)]
3967 #[case::backup(
3968 UserMapping::SystemYubiHsm2Backup{
3969 authentication_key_id: "1".parse()?,
3970 wrapping_key_id: "2".parse()?,
3971 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3972 system_user: "backup".parse()?,
3973 },
3974 FilterUserKeys::All,
3975 )]
3976 #[case::metrics(
3977 UserMapping::SystemYubiHsm2Metrics {
3978 authentication_key_id: "1".parse()?,
3979 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
3980 system_user: "metrics".parse()?,
3981 },
3982 FilterUserKeys::All,
3983 )]
3984 #[case::hermetic_metrics(
3985 UserMapping::HermeticSystemYubiHsm2Metrics {
3986 authentication_key_id: "1".parse()?,
3987 system_user: "metrics".parse()?,
3988 },
3989 FilterUserKeys::All,
3990 )]
3991 #[case::operator_signing(
3992 UserMapping::SystemYubiHsm2OperatorSigning {
3993 authentication_key_id: "1".parse()?,
3994 backend_key_setup: SigningKeySetup::new(
3995 "Curve25519".parse()?,
3996 vec!["EdDsaSignature".parse()?],
3997 None,
3998 "EdDsa".parse()?,
3999 CryptographicKeyContext::OpenPgp{
4000 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4001 version: "v4".parse()?,
4002 },
4003 )?,
4004 backend_key_id: "1".parse()?,
4005 backend_key_domain: 1,
4006 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4007 system_user: "system-operator".parse()?,
4008 },
4009 FilterUserKeys::All,
4010 )]
4011 fn user_mapping_get_nethsm_user_key_and_tag(
4012 #[case] mapping: UserMapping,
4013 #[case] filter: FilterUserKeys,
4014 ) -> TestResult {
4015 let expected: Vec<(UserId, KeyId, SigningKeySetup, String)> = Vec::new();
4016 assert_eq!(mapping.get_nethsm_user_key_and_tag(filter), expected);
4017 Ok(())
4018 }
4019
4020 #[rstest]
4023 #[case::admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?))]
4024 #[case::backup(
4025 UserMapping::SystemYubiHsm2Backup{
4026 authentication_key_id: "1".parse()?,
4027 wrapping_key_id: "2".parse()?,
4028 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4029 system_user: "backup".parse()?,
4030 }
4031 )]
4032 #[case::metrics(
4033 UserMapping::SystemYubiHsm2Metrics {
4034 authentication_key_id: "1".parse()?,
4035 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4036 system_user: "metrics".parse()?,
4037 },
4038 )]
4039 #[case::hermetic_metrics(
4040 UserMapping::HermeticSystemYubiHsm2Metrics {
4041 authentication_key_id: "1".parse()?,
4042 system_user: "metrics".parse()?,
4043 },
4044 )]
4045 #[case::operator_signing(
4046 UserMapping::SystemYubiHsm2OperatorSigning {
4047 authentication_key_id: "1".parse()?,
4048 backend_key_setup: SigningKeySetup::new(
4049 "Curve25519".parse()?,
4050 vec!["EdDsaSignature".parse()?],
4051 None,
4052 "EdDsa".parse()?,
4053 CryptographicKeyContext::OpenPgp{
4054 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4055 version: "v4".parse()?,
4056 },
4057 )?,
4058 backend_key_id: "1".parse()?,
4059 backend_key_domain: 1,
4060 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4061 system_user: "system-operator".parse()?,
4062 },
4063 )]
4064 fn user_mapping_get_nethsm_user_role_and_tags(#[case] mapping: UserMapping) -> TestResult {
4065 let expected: Vec<(UserId, UserRole, Vec<String>)> = Vec::new();
4066 assert_eq!(mapping.get_nethsm_user_role_and_tags(), expected);
4067 Ok(())
4068 }
4069
4070 #[rstest]
4073 #[case::admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), None)]
4074 #[case::backup(
4075 UserMapping::SystemYubiHsm2Backup{
4076 authentication_key_id: "1".parse()?,
4077 wrapping_key_id: "2".parse()?,
4078 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4079 system_user: "backup".parse()?,
4080 },
4081 Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?),
4082 )]
4083 #[case::metrics(
4084 UserMapping::SystemYubiHsm2Metrics {
4085 authentication_key_id: "1".parse()?,
4086 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4087 system_user: "metrics".parse()?,
4088 },
4089 Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?),
4090 )]
4091 #[case::hermetic_metrics(
4092 UserMapping::HermeticSystemYubiHsm2Metrics {
4093 authentication_key_id: "1".parse()?,
4094 system_user: "metrics".parse()?,
4095 },
4096 None,
4097 )]
4098 #[case::operator_signing(
4099 UserMapping::SystemYubiHsm2OperatorSigning {
4100 authentication_key_id: "1".parse()?,
4101 backend_key_setup: SigningKeySetup::new(
4102 "Curve25519".parse()?,
4103 vec!["EdDsaSignature".parse()?],
4104 None,
4105 "EdDsa".parse()?,
4106 CryptographicKeyContext::OpenPgp{
4107 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4108 version: "v4".parse()?,
4109 },
4110 )?,
4111 backend_key_id: "1".parse()?,
4112 backend_key_domain: 1,
4113 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4114 system_user: "system-operator".parse()?,
4115 },
4116 Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?),
4117 )]
4118 fn user_mapping_get_ssh_authorized_key(
4119 #[case] mapping: UserMapping,
4120 #[case] output: Option<AuthorizedKeyEntry>,
4121 ) -> TestResult {
4122 assert_eq!(mapping.get_ssh_authorized_key(), output.as_ref());
4123 Ok(())
4124 }
4125
4126 #[rstest]
4129 #[case::admin_target_system_wide(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), None)]
4130 #[case::admin_target_namespace(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), Some("ns1".parse()?))]
4131 #[case::backup_target_system_wide(
4132 UserMapping::SystemYubiHsm2Backup{
4133 authentication_key_id: "1".parse()?,
4134 wrapping_key_id: "2".parse()?,
4135 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4136 system_user: "backup".parse()?,
4137 },
4138 None,
4139 )]
4140 #[case::backup_target_namespace(
4141 UserMapping::SystemYubiHsm2Backup{
4142 authentication_key_id: "1".parse()?,
4143 wrapping_key_id: "2".parse()?,
4144 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4145 system_user: "backup".parse()?,
4146 },
4147 Some("ns1".parse()?),
4148 )]
4149 #[case::metrics_target_system_wide(
4150 UserMapping::SystemYubiHsm2Metrics {
4151 authentication_key_id: "1".parse()?,
4152 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4153 system_user: "metrics".parse()?,
4154 },
4155 None,
4156 )]
4157 #[case::metrics_target_namespace(
4158 UserMapping::SystemYubiHsm2Metrics {
4159 authentication_key_id: "1".parse()?,
4160 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4161 system_user: "metrics".parse()?,
4162 },
4163 Some("ns1".parse()?),
4164 )]
4165 #[case::hermetic_metrics_target_system_wide(
4166 UserMapping::HermeticSystemYubiHsm2Metrics {
4167 authentication_key_id: "1".parse()?,
4168 system_user: "metrics".parse()?,
4169 },
4170 None,
4171 )]
4172 #[case::hermetic_metrics_target_namespace(
4173 UserMapping::HermeticSystemYubiHsm2Metrics {
4174 authentication_key_id: "1".parse()?,
4175 system_user: "metrics".parse()?,
4176 },
4177 Some("ns1".parse()?),
4178 )]
4179 #[case::operator_signing_target_system_wide(
4180 UserMapping::SystemYubiHsm2OperatorSigning {
4181 authentication_key_id: "1".parse()?,
4182 backend_key_setup: SigningKeySetup::new(
4183 "Curve25519".parse()?,
4184 vec!["EdDsaSignature".parse()?],
4185 None,
4186 "EdDsa".parse()?,
4187 CryptographicKeyContext::OpenPgp{
4188 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4189 version: "v4".parse()?,
4190 },
4191 )?,
4192 backend_key_id: "1".parse()?,
4193 backend_key_domain: 1,
4194 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4195 system_user: "system-operator".parse()?,
4196 },
4197 None,
4198 )]
4199 #[case::operator_signing_target_namespace(
4200 UserMapping::SystemYubiHsm2OperatorSigning {
4201 authentication_key_id: "1".parse()?,
4202 backend_key_setup: SigningKeySetup::new(
4203 "Curve25519".parse()?,
4204 vec!["EdDsaSignature".parse()?],
4205 None,
4206 "EdDsa".parse()?,
4207 CryptographicKeyContext::OpenPgp{
4208 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4209 version: "v4".parse()?,
4210 },
4211 )?,
4212 backend_key_id: "1".parse()?,
4213 backend_key_domain: 1,
4214 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4215 system_user: "system-operator".parse()?,
4216 },
4217 Some("ns1".parse()?),
4218 )]
4219 fn user_mapping_get_nethsm_key_ids(
4220 #[case] mapping: UserMapping,
4221 #[case] namespace: Option<NamespaceId>,
4222 ) -> TestResult {
4223 let expected: Vec<KeyId> = Vec::new();
4224 assert_eq!(mapping.get_nethsm_key_ids(namespace.as_ref()), expected);
4225 Ok(())
4226 }
4227
4228 #[rstest]
4231 #[case::admin_target_system_wide(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), None)]
4232 #[case::admin_target_namespace(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), Some("ns1".parse()?))]
4233 #[case::backup_target_system_wide(
4234 UserMapping::SystemYubiHsm2Backup{
4235 authentication_key_id: "1".parse()?,
4236 wrapping_key_id: "2".parse()?,
4237 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4238 system_user: "backup".parse()?,
4239 },
4240 None,
4241 )]
4242 #[case::backup_target_namespace(
4243 UserMapping::SystemYubiHsm2Backup{
4244 authentication_key_id: "1".parse()?,
4245 wrapping_key_id: "2".parse()?,
4246 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4247 system_user: "backup".parse()?,
4248 },
4249 Some("ns1".parse()?),
4250 )]
4251 #[case::metrics_target_system_wide(
4252 UserMapping::SystemYubiHsm2Metrics {
4253 authentication_key_id: "1".parse()?,
4254 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4255 system_user: "metrics".parse()?,
4256 },
4257 None,
4258 )]
4259 #[case::metrics_target_namespace(
4260 UserMapping::SystemYubiHsm2Metrics {
4261 authentication_key_id: "1".parse()?,
4262 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4263 system_user: "metrics".parse()?,
4264 },
4265 Some("ns1".parse()?),
4266 )]
4267 #[case::hermetic_metrics_target_system_wide(
4268 UserMapping::HermeticSystemYubiHsm2Metrics {
4269 authentication_key_id: "1".parse()?,
4270 system_user: "metrics".parse()?,
4271 },
4272 None,
4273 )]
4274 #[case::hermetic_metrics_target_namespace(
4275 UserMapping::HermeticSystemYubiHsm2Metrics {
4276 authentication_key_id: "1".parse()?,
4277 system_user: "metrics".parse()?,
4278 },
4279 Some("ns1".parse()?),
4280 )]
4281 #[case::operator_signing_target_system_wide(
4282 UserMapping::SystemYubiHsm2OperatorSigning {
4283 authentication_key_id: "1".parse()?,
4284 backend_key_setup: SigningKeySetup::new(
4285 "Curve25519".parse()?,
4286 vec!["EdDsaSignature".parse()?],
4287 None,
4288 "EdDsa".parse()?,
4289 CryptographicKeyContext::OpenPgp{
4290 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4291 version: "v4".parse()?,
4292 },
4293 )?,
4294 backend_key_id: "1".parse()?,
4295 backend_key_domain: 1,
4296 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4297 system_user: "system-operator".parse()?,
4298 },
4299 None,
4300 )]
4301 #[case::operator_signing_target_namespace(
4302 UserMapping::SystemYubiHsm2OperatorSigning {
4303 authentication_key_id: "1".parse()?,
4304 backend_key_setup: SigningKeySetup::new(
4305 "Curve25519".parse()?,
4306 vec!["EdDsaSignature".parse()?],
4307 None,
4308 "EdDsa".parse()?,
4309 CryptographicKeyContext::OpenPgp{
4310 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4311 version: "v4".parse()?,
4312 },
4313 )?,
4314 backend_key_id: "1".parse()?,
4315 backend_key_domain: 1,
4316 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4317 system_user: "system-operator".parse()?,
4318 },
4319 Some("ns1".parse()?),
4320 )]
4321 fn user_mapping_get_nethsm_tags(
4322 #[case] mapping: UserMapping,
4323 #[case] namespace: Option<NamespaceId>,
4324 ) -> TestResult {
4325 let expected: Vec<&str> = Vec::new();
4326 assert_eq!(mapping.get_nethsm_tags(namespace.as_ref()), expected);
4327 Ok(())
4328 }
4329
4330 #[rstest]
4333 #[case::admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?))]
4334 #[case::backup(
4335 UserMapping::SystemYubiHsm2Backup{
4336 authentication_key_id: "1".parse()?,
4337 wrapping_key_id: "2".parse()?,
4338 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4339 system_user: "backup".parse()?,
4340 },
4341 )]
4342 #[case::metrics(
4343 UserMapping::SystemYubiHsm2Metrics {
4344 authentication_key_id: "1".parse()?,
4345 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4346 system_user: "metrics".parse()?,
4347 },
4348 )]
4349 #[case::hermetic_metrics(
4350 UserMapping::HermeticSystemYubiHsm2Metrics {
4351 authentication_key_id: "1".parse()?,
4352 system_user: "metrics".parse()?,
4353 },
4354 )]
4355 #[case::operator_signing(
4356 UserMapping::SystemYubiHsm2OperatorSigning {
4357 authentication_key_id: "1".parse()?,
4358 backend_key_setup: SigningKeySetup::new(
4359 "Curve25519".parse()?,
4360 vec!["EdDsaSignature".parse()?],
4361 None,
4362 "EdDsa".parse()?,
4363 CryptographicKeyContext::OpenPgp{
4364 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4365 version: "v4".parse()?,
4366 },
4367 )?,
4368 backend_key_id: "1".parse()?,
4369 backend_key_domain: 1,
4370 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4371 system_user: "system-operator".parse()?,
4372 },
4373 )]
4374 fn user_mapping_get_nethsm_namespaces(#[case] mapping: UserMapping) -> TestResult {
4375 let expected: Vec<NamespaceId> = Vec::new();
4376 assert_eq!(mapping.get_nethsm_namespaces(), expected);
4377 Ok(())
4378 }
4379
4380 #[rstest]
4383 #[case::admin(UserMapping::YubiHsm2OnlyAdmin("1".parse()?), false)]
4384 #[case::backup(
4385 UserMapping::SystemYubiHsm2Backup{
4386 authentication_key_id: "1".parse()?,
4387 wrapping_key_id: "2".parse()?,
4388 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4389 system_user: "backup".parse()?,
4390 },
4391 true
4392 )]
4393 #[case::metrics(
4394 UserMapping::SystemYubiHsm2Metrics {
4395 authentication_key_id: "1".parse()?,
4396 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4397 system_user: "metrics".parse()?,
4398 },
4399 true
4400 )]
4401 #[case::hermetic_metrics(
4402 UserMapping::HermeticSystemYubiHsm2Metrics {
4403 authentication_key_id: "1".parse()?,
4404 system_user: "metrics".parse()?,
4405 },
4406 true
4407 )]
4408 #[case::operator_signing(
4409 UserMapping::SystemYubiHsm2OperatorSigning {
4410 authentication_key_id: "1".parse()?,
4411 backend_key_setup: SigningKeySetup::new(
4412 "Curve25519".parse()?,
4413 vec!["EdDsaSignature".parse()?],
4414 None,
4415 "EdDsa".parse()?,
4416 CryptographicKeyContext::OpenPgp{
4417 user_ids: OpenPgpUserIdList::new(vec!["John Doe <john@example.org>".parse()?])?,
4418 version: "v4".parse()?,
4419 },
4420 )?,
4421 backend_key_id: "1".parse()?,
4422 backend_key_domain: 1,
4423 ssh_authorized_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3NyNfSqtDxdnWwSVzulZi0k7Lyjw3vBEG+U8y6KsuW user@host".parse()?,
4424 system_user: "system-operator".parse()?,
4425 },
4426 true,
4427 )]
4428 fn user_mapping_has_system_and_backend_user(
4429 #[case] mapping: UserMapping,
4430 #[case] output: bool,
4431 ) -> TestResult {
4432 assert_eq!(mapping.has_system_and_backend_user(), output);
4433 Ok(())
4434 }
4435 }
4436
4437 #[test]
4440 fn check_secrets_file_succeeds() -> TestResult {
4441 setup_logging(LevelFilter::Debug)?;
4442
4443 let temp_file = NamedTempFile::new()?;
4444 let path = temp_file.path();
4445 set_permissions(path, Permissions::from_mode(SECRET_FILE_MODE))?;
4446 debug!(
4447 "Created {path:?} with mode {:o}",
4448 path.metadata()?.permissions().mode()
4449 );
4450
4451 check_secrets_file(path)?;
4452
4453 Ok(())
4454 }
4455
4456 #[test]
4458 fn check_secrets_file_fails_on_missing_file() -> TestResult {
4459 setup_logging(LevelFilter::Debug)?;
4460
4461 let temp_file = NamedTempFile::new()?;
4462 let path = temp_file.path().to_path_buf();
4463 temp_file.close()?;
4464
4465 if check_secrets_file(&path).is_ok() {
4466 panic!("The path {path:?} is missing and should not have passed as a secrets file.");
4467 }
4468
4469 Ok(())
4470 }
4471
4472 #[test]
4474 fn check_secrets_file_fails_on_dir() -> TestResult {
4475 setup_logging(LevelFilter::Debug)?;
4476
4477 let temp_file = TempDir::new()?;
4478 let path = temp_file.path();
4479 debug!(
4480 "Created {path:?} with mode {:o}",
4481 path.metadata()?.permissions().mode()
4482 );
4483
4484 if check_secrets_file(path).is_ok() {
4485 panic!("The dir {path:?} should not have passed as a secrets file.");
4486 }
4487
4488 Ok(())
4489 }
4490
4491 #[test]
4493 fn check_secrets_file_fails_on_invalid_permissions() -> TestResult {
4494 setup_logging(LevelFilter::Debug)?;
4495
4496 let temp_file = NamedTempFile::new()?;
4497 let path = temp_file.path();
4498 set_permissions(path, Permissions::from_mode(0o100644))?;
4499 debug!(
4500 "Created {path:?} with mode {:o}",
4501 path.metadata()?.permissions().mode()
4502 );
4503
4504 if check_secrets_file(path).is_ok() {
4505 panic!("The file at {path:?} should not have passed as a secrets file.");
4506 }
4507
4508 Ok(())
4509 }
4510}