enhanced user management

This commit is contained in:
Thomas von Dein 2024-12-16 14:23:45 +01:00
parent ef31172e81
commit e6baefdbd5
6 changed files with 172 additions and 116 deletions

13
TODO.md
View File

@ -14,3 +14,16 @@ test the current setup: does it get configured and how does it limit
users? also check if new users belong to login class "jail" and test users? also check if new users belong to login class "jail" and test
their limits their limits
## devzat file busy still failing
https://github.com/BastilleBSD/bastille/issues/772
## ZFS quota
zfs set groupquota@bsdnixer=10MB zhcloud/home
zfs get groupquota@bsdnixer zhcloud/home
zfs groupspace zhcloud/home
zfs userspace zhcloud/home

View File

@ -62,12 +62,21 @@ defaults:
jailbase: /usr/local/bastille/jails jailbase: /usr/local/bastille/jails
jailgroups: jailgroups:
- name: first
state: present
id: 4000
- name: bsdnixer - name: bsdnixer
state: present state: present
jailusers: jailusers:
- name: first
state: present
id: 4000
- name: scip - name: scip
state: present state: present
- name: tuud
group: wheel
state: present
- name: tom - name: tom
state: present state: present

View File

@ -1,17 +1,18 @@
SERVICE devzat stop SERVICE devzat stop
CP usr /
SYSRC sendmail_enable=NONE SYSRC sendmail_enable=NONE
SYSRC tmpsize=500m SYSRC tmpsize=500m
SYSRC tmpmfs=AUTO SYSRC tmpmfs=AUTO
SYSRC clear_tmp_enable=YES SYSRC clear_tmp_enable=YES
SYSRC devzat_enable=YES SYSRC devzat_enable=YES
CMD if test -L /home; then rm /home; fi CMD if test -L /home; then rm /home; fi
CMD mkdir -p /home CMD mkdir -p /home
FSTAB /home home nullfs rw 0 0 FSTAB /home home nullfs rw 0 0
CMD install -d -o nobody -m 700 /home/devzat CMD install -d -o nobody -m 700 /home/devzat
CP usr /
SERVICE devzat start SERVICE devzat start

View File

@ -2,6 +2,7 @@
rootdir="" rootdir=""
group="" group=""
id=""
action="" action=""
usage() { usage() {
@ -16,7 +17,7 @@ run() {
} }
OPTIND=1 OPTIND=1
while getopts d:g:a: opt ; do while getopts d:g:a:i: opt ; do
case $opt in case $opt in
d) d)
rootdir="$OPTARG" rootdir="$OPTARG"
@ -24,6 +25,9 @@ while getopts d:g:a: opt ; do
g) g)
group="$OPTARG" group="$OPTARG"
;; ;;
i)
id="$OPTARG"
;;
a) a)
action="$OPTARG" action="$OPTARG"
;; ;;
@ -39,28 +43,35 @@ if test -z "$group" -o -z "$action"; then
usage usage
fi fi
root="" # we do it once for $rootdir and once on the host to have synchronous groups
for root in "$rootdir" ""; do
args=""
if test -n "$rootdir"; then if test -n "$root"; then
root="-R $rootdir" root="-R $root"
fi fi
case "$action" in if test -n "$id"; then
present) args="-g $id"
if pw $root group show "$group" > /dev/null 2>&1; then fi
if pw $root group show "$group" | grep -q LOCKED; then
echo "$group exists." case "$action" in
present)
if pw $root group show "$group" > /dev/null 2>&1; then
if pw $root group show "$group" | grep -q LOCKED; then
echo "$group exists."
fi
else
run pw $root group add "$group" $args
fi fi
else ;;
run pw $root group add "$group" absent)
fi if pw $root group show "$group" > /dev/null 2>&1; then
;; run pw $root group del "$group"
absent) fi
if pw $root group show "$group" > /dev/null 2>&1; then ;;
run pw $root group del "$group" *)
fi usage
;; ;;
*) esac
usage done
;;
esac

View File

@ -11,6 +11,7 @@ shell="/usr/local/bin/bash"
comment="" comment=""
loginclass="jail" loginclass="jail"
action="" action=""
id=""
usage() { usage() {
echo "Usage: $0 -u user [-h home] [-s shell] [-g groups] [-d rootdir] [-c comment] -a action" echo "Usage: $0 -u user [-h home] [-s shell] [-g groups] [-d rootdir] [-c comment] -a action"
@ -20,7 +21,7 @@ usage() {
getuid() { getuid() {
# resolve jail uid # resolve jail uid
root="$1" root="$1"
user="$2" user="$2"
pw $root show user "$user" -7 | cut -d: -f 3 pw $root show user "$user" -7 | cut -d: -f 3
@ -28,14 +29,14 @@ getuid() {
run() { run() {
# verbose exec # verbose exec
echo "$@" echo "$@"
"$@" "$@"
} }
# parse commandline flags # parse commandline flags
OPTIND=1 OPTIND=1
while getopts d:u:h:g:s:c:a: opt ; do while getopts d:u:h:g:s:c:a:i: opt ; do
case $opt in case $opt in
d) d)
rootdir="$OPTARG" rootdir="$OPTARG"
@ -43,6 +44,9 @@ while getopts d:u:h:g:s:c:a: opt ; do
u) u)
user="$OPTARG" user="$OPTARG"
;; ;;
i)
id="$OPTARG"
;;
h) h)
home="$OPTARG" home="$OPTARG"
;; ;;
@ -70,99 +74,117 @@ if test -z "$user" -o -z "$action"; then
usage usage
fi fi
# setup pw flags # we do it once for $rootdir and once on the host to have synchronous
args="" # users, however, host users will be locked, unless they are in group
root="" # wheel
for root in "$rootdir" ""; do
# setup pw flags
args=""
skel=""
if test -n "$rootdir"; then
root="-R $rootdir"
fi
if test -n "$groups"; then if test -n "$root"; then
args="-G $groups" root="-R $root"
fi if test -d "$root/etc/skel"; then
skel="-k /etc/skel"
if test -n "$home"; then
args="$args -d $home -k /etc/skel -m -M 700"
else
args="$args -d /home/$user -k /etc/skel -m -M 700"
fi
if test -n "$shell"; then
args="$args -s $shell"
else
args="$args -s /usr/local/bin/bash"
fi
if test -n "$comment"; then
args="$args -c $comment"
fi
if test -n "$loginclass"; then
args="$args -L $loginclass"
fi
# the horse shall work
case "$action" in
present)
if pw $root user show "$user" > /dev/null 2>&1; then
if pw $root user show "$user" | grep -q LOCKED; then
# user is present but locked
run pw unlock "$user"
else
echo "$user exists."
fi
else
# create user
run pw $root user add "$user" $args
fi fi
fi
if test -e "/usr/local/bastille/keys/$user" -a ! -e "/home/$user/.ssh/authorized_keys"; then if test -n "$groups"; then
# install ssh key args="-G $groups"
uid=$(getuid "$root" "$user") fi
run install -m 700 -o "$uid" -g "$uid" -d "/home/$user/.ssh"
run install -m 600 -o "$uid" -g "$uid" "/usr/local/bastille/keys/$user" "/home/$user/.ssh/authorized_keys"
# generate chat key, which is required so login to if test -n "$home"; then
# kobayashi, so that ssh-chat works even if the user does args="$args -d $home $skel -m -M 700"
# not have their own key yet. else
run ssh-keygen -t ed25519 -f /home/$user/.ssh/id_chat_kobayashi -P "" args="$args -d /home/$user $skel -m -M 700"
fi
( if test -n "$shell"; then
echo "The key id_chat_kobayashi exists so that you're able to reach" args="$args -s $shell"
echo "the kobayashi chat service. Once you have generated your own" else
echo "key, you can just delete it." args="$args -s /usr/local/bin/bash"
) > "/home/$user/.ssh/README" fi
if test -n "$comment"; then
args="$args -c $comment"
fi
if test -n "$loginclass"; then
args="$args -L $loginclass"
fi
if test -n "$id"; then
args="$args -u $id"
fi
# the horse shall work
case "$action" in
present)
if pw $root user show "$user" > /dev/null 2>&1; then
if pw $root user show "$user" | grep -q LOCKED; then
# user is present but locked
run pw $root unlock "$user"
else
echo "$user exists."
fi
else
# create user
run pw $root user add "$user" $args
# if we're running on host and the user is a regular jail user, lock them
if test -z "$root" -a "$groups" != "wheel"; then
run pw lock "$user"
fi
fi
if test -e "/usr/local/bastille/keys/$user" -a ! -e "/home/$user/.ssh/authorized_keys"; then
# install ssh key
uid=$(getuid "$root" "$user")
run install -m 700 -o "$uid" -g "$uid" -d "/home/$user/.ssh"
run install -m 600 -o "$uid" -g "$uid" "/usr/local/bastille/keys/$user" "/home/$user/.ssh/authorized_keys"
# generate chat key, which is required so login to
# kobayashi, so that ssh-chat works even if the user does
# not have their own key yet.
run ssh-keygen -t ed25519 -f /home/$user/.ssh/id_chat_kobayashi -P ""
if test ! -e "/home/$user/.ssh/config"; then
( (
echo "Host kobayashi" echo "The key id_chat_kobayashi exists so that you're able to reach"
echo " Port 2222" echo "the kobayashi chat service. Once you have generated your own"
echo " IdentityFile ~/.ssh/id_chat_kobayashi" echo "key, you can just delete it."
echo " StrictHostKeyChecking no" ) > "/home/$user/.ssh/README"
) > "/home/$user/.ssh/config"
if test ! -e "/home/$user/.ssh/config"; then
(
echo "Host kobayashi"
echo " Port 2222"
echo " IdentityFile ~/.ssh/id_chat_kobayashi"
echo " StrictHostKeyChecking no"
) > "/home/$user/.ssh/config"
fi
run chown "$uid:$uid" /home/$user/.ssh/*
fi fi
;;
run chown "$uid:$uid" /home/$user/.ssh/* absent)
fi if pw $root user show "$user" > /dev/null 2>&1; then
;; # get rid
absent) run pw $root user del "$user"
if pw $root user show "$user" > /dev/null 2>&1; then
# get rid
run pw $root user del "$user"
fi
;;
locked)
if pw $root user show "$user" > /dev/null 2>&1; then
if pw $root user show "$user" | grep -q LOCKED; then
echo "$user is already locked."
else
# lock'em out
run pw lock "$user"
fi fi
fi ;;
;; locked)
*) if pw $root user show "$user" > /dev/null 2>&1; then
usage if pw $root user show "$user" | grep -q LOCKED; then
;; echo "$user is already locked."
esac else
# lock'em out
run pw $root lock "$user"
fi
fi
;;
*)
usage
;;
esac
done

View File

@ -97,7 +97,7 @@
# create our own group[s] # create our own group[s]
- name: Manage groups - name: Manage groups
loop: "{{ jailgroups }}" loop: "{{ jailgroups }}"
ansible.builtin.script: "bin/group.sh -g {{ item.name }} -a {{ item.state }} -d /usr/local/bastille/jails/{{ role_name }}/root" ansible.builtin.script: "bin/group.sh -g {{ item.name }} -a {{ item.state }} -i '{{ item.id | default(None) }}' -d /usr/local/bastille/jails/{{ role_name }}/root"
# The normal ansible user module can't be used here, because we're # The normal ansible user module can't be used here, because we're
# talking about jail users here. I tried to patch the module to # talking about jail users here. I tried to patch the module to
@ -109,7 +109,7 @@
# well. # well.
- name: Manage users - name: Manage users
loop: "{{ jailusers }}" loop: "{{ jailusers }}"
ansible.builtin.script: "bin/user.sh -u {{ item.name }} -g '{{ item.groups | default(defaults.group) }}' -c {{ role_name }}-user -a {{ item.state }} -d {{ defaults.jailbase }}/{{ role_name }}/root" ansible.builtin.script: "bin/user.sh -u {{ item.name }} -g '{{ item.groups | default(defaults.group) }}' -c {{ role_name }}-user -a {{ item.state }} -i '{{ item.id | default(None) }}' -d {{ defaults.jailbase }}/{{ role_name }}/root"
- name: add dns entry for jail host - name: add dns entry for jail host
community.dns.hetzner_dns_record: community.dns.hetzner_dns_record: