#!/usr/bin/env bash # admin-path.sh — assert the admin binaries are REACHABLE, not merely that we # are root. # # Being uid 0 and being able to find useradd are different facts, and rig # asserted only the first. `su` without `-`, sudo with a sanitised secure_path, # and several container images all hand you a root shell whose PATH carries no # /usr/sbin — which is where useradd, usermod and groupadd live on Debian. The # result was a bare `useradd: command not found` naming a line number inside a # versioned install root, emitted AFTER a registration token had been read off # the operator's terminal (#139). # # Which binaries this covers is measured, not assumed (Debian 13, 2026-08-01): # # useradd usermod groupadd userdel groupdel /usr/sbin package: passwd # visudo /usr/sbin package: sudo # gpasswd /usr/bin package: passwd # # Two consequences worth keeping written down. `gpasswd` is in the same PACKAGE # as useradd but a different DIRECTORY, so it is reachable on a PATH-shorn root # and does not belong in any of these preflights — do not add it for symmetry. # And `visudo` shares the directory but not the package, so its absence has a # second, innocent cause (sudo simply not installed) that the others do not, so # `rig users apply` checks it separately, after the point where that cause is # ruled out. See the comment there. # # (Spelled without the `.sh` on purpose: test/cli.sh pins that exactly one file # under commands/ names that script, to catch a second caller appearing. A # comment is not a caller, but the pin is deliberately blunt and cheap.) # # It REFUSES rather than repairing PATH itself. A command that quietly prepends # /usr/sbin teaches the operator nothing and leaves a misconfigured host # misconfigured; the same reason bootstrap refuses rather than guessing. The # message carries the fix so the refusal costs one paste, not an investigation. # require_admin_bins ... — die unless every one resolves on PATH. require_admin_bins() { local missing=() b for b in "$@"; do command -v "$b" >/dev/null 2>&1 || missing+=("$b") done [ "${#missing[@]}" -eq 0 ] && return 0 # Names the REMEDY, not this script: the operator typed a `rig ...` command, # and echoing the internal path back at them is the unhelpful half of the # original `useradd: command not found`. die "cannot find ${missing[*]} on PATH — it lives in /usr/sbin, which this root shell does not carry (a 'su' without '-' does this, and so do some container images). Re-run the same rig command with: PATH=/usr/sbin:/sbin:\$PATH" }