Skip to content

Commit

Permalink
stash
Browse files Browse the repository at this point in the history
  • Loading branch information
ckyrouac committed Feb 26, 2025
1 parent 39e0527 commit 9f77b79
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 38 deletions.
4 changes: 1 addition & 3 deletions system-reinstall-bootc/src/podman.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,9 @@ pub(crate) fn command(image: &str, root_key: &Option<UserKeys>) -> 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());
Expand Down
116 changes: 81 additions & 35 deletions system-reinstall-bootc/src/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -146,6 +145,54 @@ impl SshdConfig {
}
}

fn get_keys_from_files(user: &uzers::User, keyfiles: &Vec<String>) -> Result<String> {
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<String> {
Ok(String::new())
}

pub(crate) fn get_all_users_keys() -> Result<Vec<UserKeys>> {
let loginctl_user_names = loginctl_users().context("enumerate users")?;

Expand All @@ -158,52 +205,33 @@ pub(crate) fn get_all_users_keys() -> Result<Vec<UserKeys>> {
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,
Expand All @@ -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");
}
}

0 comments on commit 9f77b79

Please sign in to comment.