From 09da116ccdf674b1f8650360370343ac92fa0f67 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 6 Jan 2024 17:24:34 +0100 Subject: [PATCH] Move /etc/group generation to the installer This ensures that the gid's for the auto-generated user groups stay in sync with the gid in /etc/passwd. It also makes it easier to evolve the format of /etc/group in the future. --- config/default.toml | 12 ++++-------- src/config/mod.rs | 7 +++++++ src/config/user.rs | 7 +++++++ src/lib.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++- test.toml | 13 +++++-------- 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/config/default.toml b/config/default.toml index 0a5e7226bd..fef03c7b6e 100644 --- a/config/default.toml +++ b/config/default.toml @@ -69,6 +69,10 @@ home = "/root" # Password is unset password = "" +[groups.sudo] +gid = 1 +members = ["user"] + [[files]] path = "/etc/init.d/00_base" data = """ @@ -135,14 +139,6 @@ data = """ path = "/etc/pkg.d/50_redox" data = "https://static.redox-os.org/pkg" -[[files]] -path = "/etc/group" -data = """ -root;0;root -user;1000;user -sudo;1;user -""" - [[files]] path = "/etc/hostname" data = """ diff --git a/src/config/mod.rs b/src/config/mod.rs index be679f19e1..5f11eff2c5 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -20,6 +20,8 @@ pub struct Config { pub files: Vec, #[serde(default)] pub users: BTreeMap, + #[serde(default)] + pub groups: BTreeMap, } impl Config { @@ -63,6 +65,7 @@ impl Config { packages: other_packages, files: other_files, users: other_users, + groups: other_groups, } = other; self.general.merge(other_general); @@ -76,5 +79,9 @@ impl Config { for (user, user_config) in other_users { self.users.insert(user, user_config); } + + for (group, group_config) in other_groups { + self.groups.insert(group, group_config); + } } } diff --git a/src/config/user.rs b/src/config/user.rs index 3b82342048..9e9393de0c 100644 --- a/src/config/user.rs +++ b/src/config/user.rs @@ -7,3 +7,10 @@ pub struct UserConfig { pub home: Option, pub shell: Option, } + +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +pub struct GroupConfig { + pub gid: Option, + // FIXME move this to the UserConfig struct as extra_groups + pub members: Vec, +} diff --git a/src/lib.rs b/src/lib.rs index f70c50d56d..84c5a9d0f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -181,6 +181,9 @@ pub fn install_dir, S: AsRef>(config: Config, output_dir: P, let mut passwd = String::new(); let mut shadow = String::new(); let mut next_uid = 1000; + let mut next_gid = 1000; + + let mut groups = vec![]; for (username, user) in config.users { // plaintext @@ -200,7 +203,11 @@ pub fn install_dir, S: AsRef>(config: Config, output_dir: P, next_uid = uid + 1; } - let gid = user.gid.unwrap_or(uid); + let gid = user.gid.unwrap_or(next_gid); + + if gid >= next_gid { + next_gid = gid + 1; + } let name = prompt!(user.name, username.clone(), "{}: name (GECOS) [{}]: ", username, username)?; let home = prompt!(user.home, format!("/home/{}", username), "{}: home [/home/{}]: ", username, username)?; @@ -229,6 +236,19 @@ pub fn install_dir, S: AsRef>(config: Config, output_dir: P, passwd.push_str(&format!("{};{};{};{};file:{};file:{}\n", username, uid, gid, name, home, shell)); shadow.push_str(&format!("{};{}\n", username, password)); + groups.push((username.clone(), gid, vec![username])); + } + + for (group, group_config) in config.groups { + // FIXME this assumes there is no overlap between auto-created groups for users + // and explicitly specified groups. + let gid = group_config.gid.unwrap_or(next_gid); + + if gid >= next_gid { + next_gid = gid + 1; + } + + groups.push((group, gid, group_config.members)); } if !passwd.is_empty() { @@ -258,6 +278,31 @@ pub fn install_dir, S: AsRef>(config: Config, output_dir: P, }.create(&output_dir)?; } + if !groups.is_empty() { + let mut groups_data = String::new(); + + for (name, gid, members) in groups { + use std::fmt::Write; + writeln!(groups_data, "{name};{gid};{}", members.join(",")).unwrap(); + + println!("Adding group {}:", name); + println!("\tGID: {}", gid); + println!("\tMembers: {}", members.join(", ")); + } + + FileConfig { + path: "/etc/group".to_string(), + data: groups_data, + symlink: false, + directory: false, + // Take defaults + mode: None, + uid: None, + gid: None, + recursive_chown: false, + }.create(&output_dir)?; + } + Ok(()) } diff --git a/test.toml b/test.toml index 39c0082dcf..08b9f2be97 100644 --- a/test.toml +++ b/test.toml @@ -54,6 +54,11 @@ home = "/root" # Password is unset password = "" +# Group settings +[groups.sudo] +gid = 1 +members = ["user"] + [[files]] path = "/etc/init.d/00_base" data = """ @@ -118,14 +123,6 @@ data = """ path = "/etc/pkg.d/50_redox" data = "https://static.redox-os.org/pkg" -[[files]] -path = "/etc/group" -data = """ -root;0;root -user;1000;user -sudo;1;user -""" - [[files]] path = "/etc/hostname" data = """