From 028e7c16940f27015ce26aebcaeb6a039f422a2f Mon Sep 17 00:00:00 2001 From: Anton Loukianov Date: Mon, 15 Jul 2024 17:34:11 -0700 Subject: [PATCH] Implement home_mount_path logic (#2894) --- CONTRIBUTORS.md | 1 + examples/unixd | 19 +++++++++++++++++-- examples/unixd.macos | 1 + .../resolver/src/bin/kanidm_unixd_tasks.rs | 15 ++++++++++++--- unix_integration/resolver/src/unix_config.rs | 8 ++++++++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c23de5309..4529a0930 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -38,6 +38,7 @@ - Merlijn Verstraete (ToxicMushroom) - Tobias Krischer (tobikris) - Daniil Egortsev (playhardgopro) +- Anton Loukianov (antonl) ## Acknowledgements diff --git a/examples/unixd b/examples/unixd index 7dd8b96c1..aee050b3d 100644 --- a/examples/unixd +++ b/examples/unixd @@ -60,6 +60,23 @@ pam_allowed_login_groups = ["posix_group"] # home_attr = "uuid" +# Controls the prefix that will be appended to the home alias when mounting home directories. Must +# end with a trailing `/`. If unset, defaults to the value of the `home_prefix`. +# +# This is option is useful when implementing a networked home directory layout. A common implementation +# is to configure a networked filesystem that contains user directories mounted at `/u/` (eg /u/$user_uuid) +# and then symlink the mounted directory into /home/$user_name when the user logs in. This can be accomplished +# with a configuration that includes the following: +# +# > home_attr = "uuid" +# > home_alias = "name" +# > home_prefix = "/u/" +# > home_mount_prefix = "/home/" +# +# Default: unset +# +# home_mount_prefix = "/home/" +# # The default token attribute used for generating symlinks pointing to the user's home # directory. If set, this will become the value of the home path to nss calls. It is recommended you @@ -115,5 +132,3 @@ pam_allowed_login_groups = ["posix_group"] # Default: Empty set (no overrides) # allow_local_account_override = ["admin"] - - diff --git a/examples/unixd.macos b/examples/unixd.macos index 06c6a17d0..ebbacb04d 100644 --- a/examples/unixd.macos +++ b/examples/unixd.macos @@ -6,6 +6,7 @@ task_sock_path = "/tmp/kanimd_unidx_task.sock" pam_allowed_login_groups = ["posix_group"] # default_shell = "/bin/sh" # home_prefix = "/home/" +# home_mount_prefix = "/home/" # home_attr = "uuid" # home_alias = "spn" # uid_attr_map = "spn" diff --git a/unix_integration/resolver/src/bin/kanidm_unixd_tasks.rs b/unix_integration/resolver/src/bin/kanidm_unixd_tasks.rs index 375862f0f..456fd6b6a 100644 --- a/unix_integration/resolver/src/bin/kanidm_unixd_tasks.rs +++ b/unix_integration/resolver/src/bin/kanidm_unixd_tasks.rs @@ -35,7 +35,7 @@ use tokio_util::codec::{Decoder, Encoder, Framed}; use walkdir::WalkDir; #[cfg(all(target_family = "unix", feature = "selinux"))] -use crate::selinux_util; +use kanidm_unix_resolver::selinux_util; struct TaskCodec; @@ -89,6 +89,7 @@ fn chown(path: &Path, gid: u32) -> Result<(), String> { fn create_home_directory( info: &HomeDirectoryInfo, home_prefix: &str, + home_mount_prefix: &Option, use_etc_skel: bool, use_selinux: bool, ) -> Result<(), String> { @@ -96,12 +97,17 @@ fn create_home_directory( let name = info.name.trim_start_matches('.').replace(['/', '\\'], ""); let home_prefix_path = Path::new(home_prefix); + let home_mount_prefix_path = Path::new(home_mount_prefix.as_deref().unwrap_or(home_prefix)); // Does our home_prefix actually exist? if !home_prefix_path.exists() || !home_prefix_path.is_dir() { return Err("Invalid home_prefix from configuration".to_string()); } + if !home_mount_prefix_path.exists() || !home_mount_prefix_path.is_dir() { + return Err("Invalid home_mount_prefix from configuration".to_string()); + } + // Actually process the request here. let hd_path_raw = format!("{}{}", home_prefix, name); let hd_path = Path::new(&hd_path_raw); @@ -192,8 +198,10 @@ fn create_home_directory( // Assert the resulting alias path is consistent and correct. if let Some(pp) = alias_path.parent() { - if pp != home_prefix_path { - return Err("Invalid home directory alias - not within home_prefix".to_string()); + if pp != home_mount_prefix_path { + return Err( + "Invalid home directory alias - not within home_mount_prefix".to_string(), + ); } } else { return Err("Invalid/Corrupt alias directory path - no prefix found".to_string()); @@ -237,6 +245,7 @@ async fn handle_tasks(stream: UnixStream, cfg: &KanidmUnixdConfig) { let resp = match create_home_directory( &info, &cfg.home_prefix, + &cfg.home_mount_prefix, cfg.use_etc_skel, cfg.selinux, ) { diff --git a/unix_integration/resolver/src/unix_config.rs b/unix_integration/resolver/src/unix_config.rs index 9e723e483..a714d20b6 100644 --- a/unix_integration/resolver/src/unix_config.rs +++ b/unix_integration/resolver/src/unix_config.rs @@ -25,6 +25,7 @@ struct ConfigInt { pam_allowed_login_groups: Option>, default_shell: Option, home_prefix: Option, + home_mount_prefix: Option, home_attr: Option, home_alias: Option, use_etc_skel: Option, @@ -70,6 +71,7 @@ pub struct KanidmUnixdConfig { pub pam_allowed_login_groups: Vec, pub default_shell: String, pub home_prefix: String, + pub home_mount_prefix: Option, pub home_attr: HomeAttr, pub home_alias: Option, pub use_etc_skel: bool, @@ -104,6 +106,10 @@ impl Display for KanidmUnixdConfig { )?; writeln!(f, "default_shell: {}", self.default_shell)?; writeln!(f, "home_prefix: {}", self.home_prefix)?; + match self.home_mount_prefix.as_deref() { + Some(val) => writeln!(f, "home_mount_prefix: {}", val)?, + None => writeln!(f, "home_mount_prefix: unset")?, + } writeln!(f, "home_attr: {}", self.home_attr)?; match self.home_alias { Some(val) => writeln!(f, "home_alias: {}", val)?, @@ -147,6 +153,7 @@ impl KanidmUnixdConfig { pam_allowed_login_groups: Vec::new(), default_shell: DEFAULT_SHELL.to_string(), home_prefix: DEFAULT_HOME_PREFIX.to_string(), + home_mount_prefix: None, home_attr: DEFAULT_HOME_ATTR, home_alias: DEFAULT_HOME_ALIAS, use_etc_skel: DEFAULT_USE_ETC_SKEL, @@ -222,6 +229,7 @@ impl KanidmUnixdConfig { .unwrap_or(self.pam_allowed_login_groups), default_shell: config.default_shell.unwrap_or(self.default_shell), home_prefix: config.home_prefix.unwrap_or(self.home_prefix), + home_mount_prefix: config.home_mount_prefix, home_attr: config .home_attr .and_then(|v| match v.as_str() {