From 3878dcddaeff570db68b3828a122ef11a6514b2a Mon Sep 17 00:00:00 2001 From: David Mulder Date: Mon, 9 Dec 2024 09:22:05 -0700 Subject: [PATCH 1/5] Include multi-domain important info in himmelblau.conf man Fixes https://github.com/himmelblau-idm/himmelblau/issues/314 Signed-off-by: David Mulder --- man/man5/himmelblau.conf.5 | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/man/man5/himmelblau.conf.5 b/man/man5/himmelblau.conf.5 index 51021db..ee07efa 100644 --- a/man/man5/himmelblau.conf.5 +++ b/man/man5/himmelblau.conf.5 @@ -51,9 +51,22 @@ A comma-separated list of configured domains. This parameter is .B REQUIRED for successful authentication. If this option is not specified, no users will be permitted to authenticate. The first user to authenticate to each domain will become the owner of the device object in the directory. + +If multiple domains are specified, you +.B MUST +define an +.B idmap_range +for each domain to avoid conflicts in user and group ID mappings. Overlapping ID ranges will cause the idmapper to throw a critical error and stop the daemon. This safeguard ensures that two users are not mistakenly mapped to the same UID. + .EXAMPLES domains = example.com,example2.com +[example.com] +idmap_range = 5000000-5999999 + +[example2.com] +idmap_range = 6000000-6999999 + .TP .B debug .RE @@ -254,6 +267,16 @@ shell = /bin/bash .RE Specifies the range of IDs to be used for the user and group mappings. +When this option is modified, you +.B SHOULD +run: +.RS +.IP +sudo aad-tool cache-clear --really +.RE + +To ensure that old cached ID mappings are cleared, preventing potential UID overlaps caused by stale cache data. + .EXAMPLES idmap_range = 5000000-5999999 @@ -351,6 +374,16 @@ shell = /bin/bash .RE Overrides the `idmap_range` value for this domain. +When this option is modified, you +.B SHOULD +run: +.RS +.IP +sudo aad-tool cache-clear --really +.RE + +To ensure that old cached ID mappings are cleared, preventing potential UID overlaps caused by stale cache data. + .EXAMPLES [example.com] idmap_range = 5000000-5999999 From 13f01ffeb3478a81c3db35541d6ac17bfe6f03e0 Mon Sep 17 00:00:00 2001 From: David Mulder Date: Mon, 9 Dec 2024 11:32:08 -0700 Subject: [PATCH 2/5] Fix config hsm type Tpm error There was a typo in the hsm type parsing. Signed-off-by: David Mulder --- src/common/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/src/config.rs b/src/common/src/config.rs index ddb2bee..341f119 100644 --- a/src/common/src/config.rs +++ b/src/common/src/config.rs @@ -309,7 +309,7 @@ impl HimmelblauConfig { match self.config.get("global", "hsm_type") { Some(val) => match val.to_lowercase().as_str() { "soft" => HsmType::Soft, - "tmp" => HsmType::Tpm, + "tpm" => HsmType::Tpm, _ => { warn!("Invalid hsm_type configured, using default ..."); HsmType::default() From 8344491f09fd32a3ac4d01c2a4c620ce2a687771 Mon Sep 17 00:00:00 2001 From: David Mulder Date: Mon, 9 Dec 2024 11:34:04 -0700 Subject: [PATCH 3/5] Fix incorrect default domain The list of domains was being sorted, mixing up the default domain and causing it to be whichever came first alphabetically. Signed-off-by: David Mulder --- src/common/src/config.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/common/src/config.rs b/src/common/src/config.rs index 341f119..8b7661f 100644 --- a/src/common/src/config.rs +++ b/src/common/src/config.rs @@ -379,9 +379,11 @@ impl HimmelblauConfig { }; let mut sections = self.config.sections(); sections.retain(|s| s != "global"); - domains.extend(sections); - domains.sort(); - domains.dedup(); + for section in sections { + if !domains.contains(§ion) { + domains.push(section); + } + } domains } From 944b8685f8e6bdf5f1bca5457c99a718006a5781 Mon Sep 17 00:00:00 2001 From: David Mulder Date: Mon, 9 Dec 2024 11:35:00 -0700 Subject: [PATCH 4/5] Add config parsing unit tests To prevent mistakes in the configuration in the future, adding unit tests so we are checking that these are handled correctly. Signed-off-by: David Mulder --- src/common/src/config.rs | 672 +++++++++++++++++++++++++++++++++- src/common/src/unix_config.rs | 4 +- 2 files changed, 673 insertions(+), 3 deletions(-) diff --git a/src/common/src/config.rs b/src/common/src/config.rs index 8b7661f..a8eb543 100644 --- a/src/common/src/config.rs +++ b/src/common/src/config.rs @@ -33,7 +33,7 @@ use crate::unix_config::{HomeAttr, HsmType}; use idmap::DEFAULT_IDMAP_RANGE; use std::env; -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub enum IdAttr { Uuid, Name, @@ -489,3 +489,673 @@ impl fmt::Debug for HimmelblauConfig { write!(f, "{:?}", self.config) } } + +#[cfg(test)] +mod tests { + use super::*; + use std::env; + use std::fs; + + // Helper function to create temporary configuration files + fn create_temp_config(contents: &str) -> String { + let file_path = format!("/tmp/himmelblau_test_config_{}.ini", uuid::Uuid::new_v4()); + fs::write(&file_path, contents).expect("Failed to write temporary config file"); + file_path + } + + #[test] + fn test_get_home_prefix() { + let config_data = r#" + [global] + home_prefix = /home/global + + [example.com] + home_prefix = /home/example + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_home_prefix(Some("example.com")), "/home/example"); + assert_eq!(config.get_home_prefix(None), "/home/global"); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!( + config_empty.get_home_prefix(Some("unknown.com")), + DEFAULT_HOME_PREFIX + ); + } + + #[test] + fn test_get_shell() { + let config_data = r#" + [global] + shell = /bin/bash + + [example.com] + shell = /bin/zsh + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_shell(Some("example.com")), "/bin/zsh"); + assert_eq!(config.get_shell(None), "/bin/bash"); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_shell(Some("unknown.com")), DEFAULT_SHELL); + } + + #[test] + fn test_get_connection_timeout() { + let config_data = r#" + [global] + connection_timeout = 45 + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_connection_timeout(), 45); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_connection_timeout(), 30); + } + + #[test] + fn test_get_idmap_range() { + let config_data = r#" + [global] + idmap_range = 1000-2000 + + [example.com] + idmap_range = 5000-6000 + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_idmap_range("example.com"), (5000, 6000)); + assert_eq!(config.get_idmap_range("unknown.com"), (1000, 2000)); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_idmap_range("any.com"), DEFAULT_IDMAP_RANGE); + } + + #[test] + fn test_get_broker_socket_path() { + let config_data = r#" + [global] + broker_socket_path = /var/run/broker.sock + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_broker_socket_path(), "/var/run/broker.sock"); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!( + config_empty.get_broker_socket_path(), + DEFAULT_BROKER_SOCK_PATH + ); + } + + #[test] + fn test_get_pam_allow_groups() { + let config_data = r#" + [example.com] + pam_allow_groups = 2eb4e6a2-f55d-4cf4-8e62-978f9f4a828d,f791d7c2-66cd-4f67-a195-72c6faf3c3b5 + + [global] + pam_allow_groups = 825d1f7e-c4cd-4fc2-aeeb-1f92357f8da6,0149b437-fbaa-4419-bf46-f9a9f9a3438c + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + let mut groups = config.get_pam_allow_groups(); + groups.sort(); + let mut expected_groups: Vec = vec![ + "2eb4e6a2-f55d-4cf4-8e62-978f9f4a828d".to_string(), + "f791d7c2-66cd-4f67-a195-72c6faf3c3b5".to_string(), + "825d1f7e-c4cd-4fc2-aeeb-1f92357f8da6".to_string(), + "0149b437-fbaa-4419-bf46-f9a9f9a3438c".to_string(), + ]; + expected_groups.sort(); + + assert_eq!(groups, expected_groups); + } + + #[test] + fn test_get_hsm_pin_path_env_override() { + env::set_var("HIMMELBLAU_HSM_PIN_PATH", "/custom/pin/path"); + + let config_data = r#" + [global] + hsm_pin_path = /etc/hsm/default_pin + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_hsm_pin_path(), "/custom/pin/path"); + + env::remove_var("HIMMELBLAU_HSM_PIN_PATH"); + } + + #[test] + fn test_get_apply_policy() { + let config_data = r#" + [global] + apply_policy = true + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_apply_policy(), true); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_apply_policy(), false); + } + + #[test] + fn test_get_home_attr() { + let config_data = r#" + [global] + home_attr = cn + + [example.com] + home_attr = spn + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_home_attr(None), HomeAttr::Cn); + assert_eq!(config.get_home_attr(Some("example.com")), HomeAttr::Spn); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_home_attr(None), HomeAttr::Uuid); + } + + #[test] + fn test_get_home_alias() { + let config_data = r#" + [global] + home_alias = cn + + [example.com] + home_alias = uuid + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_home_alias(None), Some(HomeAttr::Cn)); + assert_eq!( + config.get_home_alias(Some("example.com")), + Some(HomeAttr::Uuid) + ); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!( + config_empty.get_home_alias(Some("unknown.com")), + Some(HomeAttr::Spn) + ); + } + + #[test] + fn test_get_odc_provider() { + let config_data = r#" + [global] + odc_provider = suse.com + + [example.com] + odc_provider = odc.officeapps.live.com + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_odc_provider("unknown.com"), "suse.com"); + assert_eq!( + config.get_odc_provider("example.com"), + "odc.officeapps.live.com" + ); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!( + config_empty.get_odc_provider("unknown.com"), + DEFAULT_ODC_PROVIDER + ); + } + + #[test] + fn test_get_app_id() { + let config_data = r#" + [example.com] + app_id = 70fee399-7cd8-42f9-a0ea-1e12ea308908 + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_app_id("unknown.com"), BROKER_APP_ID,); + assert_eq!( + config.get_app_id("example.com"), + "70fee399-7cd8-42f9-a0ea-1e12ea308908" + ); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_app_id("example.com"), BROKER_APP_ID); + } + + #[test] + fn test_get_socket_path() { + let config_data = r#" + [global] + socket_path = /var/run/socket_path.sock + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_socket_path(), "/var/run/socket_path.sock"); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_socket_path(), DEFAULT_SOCK_PATH); + } + + #[test] + fn test_get_task_socket_path() { + let config_data = r#" + [global] + task_socket_path = /var/run/task_socket.sock + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_task_socket_path(), "/var/run/task_socket.sock"); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_task_socket_path(), DEFAULT_TASK_SOCK_PATH); + } + + #[test] + fn test_get_cache_timeout() { + let config_data = r#" + [global] + cache_timeout = 120 + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_cache_timeout(), 120); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_cache_timeout(), DEFAULT_CACHE_TIMEOUT); + } + + #[test] + fn test_get_unix_sock_timeout() { + let config_data = r#" + [global] + connection_timeout = 15 + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_unix_sock_timeout(), 30); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!( + config_empty.get_unix_sock_timeout(), + DEFAULT_CONN_TIMEOUT * 2 + ); + } + + #[test] + fn test_get_db_path() { + let config_data = r#" + [global] + db_path = /var/db/himmelblau.db + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_db_path(), "/var/db/himmelblau.db"); + } + + #[test] + fn test_get_hsm_type() { + let (config_data, default, alt) = if HsmType::default() == HsmType::Soft { + ( + r#" + [global] + hsm_type = tpm + "#, + HsmType::Soft, + HsmType::Tpm, + ) + } else { + ( + r#" + [global] + hsm_type = soft + "#, + HsmType::Tpm, + HsmType::Soft, + ) + }; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + assert_eq!(config.get_hsm_type(), alt); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_hsm_type(), default); + } + + #[test] + fn test_get_use_etc_skel() { + let config_data = r#" + [global] + use_etc_skel = true + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_use_etc_skel(), true); + + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_use_etc_skel(), false); + } + + #[test] + fn test_get_configured_domains() { + let config_data = r#" + [global] + domains = example.com,test.com + + [alpha.com] + [test.com] + [example2.com] + [example.com] + [test2.com] + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + let mut domains = config.get_configured_domains(); + // The order from `domains` must always be preserved (specifically, we + // care about the placement of the first domain only). + assert_eq!(domains[..2], vec!["example.com", "test.com"]); + + // The order of the remaining domains is irrelevant. + domains.sort(); + assert_eq!( + domains, + vec![ + "alpha.com", + "example.com", + "example2.com", + "test.com", + "test2.com" + ] + ); + } + + #[test] + fn test_get_enable_hello() { + let config_data = r#" + [global] + enable_hello = false + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_enable_hello(), false); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_enable_hello(), DEFAULT_HELLO_ENABLED); + } + + #[test] + fn test_get_enable_experimental_mfa() { + let config_data = r#" + [global] + enable_experimental_mfa = false + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_enable_experimental_mfa(), false); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_enable_experimental_mfa(), true); + } + + #[test] + fn test_get_debug() { + let config_data = r#" + [global] + debug = true + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_debug(), true); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_debug(), false); + } + + #[test] + fn test_get_cn_name_mapping() { + let config_data = r#" + [global] + cn_name_mapping = false + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_cn_name_mapping(), false); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_cn_name_mapping(), CN_NAME_MAPPING); + } + + #[test] + fn test_get_authority_host() { + let config_data = r#" + [example.com] + authority_host = https://login.suse.com + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!( + config.get_authority_host("example.com"), + "https://login.suse.com" + ); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!( + config_empty.get_authority_host("example.com"), + DEFAULT_AUTHORITY_HOST + ); + } + + #[test] + fn test_get_graph_url() { + let config_data = r#" + [example.com] + graph_url = https://graph.suse.com + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!( + config.get_graph_url("example.com"), + Some("https://graph.suse.com".to_string()) + ); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_graph_url("example.com"), None); + } + + #[test] + fn test_get_selinux() { + let config_data = r#" + [global] + selinux = true + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_selinux(), true); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_selinux(), DEFAULT_SELINUX); + } + + #[test] + fn test_get_id_attr_map() { + let config_data = r#" + [global] + id_attr_map = uuid + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_id_attr_map(), IdAttr::Uuid); + + // Default fallback for unknown value + let config_invalid = r#" + [global] + id_attr_map = invalid_value + "#; + let temp_file_invalid = create_temp_config(config_invalid); + let config_invalid = HimmelblauConfig::new(Some(&temp_file_invalid)).unwrap(); + assert_eq!(config_invalid.get_id_attr_map(), DEFAULT_ID_ATTR_MAP); + + let config_missing = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_missing.get_id_attr_map(), DEFAULT_ID_ATTR_MAP); + } + + #[test] + fn test_get_hello_pin_min_length() { + let config_data = r#" + [global] + hello_pin_min_length = 8 + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!(config.get_hello_pin_min_length(), 8); + let config_invalid = r#" + [global] + hello_pin_min_length = invalid_value + "#; + let temp_file_invalid = create_temp_config(config_invalid); + let config_invalid = HimmelblauConfig::new(Some(&temp_file_invalid)).unwrap(); + assert_eq!( + config_invalid.get_hello_pin_min_length(), + DEFAULT_HELLO_PIN_MIN_LEN + ); + let config_missing = HimmelblauConfig::new(None).unwrap(); + assert_eq!( + config_missing.get_hello_pin_min_length(), + DEFAULT_HELLO_PIN_MIN_LEN + ); + } + + #[test] + fn test_get_tenant_id() { + let config_data = r#" + [example.com] + tenant_id = example-tenant-id + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!( + config.get_tenant_id("example.com"), + Some("example-tenant-id".to_string()) + ); + assert_eq!(config.get_tenant_id("nonexistent.com"), None); + let config_missing = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_missing.get_tenant_id("example.com"), None); + } + + #[test] + fn test_get_local_groups() { + let config_data = r#" + [global] + local_groups = group1,group2,group3 + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + let expected_groups = vec![ + "group1".to_string(), + "group2".to_string(), + "group3".to_string(), + ]; + assert_eq!(config.get_local_groups(), expected_groups); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_local_groups(), Vec::::new()); + } + + #[test] + fn test_get_logon_script() { + let config_data = r#" + [global] + logon_script = /path/to/logon/script + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + assert_eq!( + config.get_logon_script(), + Some("/path/to/logon/script".to_string()) + ); + let config_missing = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_missing.get_logon_script(), None); + } + + #[test] + fn test_get_logon_token_scopes() { + let config_data = r#" + [global] + logon_token_scopes = scope1,scope2,scope3 + "#; + + let temp_file = create_temp_config(config_data); + let config = HimmelblauConfig::new(Some(&temp_file)).unwrap(); + + let expected_scopes = vec![ + "scope1".to_string(), + "scope2".to_string(), + "scope3".to_string(), + ]; + assert_eq!(config.get_logon_token_scopes(), expected_scopes); + let config_empty = HimmelblauConfig::new(None).unwrap(); + assert_eq!(config_empty.get_logon_token_scopes(), Vec::::new()); + } + + #[test] + fn test_str_to_home_attr() { + assert_eq!(str_to_home_attr("uuid"), HomeAttr::Uuid); + assert_eq!(str_to_home_attr("spn"), HomeAttr::Spn); + assert_eq!(str_to_home_attr("cn"), HomeAttr::Cn); + assert_eq!(str_to_home_attr("invalid"), HomeAttr::Uuid); // Default fallback + } + + #[test] + fn test_split_username() { + assert_eq!( + split_username("user@example.com"), + Some(("user", "example.com")) + ); + assert_eq!(split_username("invalid_username"), None); + } +} diff --git a/src/common/src/unix_config.rs b/src/common/src/unix_config.rs index 7813a9b..b96013d 100644 --- a/src/common/src/unix_config.rs +++ b/src/common/src/unix_config.rs @@ -9,7 +9,7 @@ */ use std::fmt::{Display, Formatter}; -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub enum HomeAttr { Uuid, Spn, @@ -51,7 +51,7 @@ impl Display for UidAttr { } } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq)] pub enum HsmType { #[cfg_attr(not(feature = "tpm"), default)] Soft, From e31c285de51586d1bb732dc004d85bea943f59f3 Mon Sep 17 00:00:00 2001 From: David Mulder Date: Mon, 9 Dec 2024 12:51:21 -0700 Subject: [PATCH 5/5] Version 0.7.10 Signed-off-by: David Mulder --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c514f7d..8c8d077 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ members = [ resolver = "2" [workspace.package] -version = "0.7.9" +version = "0.7.10" authors = [ "David Mulder " ]