rig/commands/users-status.sh

66 lines
2.3 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# rig users status — what this box's operator accounts actually are, read from
# the machine itself: roles derived from REAL group membership (not the
# ledger's memory of an apply), key counts from authorized_keys, lock state
# from shadow. Reads only — no network, no writes.
set -euo pipefail
log() { printf 'rig-users: %s\n' "$*"; }
warn() { printf 'rig-users: WARNING: %s\n' "$*" >&2; }
die() { printf 'rig-users: ERROR: %s\n' "$1" >&2; exit "${2:-1}"; }
usage() {
cat <<'EOF'
usage: rig users status
Per rig-managed user (the /etc/rig/users ledger): roles derived from the
groups the user is ACTUALLY in (rig-admin -> admin, rig -> rig, incus -> box),
the authorized_keys count, and whether the account is locked or active.
Reads the box only — no network, no writes. Run as root (shadow is read).
EOF
}
# --- args (validated before the root check, so errors are testable) ---------
while [ $# -gt 0 ]; do
case "$1" in
-h|--help) usage; exit 0 ;;
*) die "unknown flag: $1" 2 ;;
esac
done
[ "$(id -u)" -eq 0 ] || die "must run as root"
LEDGER=/etc/rig/users
if [ ! -r "$LEDGER" ]; then
log "no rig-managed users (no $LEDGER yet — rig users apply creates it)"
exit 0
fi
while IFS= read -r u; do
[ -n "$u" ] || continue
if ! id -u "$u" >/dev/null 2>&1; then
# In the ledger but off the box: someone deleted by hand what rig only
# ever locks. Say so rather than crash or silently skip.
warn "$u: in the ledger but not on the box (rig never deletes — removed by hand?)"
continue
fi
groups=" $(id -nG "$u") "
roles=""
case "$groups" in *" rig-admin "*) roles="admin" ;; esac
case "$groups" in *" rig "*) roles="${roles:+$roles,}rig" ;; esac
case "$groups" in *" incus "*) roles="${roles:+$roles,}box" ;; esac
[ -n "$roles" ] || roles="none"
home="$(getent passwd "$u" | cut -d: -f6)"
keys=0
if [ -r "$home/.ssh/authorized_keys" ]; then
keys="$(grep -c . "$home/.ssh/authorized_keys" || true)"
fi
# Field 2 of `passwd -S` is the lock flag; locked is apply's resting state
# for a user dropped from the file, so it is the fact worth surfacing.
state=active
case "$(passwd -S "$u" 2>/dev/null | awk '{print $2}')" in
L|LK) state=locked ;;
esac
log "$u roles=$roles keys=$keys $state"
done < "$LEDGER"