useradd: implemented useradd -K/--key KEY=VALUE (override /etc/login.defs defaults) - #211
Conversation
pierre-warnier
left a comment
There was a problem hiding this comment.
Thanks for this @jlesage, and sorry for the slow first response — the maintainers were away over August.
This is a well-put-together contribution: the LoginDefs::set/apply_overrides API is a clean place for the logic, overrides are applied before the defaults are read (so CREATE_HOME/SKEL behave correctly), and you covered it at three levels — unit tests on the parser, allocation tests for UID/GID/SYS ranges, and root-only integration tests. I ran the suite as root in the Debian container: 23/23 test_useradd tests pass, and fmt + clippy -D warnings + the full workspace suite are green.
One thing to fix before merge, then I'm happy to land it:
useradd -D ignores -K
cmd_defaults() is the third LoginDefs::load site and it doesn't get the overrides, so -K is silently dropped in -D mode. Verified on your branch:
$ useradd -D -K HOME=/OVERRIDDEN -K SHELL=/bin/zsh
GROUP=100
HOME=/home # expected /OVERRIDDEN
INACTIVE=-1
EXPIRE=
SHELL= # expected /bin/zshparse_options and do_useradd both apply them correctly — it's just this one path. Something like:
fn cmd_defaults(matches: &clap::ArgMatches) -> UResult<()> {
let root = SysRoot::default();
let mut defs = LoginDefs::load(&root.login_defs_path())
.map_err(|e| UseraddError::CannotUpdatePasswd(format!("{e}")))?;
apply_login_defs_overrides(&mut defs, &parse_login_defs_overrides(matches)?);(the _matches parameter is already there, just unused). A small -D -K assertion in the integration tests would lock it in.
Non-blocking, for me to follow up
groupadd already has its own -K handling in allocate_gid, which hand-patches only GID_MIN/GID_MAX/SYS_GID_* and silently ignores unparseable values and every other key. Your LoginDefs::apply_overrides is strictly better — I'll open a separate PR migrating groupadd onto it after this lands, so the two tools behave the same. Nothing for you to do here.
cmd_defaults loaded login.defs but dropped -K/--key, so `useradd -D -K HOME=...` printed the file values. Apply overrides before printing, and honor --root so -R -D uses the chroot login.defs.
|
@pierre-warnier thank you for the review. I pushed the requested fix. Thank you! |
pierre-warnier
left a comment
There was a problem hiding this comment.
Verified and merging — thanks @jlesage.
The -D path now honours the overrides:
$ useradd -D
HOME=/home
$ useradd -D -K HOME=/OVERRIDDEN -K SHELL=/bin/zsh
HOME=/OVERRIDDEN
SHELL=/bin/zshYou also went past what I asked for, and both additions are good ones:
cmd_defaultswas hardcodingSysRoot::default(), souseradd -D -R /some/rootsilently read the host'slogin.defs. That was a separate bug and you fixed it.- Splitting out
write_defaults(matches, out)makes the report testable — it previously wrote straight to stdout with no seam.
Full gate green on Debian: fmt, clippy -D warnings, cargo test --workspace, and 25/25 test_useradd integration tests as root.
Sorry again for the four-week wait on the first review. Follow-up on my side: groupadd has its own hand-rolled -K handling that only understands the GID-range keys and swallows parse errors; I'll migrate it onto your LoginDefs::apply_overrides so both tools behave identically (#223).
This implements the useradd -K/--key KEY=VALUE (override /etc/login.defs defaults).