forked from lix-project/lix-installer
Support busybox user/group modification, more informational errors (#319)
This commit is contained in:
parent
51056b854a
commit
32dca2e846
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -360,6 +360,12 @@ version = "1.0.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.32"
|
||||
|
@ -980,6 +986,7 @@ dependencies = [
|
|||
"typetag",
|
||||
"url",
|
||||
"uuid",
|
||||
"which",
|
||||
"xz2",
|
||||
]
|
||||
|
||||
|
@ -2068,6 +2075,17 @@ dependencies = [
|
|||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
|
||||
dependencies = [
|
||||
"either",
|
||||
"libc",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
|
@ -58,6 +58,7 @@ os-release = { version = "0.1.0", default-features = false, optional = true }
|
|||
is_ci = { version = "1.1.1", default-features = false, optional = true }
|
||||
strum = { version = "0.24.1", features = ["derive"] }
|
||||
nix-config-parser = { version = "0.1.2", features = ["serde"] }
|
||||
which = "4.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
eyre = { version = "0.6.8", default-features = false, features = [ "track-caller" ] }
|
||||
|
|
|
@ -202,14 +202,26 @@ impl Action for AddUserToGroup {
|
|||
.await?;
|
||||
},
|
||||
_ => {
|
||||
execute_command(
|
||||
Command::new("gpasswd")
|
||||
.process_group(0)
|
||||
.args(["-a"])
|
||||
.args([&name.to_string(), &groupname.to_string()])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
if which::which("gpasswd").is_ok() {
|
||||
execute_command(
|
||||
Command::new("gpasswd")
|
||||
.process_group(0)
|
||||
.args(["-a"])
|
||||
.args([name, groupname])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else if which::which("addgroup").is_ok() {
|
||||
execute_command(
|
||||
Command::new("addgroup")
|
||||
.process_group(0)
|
||||
.args([name, groupname])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
return Err(ActionError::MissingAddUserToGroupCommand);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -255,14 +267,26 @@ impl Action for AddUserToGroup {
|
|||
.await?;
|
||||
},
|
||||
_ => {
|
||||
execute_command(
|
||||
Command::new("gpasswd")
|
||||
.process_group(0)
|
||||
.args(["-d"])
|
||||
.args([&name.to_string(), &groupname.to_string()])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
if which::which("gpasswd").is_ok() {
|
||||
execute_command(
|
||||
Command::new("gpasswd")
|
||||
.process_group(0)
|
||||
.args(["-d"])
|
||||
.args([&name.to_string(), &groupname.to_string()])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else if which::which("delgroup").is_ok() {
|
||||
execute_command(
|
||||
Command::new("delgroup")
|
||||
.process_group(0)
|
||||
.args([name, groupname])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
return Err(ActionError::MissingRemoveUserFromGroupCommand);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -92,20 +92,32 @@ impl Action for CreateGroup {
|
|||
"Nix build group for nix-daemon",
|
||||
"-i",
|
||||
&format!("{gid}"),
|
||||
name.as_str(),
|
||||
name,
|
||||
])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
},
|
||||
_ => {
|
||||
execute_command(
|
||||
Command::new("groupadd")
|
||||
.process_group(0)
|
||||
.args(["-g", &gid.to_string(), "--system", &name])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
if which::which("groupadd").is_ok() {
|
||||
execute_command(
|
||||
Command::new("groupadd")
|
||||
.process_group(0)
|
||||
.args(["-g", &gid.to_string(), "--system", name])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else if which::which("addgroup").is_ok() {
|
||||
execute_command(
|
||||
Command::new("addgroup")
|
||||
.process_group(0)
|
||||
.args(["-g", &gid.to_string(), "--system", name])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
return Err(ActionError::MissingGroupCreationCommand);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -143,13 +155,25 @@ impl Action for CreateGroup {
|
|||
if !output.status.success() {}
|
||||
},
|
||||
_ => {
|
||||
execute_command(
|
||||
Command::new("groupdel")
|
||||
.process_group(0)
|
||||
.arg(&name)
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
if which::which("groupdel").is_ok() {
|
||||
execute_command(
|
||||
Command::new("groupdel")
|
||||
.process_group(0)
|
||||
.arg(name)
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else if which::which("delgroup").is_ok() {
|
||||
execute_command(
|
||||
Command::new("delgroup")
|
||||
.process_group(0)
|
||||
.arg(name)
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
return Err(ActionError::MissingGroupDeletionCommand);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ impl Action for CreateUser {
|
|||
let Self {
|
||||
name,
|
||||
uid,
|
||||
groupname: _,
|
||||
groupname,
|
||||
gid,
|
||||
} = self;
|
||||
|
||||
|
@ -178,31 +178,57 @@ impl Action for CreateUser {
|
|||
.await?;
|
||||
},
|
||||
_ => {
|
||||
execute_command(
|
||||
Command::new("useradd")
|
||||
.process_group(0)
|
||||
.args([
|
||||
"--home-dir",
|
||||
"/var/empty",
|
||||
"--comment",
|
||||
&format!("\"Nix build user\""),
|
||||
"--gid",
|
||||
&gid.to_string(),
|
||||
"--groups",
|
||||
&gid.to_string(),
|
||||
"--no-user-group",
|
||||
"--system",
|
||||
"--shell",
|
||||
"/sbin/nologin",
|
||||
"--uid",
|
||||
&uid.to_string(),
|
||||
"--password",
|
||||
"\"!\"",
|
||||
&name.to_string(),
|
||||
])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
if which::which("useradd").is_ok() {
|
||||
execute_command(
|
||||
Command::new("useradd")
|
||||
.process_group(0)
|
||||
.args([
|
||||
"--home-dir",
|
||||
"/var/empty",
|
||||
"--comment",
|
||||
"Nix build user",
|
||||
"--gid",
|
||||
&gid.to_string(),
|
||||
"--groups",
|
||||
&gid.to_string(),
|
||||
"--no-user-group",
|
||||
"--system",
|
||||
"--shell",
|
||||
"/sbin/nologin",
|
||||
"--uid",
|
||||
&uid.to_string(),
|
||||
"--password",
|
||||
"!",
|
||||
name,
|
||||
])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else if which::which("adduser").is_ok() {
|
||||
execute_command(
|
||||
Command::new("adduser")
|
||||
.process_group(0)
|
||||
.args([
|
||||
"--home",
|
||||
"/var/empty",
|
||||
"--gecos",
|
||||
"Nix build user",
|
||||
"--ingroup",
|
||||
groupname,
|
||||
"--system",
|
||||
"--shell",
|
||||
"/sbin/nologin",
|
||||
"--uid",
|
||||
&uid.to_string(),
|
||||
"--disabled-password",
|
||||
name,
|
||||
])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
return Err(ActionError::MissingUserCreationCommand);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -266,13 +292,25 @@ impl Action for CreateUser {
|
|||
}
|
||||
},
|
||||
_ => {
|
||||
execute_command(
|
||||
Command::new("userdel")
|
||||
.process_group(0)
|
||||
.args([&name.to_string()])
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
if which::which("userdel").is_ok() {
|
||||
execute_command(
|
||||
Command::new("userdel")
|
||||
.process_group(0)
|
||||
.arg(name)
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else if which::which("deluser").is_ok() {
|
||||
execute_command(
|
||||
Command::new("deluser")
|
||||
.process_group(0)
|
||||
.arg(name)
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
return Err(ActionError::MissingUserDeletionCommand);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -5,8 +5,7 @@ use crate::{
|
|||
},
|
||||
settings::CommonSettings,
|
||||
};
|
||||
use tokio::task::JoinSet;
|
||||
use tracing::{span, Instrument, Span};
|
||||
use tracing::{span, Span};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUsersAndGroups {
|
||||
|
@ -266,37 +265,11 @@ impl Action for CreateUsersAndGroups {
|
|||
nix_build_user_prefix: _,
|
||||
nix_build_user_id_base: _,
|
||||
} = self;
|
||||
let mut set = JoinSet::new();
|
||||
|
||||
let mut errors = Vec::default();
|
||||
|
||||
for (idx, create_user) in create_users.iter().enumerate() {
|
||||
let span = tracing::Span::current().clone();
|
||||
let mut create_user_clone = create_user.clone();
|
||||
let _abort_handle = set.spawn(async move {
|
||||
create_user_clone
|
||||
.try_revert()
|
||||
.instrument(span)
|
||||
.await
|
||||
.map_err(|e| ActionError::Child(create_user_clone.action_tag(), Box::new(e)))?;
|
||||
Result::<_, ActionError>::Ok((idx, create_user_clone))
|
||||
});
|
||||
}
|
||||
|
||||
while let Some(result) = set.join_next().await {
|
||||
match result {
|
||||
Ok(Ok((idx, success))) => create_users[idx] = success,
|
||||
Ok(Err(e)) => errors.push(Box::new(e)),
|
||||
Err(e) => return Err(ActionError::Join(e))?,
|
||||
};
|
||||
}
|
||||
|
||||
if !errors.is_empty() {
|
||||
if errors.len() == 1 {
|
||||
return Err(*errors.into_iter().next().unwrap());
|
||||
} else {
|
||||
return Err(ActionError::Children(errors));
|
||||
}
|
||||
for create_user in create_users.iter_mut() {
|
||||
create_user
|
||||
.try_revert()
|
||||
.await
|
||||
.map_err(|e| ActionError::Child(create_user.action_tag(), Box::new(e)))?;
|
||||
}
|
||||
|
||||
// We don't actually need to do this, when a user is deleted they are removed from groups
|
||||
|
|
|
@ -427,6 +427,22 @@ pub enum ActionError {
|
|||
Plist(#[from] plist::Error),
|
||||
#[error("Unexpected binary tarball contents found, the build result from `https://releases.nixos.org/?prefix=nix/` or `nix build nix#hydraJobs.binaryTarball.$SYSTEM` is expected")]
|
||||
MalformedBinaryTarball,
|
||||
#[error(
|
||||
"Could not find a supported command to create users in PATH; please install `useradd` or `adduser`"
|
||||
)]
|
||||
MissingUserCreationCommand,
|
||||
#[error("Could not find a supported command to create groups in PATH; please install `groupadd` or `addgroup`")]
|
||||
MissingGroupCreationCommand,
|
||||
#[error("Could not find a supported command to add users to groups in PATH; please install `gpasswd` or `addgroup`")]
|
||||
MissingAddUserToGroupCommand,
|
||||
#[error(
|
||||
"Could not find a supported command to delete users in PATH; please install `userdel` or `deluser`"
|
||||
)]
|
||||
MissingUserDeletionCommand,
|
||||
#[error("Could not find a supported command to delete groups in PATH; please install `groupdel` or `delgroup`")]
|
||||
MissingGroupDeletionCommand,
|
||||
#[error("Could not find a supported command to remove users from groups in PATH; please install `gpasswd` or `deluser`")]
|
||||
MissingRemoveUserFromGroupCommand,
|
||||
}
|
||||
|
||||
impl ActionError {
|
||||
|
|
Loading…
Reference in a new issue