diff --git a/scripts/setup/machine-setup/lib/base.sh b/scripts/setup/machine-setup/lib/base.sh index 9e135f92..eaaab9c5 100644 --- a/scripts/setup/machine-setup/lib/base.sh +++ b/scripts/setup/machine-setup/lib/base.sh @@ -199,14 +199,25 @@ ask_username() { echo " of hand. sudo gives you the same power when you ask for it, and" echo " only then — which is why root is not accepted as an answer here." - # No SUDO_USER means this was started as root rather than through sudo, which - # usually means root is how they are logged in. That is exactly the situation - # the advice above is for, so it is worth saying plainly rather than leaving - # as general guidance they can assume is aimed at somebody else. - if [[ -z "${SUDO_USER:-}" ]]; then + # Whether this was started FROM a root session, which usually means root is + # how they log in. That is exactly the situation the advice above is for, and + # the one where general advice is easiest to assume is aimed at somebody else. + # + # Two ways to be in it, and the second is the one that hides: no SUDO_USER at + # all, or a SUDO_USER that is itself uid 0. Some providers ship an image whose + # default account is uid 0 under an ordinary-looking name, so `sudo` from it + # sets SUDO_USER to something that looks like a normal user and is not. + local invoker_uid="" + [[ -n "${SUDO_USER:-}" ]] && invoker_uid="$(id -u "$SUDO_USER" 2>/dev/null || true)" + + if [[ -z "${SUDO_USER:-}" || "$invoker_uid" == "0" ]]; then echo "" - warn "You are running this as root directly, not through sudo." - echo " If root is how you normally log into this machine, now is the" + if [[ -n "${SUDO_USER:-}" ]]; then + warn "You are running this from '${SUDO_USER}', which is uid 0 — the root account." + else + warn "You are running this as root directly, not through sudo." + fi + echo " If that is how you normally log into this machine, now is the" echo " moment to make an account and stop doing that." fi echo "" @@ -225,7 +236,18 @@ ask_username() { # answered against a name that was never going to work. [[ "$answer" =~ ^[a-z_][a-z0-9_-]*\$?$ && ${#answer} -le 32 ]] || fail "'${answer}' is not a usable Linux username — lower case, starting with a letter or underscore." - [[ "$answer" == "root" ]] && fail "root is not the account to set up here." + # By uid, not by name. "root" is a label — what makes an account root is uid 0, + # and some providers ship an image whose default login is uid 0 under a + # friendlier name. Refusing only the string would let exactly that case through, + # which is the one worth catching. + local answer_uid + answer_uid="$(id -u "$answer" 2>/dev/null || true)" + if [[ "$answer_uid" == "0" ]]; then + if [[ "$answer" == "root" ]]; then + fail "root is not the account to set up here — see the warning above." + fi + fail "'${answer}' is uid 0 — the root account under another name, and not what to set up here." + fi USERNAME="$answer"