From 9f77b79e9e2d2ff9f286554393a05cc78a6ec929 Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Wed, 26 Feb 2025 10:25:54 -0500 Subject: [PATCH] stash --- system-reinstall-bootc/src/podman.rs | 4 +- system-reinstall-bootc/src/users.rs | 116 +++++++++++++++++++-------- 2 files changed, 82 insertions(+), 38 deletions(-) diff --git a/system-reinstall-bootc/src/podman.rs b/system-reinstall-bootc/src/podman.rs index 5ba7250c..e20605e5 100644 --- a/system-reinstall-bootc/src/podman.rs +++ b/system-reinstall-bootc/src/podman.rs @@ -45,11 +45,9 @@ pub(crate) fn command(image: &str, root_key: &Option) -> Command { .to_vec(); if let Some(root_key) = root_key.as_ref() { - let root_authorized_keys_path = root_key.authorized_keys_path.clone(); - podman_command_and_args.push("-v".to_string()); podman_command_and_args.push(format!( - "{root_authorized_keys_path}:{ROOT_KEY_MOUNT_POINT}" + ":{ROOT_KEY_MOUNT_POINT}" //TODO: use a temporary file that contains all user's keys )); bootc_command_and_args.push("--root-ssh-authorized-keys".to_string()); diff --git a/system-reinstall-bootc/src/users.rs b/system-reinstall-bootc/src/users.rs index 4601118b..1a440137 100644 --- a/system-reinstall-bootc/src/users.rs +++ b/system-reinstall-bootc/src/users.rs @@ -82,7 +82,6 @@ impl Drop for UidChange { pub(crate) struct UserKeys { pub(crate) user: String, pub(crate) authorized_keys: String, - pub(crate) authorized_keys_path: String, } impl UserKeys { @@ -146,6 +145,54 @@ impl SshdConfig { } } +fn get_keys_from_files(user: &uzers::User, keyfiles: &Vec) -> Result { + let home_dir = user.home_dir(); + let mut user_authorized_keys = String::new(); + + for keyfile in keyfiles { + let user_authorized_keys_path = home_dir.join(keyfile); + + if !user_authorized_keys_path.exists() { + tracing::debug!( + "Skipping authorized key file {} for user {} because it doesn't exist", + user_authorized_keys_path.to_string_lossy(), + user.name().to_string_lossy() + ); + continue; + } + + // Safety: The UID should be valid because we got it from uzers + #[allow(unsafe_code)] + let user_uid = unsafe { Uid::from_raw(user.uid()) }; + + // Change the effective uid for this scope, to avoid accidentally reading files we + // shouldn't through symlinks + let _uid_change = UidChange::new(user_uid)?; + + let key = std::fs::read_to_string(&user_authorized_keys_path) + .context("Failed to read user's authorized keys")?; + user_authorized_keys.push_str(key.as_str()); + } + + //TODO: move this up + if user_authorized_keys.trim().is_empty() { + tracing::debug!( + "Skipping user {} because it has an empty SSH authorized_keys file", + user.name().to_string_lossy() + ); + } + + Ok(user_authorized_keys) +} + +fn get_keys_from_command( + user: &uzers::User, + command: &String, + command_user: &String, +) -> Result { + Ok(String::new()) +} + pub(crate) fn get_all_users_keys() -> Result> { let loginctl_user_names = loginctl_users().context("enumerate users")?; @@ -158,52 +205,33 @@ pub(crate) fn get_all_users_keys() -> Result> { let user_info = uzers::get_user_by_name(user_name.as_str()) .context(format!("user {} not found", user_name))?; - let home_dir = user_info.home_dir(); - let user_authorized_keys_path = home_dir.join(".ssh/authorized_keys"); - - if !user_authorized_keys_path.exists() { - tracing::debug!( - "Skipping user {} because it doesn't have an SSH authorized_keys file", - user_info.name().to_string_lossy() - ); - continue; + let mut user_authorized_keys = String::new(); + if !sshd_config.authorized_keys_files.is_empty() { + let keys = get_keys_from_files(&user_info, &sshd_config.authorized_keys_files)?; + user_authorized_keys.push_str(keys.as_str()); } + if sshd_config.authorized_keys_command != "none" { + let keys = get_keys_from_command( + &user_info, + &sshd_config.authorized_keys_command, + &sshd_config.authorized_keys_command_user, + )?; + user_authorized_keys.push_str(keys.as_str()); + }; + let user_name = user_info .name() .to_str() .context("user name is not valid utf-8")?; - let user_authorized_keys = { - // Safety: The UID should be valid because we got it from uzers - #[allow(unsafe_code)] - let user_uid = unsafe { Uid::from_raw(user_info.uid()) }; - - // Change the effective uid for this scope, to avoid accidentally reading files we - // shouldn't through symlinks - let _uid_change = UidChange::new(user_uid)?; - - std::fs::read_to_string(&user_authorized_keys_path) - .context("Failed to read user's authorized keys")? - }; - - if user_authorized_keys.trim().is_empty() { - tracing::debug!( - "Skipping user {} because it has an empty SSH authorized_keys file", - user_info.name().to_string_lossy() - ); - continue; - } - let user_keys = UserKeys { user: user_name.to_string(), authorized_keys: user_authorized_keys, - authorized_keys_path: user_authorized_keys_path - .to_str() - .context("user's authorized_keys path is not valid utf-8")? - .to_string(), }; + tracing::debug!("Found user keys: {:?}", user_keys); + tracing::debug!( "Found user {} with {} SSH authorized_keys", user_keys.user, @@ -230,4 +258,22 @@ mod test { assert!(result.contains("root")); assert!(result.contains("foo-doe")); } + + fn split_on_first_whitespace(input: &str) -> Option<(&str, &str)> { + let mut parts = input.splitn(2, char::is_whitespace); + let first = parts.next()?; + let second = parts.next().unwrap_or(""); + Some((first, second)) + } + + #[test] + pub(crate) fn test_me() { + println!("ahhh"); + let input = "foo bar bar2 bar3"; + if let Some((first, rest)) = split_on_first_whitespace(input) { + println!("First part: '{}'", first); + println!("Rest part: '{}'", rest); + } + panic!("ahhh"); + } }