Implement home exam server.

This commit is contained in:
Andreas B. Mundt 2022-10-22 16:44:05 +02:00
parent 147fddc772
commit f4f0795e80
10 changed files with 248 additions and 0 deletions

17
fvs-homex-server.yml Normal file
View file

@ -0,0 +1,17 @@
## This playbook deploys a FvS homex server machine.
---
- name: apply configuration to the homex server
hosts: all
remote_user: ansible
become: yes
vars:
extra_pkgs:
- vim
- systemd-journal-remote
- python3-ldap
extra_pkgs_bpo: [ ]
roles:
- up2date_debian
- fvs-sssd
- exam_homes

View file

@ -0,0 +1,23 @@
#!/usr/bin/bash
#
# Backup and remove all student home directories.
set -eu
HDIRS='/home/'
DIRS=()
for DIR in $(find $HDIRS -maxdepth 1 -mindepth 1 -type d) ; do
H="$(basename $DIR)"
if [[ "$H" =~ ^L_ ]] || [[ "$H" =~ ansible ]] ; then
echo "Skipping home of '$H'."
continue
fi
DIRS+=("$DIR")
done
[[ "${#DIRS[@]}" -eq 0 ]] && exit 0
tar czf "/var/backups/homes_$(date -I).tar.gz" -C "$HDIRS" \
-P --transform="s%$HDIRS%%" "${DIRS[@]}"
rm -rf "${DIRS[@]}"
echo "Archived and removed: ${DIRS[@]}"

View file

@ -0,0 +1,6 @@
[Unit]
Description=Archive students' home directories
[Service]
Type=simple
ExecStart=/usr/local/sbin/archive-homes

View file

@ -0,0 +1,11 @@
[Unit]
Description=Run archive script every night
[Timer]
OnCalendar=daily
Persistent=true
AccuracySec=3h
RandomizedDelaySec=3h
[Install]
WantedBy=timers.target

View file

@ -0,0 +1,26 @@
#!/usr/bin/bash
#
# Copy content to all student home download directories.
set -eu
if [[ -z $@ ]] ; then
echo "Argument missing!"
exit 1
fi
HDIRS='/home/'
DIRS=()
for DIR in $(find $HDIRS -maxdepth 1 -mindepth 1 -type d) ; do
H="$(basename $DIR)"
if [[ "$H" =~ ^L_ ]] || [[ "$H" =~ ansible ]] ; then
echo "Skipping home of '$H'."
continue
fi
DIRS+=("$DIR")
done
[[ "${#DIRS[@]}" -eq 0 ]] && exit 0
for DIR in "${DIRS[@]}" ; do
cp -va $@ "$DIR/Downloads/"
done

View file

@ -0,0 +1,75 @@
#!/usr/bin/python3
import ldap
from os import scandir
HOME = '/home'
BASE = 'ou=schueler,ou=Benutzer,ou=fvs,ou=SCHULEN,o=ml3'
#BASE = 'ou=Benutzer,ou=fvs,ou=SCHULEN,o=ml3'
LDAP = 'ldap://ldap.steinbeisschule-reutlingen.de'
def fetch_ou(uid):
l = ldap.initialize(LDAP)
f = '(uid=' + uid + ')'
try:
return l.search_s(BASE,ldap.SCOPE_SUBTREE,f,['ou'])[0][1]['ou'][0].decode('utf-8')
except:
return None
def fetch_uids(crs):
uids = []
l = ldap.initialize(LDAP)
# if 'Abgang' in crs:
# b = 'ou=Abgang,' + BASE
# else:
# b = 'ou=' + crs + ',' + BASE
b = BASE
r = l.search_s(b,ldap.SCOPE_SUBTREE,'(ou=' + crs + ')',['uid'])
for dn,entry in r:
if entry != {}:
uids.append(entry['uid'][0].decode('utf-8'))
return uids
def assign_course(user, crs_uids, home):
c = fetch_ou(user)
print('Needed to fetch new course', c, 'for', user)
if c:
crs_uids[c] = fetch_uids(c)
home[user] = c
else:
print('No course for', user , 'found!')
if __name__ == '__main__':
home = {}
with scandir(HOME) as it:
for entry in it:
if entry.is_dir() and entry.name != 'lost+found':
home[entry.name] = ''
crs_uids = {}
for user in home:
if crs_uids == {}:
assign_course(user, crs_uids, home)
continue
for k in crs_uids.keys():
if user in crs_uids[k]:
home[user] = k
break
else:
assign_course(user, crs_uids, home)
for usr in home:
print(usr, home[usr])
for crs in crs_uids.keys():
print(usr, home[usr])
for k, v in sorted(crs_uids.items()):
print(k, sorted(v))
for item in sorted(v):
try:
print(item, home[item])
except:
print('No home for', item, 'found.')

View file

@ -0,0 +1,23 @@
#!/usr/bin/bash
#
# Backup and remove all student home directories.
set -eu
HDIRS='/home/'
DIRS=()
for DIR in $(find $HDIRS -maxdepth 1 -mindepth 1 -type d) ; do
H="$(basename $DIR)"
if [[ "$H" =~ ^L_ ]] || [[ "$H" =~ ansible ]] ; then
echo "Skipping home of '$H'."
continue
fi
DIRS+=("$DIR")
done
[[ "${#DIRS[@]}" -eq 0 ]] && exit 0
AR="homes_$(date -I).tar.gz"
tar czf "$AR" -C "$HDIRS" --exclude='.[^/]*' \
-P --transform="s%$HDIRS%%" "${DIRS[@]}"
echo "Create archive $AR containing: ${DIRS[@]}"

View file

@ -0,0 +1,12 @@
#!/usr/bin/bash
#
# Prepare Downloads directory.
set -eu
HDIRS='/home/'
if [[ ! -d "$HDIRS/$PAM_USER/Downloads" ]] && [[ ! "$PAM_USER" =~ ^L_ ]] && \
[[ ! "$PAM_USER" =~ ansible ]] ; then
mkdir --mode=0777 "$HDIRS/$PAM_USER/Downloads"
fi

View file

@ -0,0 +1,6 @@
- name: enable archive-homes.timer
systemd:
name: archive-homes.timer
state: started
enabled: true
listen: enable archive-homes.timer

View file

@ -0,0 +1,49 @@
- name: enable pam_mkhomedir.so and pam_exec.so
lineinfile:
dest: /etc/pam.d/common-session
line: "{{ item }}"
insertbefore: "# end of pam-auth-update config"
loop:
- "session optional pam_mkhomedir.so umask=0022"
- "session optional pam_exec.so /usr/local/sbin/mkDownloads"
- name: deploy mkDownloads script
copy:
src: mkDownloads
dest: /usr/local/sbin/mkDownloads
mode: 0755
# https://serverfault.com/questions/354615/allow-sftp-but-disallow-ssh
- name: only allow sftp for most users
blockinfile:
dest: /etc/ssh/sshd_config.d/local.conf
create: true
block: |
Match User !L_*,!ansible,*
PermitTTY no
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
ForceCommand internal-sftp
- name: deploy archive home script
copy:
src: archive-homes
dest: /usr/local/sbin/archive-homes
mode: 0750
- name: deploy archive home script service and timer
copy:
src: "{{ item }}"
dest: /etc/systemd/system/{{ item }}
mode: 0655
loop:
- archive-homes.service
- archive-homes.timer
notify: enable archive-homes.timer
- name: deploy examode helper
copy:
src: examode.py
dest: /usr/local/bin/examode.py
mode: 0755