scripts/baker/bin/baker

173 lines
3.5 KiB
Bash
Executable File

#!/bin/bash
# baker: user administration for breadpunk.club
# by breadw
set -euo pipefail
usage()
{
case "$1" in
[0-9]*) ec="$1"; shift ;;
*) ec=0 ;;
esac
(( $# > 0 )) && printf '!! baker: %s\n' "$*"
sed -n '2s/^#* *//' "$0" >&2
echo >&2
cat <<-ENDUSAGE >&2
usage: baker COMMAND [OPTIONS] USER
COMMANDs:
add/hire add a new user
rm/fire remove a user
promote add to groups
demote remove from groups
help show help - use 'baker help COMMAND' for specifics
ENDUSAGE
exit "$ec"
}
die()
{
ec="$1"; shift
echo "!! ${FUNCNAME[1]}: $*" >&2
exit "$ec"
}
log() { printf '%s...' "$*" >&2; }
ok() { printf ' %s\n' "Done" >&2; }
bakeradd()
{
# add a baker
# baker add -u USER -n NAME -k KEYFILE [-G GROUPS] [-s SHELL]
# a wrapper around adduser
user=
name=
keyfile=
groups=bakers
shell=/bin/bash
while getopts s:n:G:k:u: opt; do
case "$opt" in
s) shell="$OPTARG" ;;
n) name="$OPTARG" ;;
G) groups="$groups${groups:+,}$OPTARG" ;;
k) keyfile="$OPTARG" ;;
u) user="$OPTARG" ;;
\?) die 1 ;;
*) die 1 "Unknown option -$opt" ;;
esac
done
[ -z "$user" ] && die "Need a user"
[ -z "$name" ] && die "Need a name"
[ -z "$keyfile" ] && die "Need a keyfile"
log "Adding user $user"
adduser \
--shell="$shell" \
--gecos="$name" \
--disabled-password "$user" &&
ok
log "Adding user $user to groups $groups"
usermod -a -G "$groups" "$user" && ok
log "Setting up ~/.ssh for $user"
{
sudo --user="$user" mkdir "/home/$user/.ssh"
cat "$keyfile" >> "/home/$user/.ssh/authorized_keys2"
chown "$user:$user" "/home/$user/.ssh/authorized_keys2"
chmod 700 "/home/$user/.ssh"
chmod 644 "/home/$user/.ssh/authorized_keys2"
} && ok
log "Adding gemini userdir for $user"
{
mkdir "/var/gemini/bakers/$user"
chown "$user:$user" "/var/gemini/bakers/$user"
chmod 755 "/var/gemini/bakers/$user"
} && ok
echo "$user added."
}
bakerremove()
{
# remove a baker
# baker rm USER
user="$1"
log "Locking $user's account"
passwd -l "$user" && ok
log "Killing $user's processes"
pkill -KILL -u "$user" && ok
log "Removing $user's crontab"
crontab -r -u "$user" && ok
log "Removing user $user"
# TODO: look into deluser.conf
deluser --remove-home "$user" --backup-to /bread/fired/ && ok
echo "$user removed."
}
bakerpromote()
{
# add a baker to groups
# baker promote USER GROUP...
user="$1"; shift
groups=
for group; do
groups="$groups${groups:+,}$group"
done
log "Adding $user to groups: $groups"
usermod -a -G "$groups" "$user" && ok
}
bakerdemote()
{
# remove a baker from groups
# baker demote USER GROUP...
user="$1"
_sed=( sed )
for group; do
if (groups "$user" | grep "$group"); then
log "Removing $user from $group"
_sed+=( -e "/$group/d" ) && ok
else
echo "$user is not a member of $group"
fi
done
groups="$(getent group|grep "$user"|cut -d: -f1|"${_sed[@]}"|tr '\n' ',')"
log "Applying changes"
usermod -G "${groups%,}" "$user" && ok
}
main()
{ # entry point
(( $# == 0 )) && usage 1
cmd="$1"; shift || die "Not enough arguments for \"$cmd\""
case "$cmd" in
help|h|usage|-h|--help)
(( $# == 0 )) && usage 0
grep -q "baker$1" "$0" && {
echo "baker $1"
awk "BEGIN{FS=\"\\n\";RS=\"\";}/baker$1/{print}" "$0" |
sed -n 's/# //p'
exit
} || die "No command \"$1\""
;;
add|hire)
cmd=add ;;
remove|rm|fire)
cmd=remove ;;
promote)
cmd=promote ;;
demote)
cmd=demote ;;
esac
(( $(id -u) == 0 )) || die "Script must be run as root"
"baker$cmd" "$@"
}
main "$@"