From 295a111cec1397229731f2ab3393117e75edeaf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4r?= Date: Fri, 15 Jul 2022 11:59:26 +0200 Subject: [PATCH] Initial commit --- .gitignore | 6 + config/class/10-base-classes | 21 + config/class/20-hwdetect.sh | 36 + config/class/41-warning.sh | 32 + config/class/50-host-classes | 8 + config/class/55-classes | 10 + config/class/60-misc | 11 + config/class/85-efi-classes | 14 + config/class/CONTESTANT.var | 1 + config/class/DEBIAN.var | 26 + config/class/FAIBASE.var | 24 + config/class/TRAINING.var | 3 + config/debconf/DEBIAN | 10 + config/debconf/PARTICIPANT | 2 + config/disk_config/FAIBASE | 9 + config/disk_config/FAIBASE_EFI | 10 + config/disk_config/LVM | 15 + config/disk_config/LVM_EFI | 16 + .../etc/apt/apt.conf.d/force_confdef/DEBIAN | 5 + config/files/etc/apt/sources.list/DEBIAN | 3 + config/files/etc/motd/FAIBASE | 0 config/hooks/debconf.IMAGE | 45 ++ config/hooks/instsoft.DEBIAN | 25 + config/hooks/savelog.LAST.sh | 222 +++++++ config/hooks/setup.DEFAULT.sh | 7 + config/hooks/updatebase.DEBIAN | 16 + config/hooks/updatebase.PARTICIPANT | 4 + config/package_config/CONTESTANT | 7 + config/package_config/DEBIAN | 54 ++ config/package_config/DEBIAN.gpg | Bin 0 -> 2824 bytes config/package_config/GNOME | 8 + config/package_config/PARTICIPANT | 15 + config/package_config/STANDARD | 37 ++ config/package_config/TRAINING | 2 + config/package_config/XORG | 12 + config/scripts/CONTESTANT/10-config | 30 + config/scripts/DEBIAN/10-rootpw | 12 + config/scripts/DEBIAN/20-capabilities | 22 + config/scripts/DEBIAN/30-interface | 118 ++++ config/scripts/DEBIAN/40-misc | 51 ++ config/scripts/FAIBASE/10-misc | 38 ++ config/scripts/FAIBASE/20-removable_media | 25 + config/scripts/GRUB_EFI/10-setup | 68 ++ config/scripts/GRUB_PC/10-setup | 84 +++ config/scripts/LAST/50-misc | 103 +++ config/scripts/PARTICIPANT/10-config | 56 ++ config/scripts/TRAINING/10-config | 8 + config/setup-bern.sh | 41 ++ .../etc/dconf/db/local.d/00-disable-idle | 3 + .../db/local.d/00-disable-screensaver-lock | 3 + .../etc/dconf/db/local.d/00-disable-suspend | 4 + .../etc/dconf/db/local.d/00-disallow-updates | 3 + .../db/local.d/00-gnome-shell-extensions | 2 + .../etc/dconf/db/local.d/00-lock-screen | 3 + .../etc/firefox/policies/policies.json | 23 + config/simplefiles/CONTESTANT/etc/hosts | 33 + .../simplefiles/CONTESTANT/etc/nftables.conf | 45 ++ .../localauthority/20-org.d/rules.pkla | 11 + .../systemd/timesyncd.conf.d/ntp-server.conf | 3 + .../CONTESTANT/root/.ssh/authorized_keys | 0 .../usr/local/bin/install-client-cert | 49 ++ .../usr/share/chromium/initial_bookmarks.html | 10 + .../contest-lock@soi.ch/extension.js | 424 ++++++++++++ .../contest-lock@soi.ch/metadata.json | 8 + .../contest-lock@soi.ch/stylesheet-always.css | 24 + .../user-indicator@soi.ch/extension.js | 39 ++ .../user-indicator@soi.ch/metadata.json | 8 + .../user-indicator@soi.ch/stylesheet.css | 3 + .../etc/apt/sources.list.d/atom.list | 1 + .../etc/apt/sources.list.d/sublime-text.list | 1 + .../etc/apt/sources.list.d/vscode.list | 1 + .../etc/dconf/db/local.d/00-background | 5 + .../etc/dconf/db/local.d/00-favorite-apps | 2 + .../etc/dconf/db/local.d/00-input-sources | 5 + .../PARTICIPANT/etc/dconf/profile/user | 2 + .../etc/ssh/sshd_config.d/sshd.conf | 2 + .../local/share/backgrounds/wallpaper-soi.svg | 26 + .../share/keyrings/atom-archive-keyring.gpg | Bin 0 -> 2826 bytes .../keyrings/microsoft-archive-keyring.gpg | Bin 0 -> 641 bytes .../keyrings/sublimehq-archive-keyring.gpg | Bin 0 -> 2758 bytes readme.md | 629 ++++++++++++++++++ tools/assign-user.sh | 20 + tools/backup-create.sh | 27 + tools/contest-lock.json | 5 + tools/create-certs.sh | 58 ++ tools/hostlist | 19 + tools/hostlist-bern | 21 + tools/hostlist-test | 1 + tools/usernames.csv | 2 + 89 files changed, 2897 insertions(+) create mode 100644 .gitignore create mode 100755 config/class/10-base-classes create mode 100755 config/class/20-hwdetect.sh create mode 100755 config/class/41-warning.sh create mode 100755 config/class/50-host-classes create mode 100755 config/class/55-classes create mode 100755 config/class/60-misc create mode 100755 config/class/85-efi-classes create mode 100644 config/class/CONTESTANT.var create mode 100644 config/class/DEBIAN.var create mode 100644 config/class/FAIBASE.var create mode 100644 config/class/TRAINING.var create mode 100644 config/debconf/DEBIAN create mode 100644 config/debconf/PARTICIPANT create mode 100644 config/disk_config/FAIBASE create mode 100644 config/disk_config/FAIBASE_EFI create mode 100644 config/disk_config/LVM create mode 100644 config/disk_config/LVM_EFI create mode 100644 config/files/etc/apt/apt.conf.d/force_confdef/DEBIAN create mode 100644 config/files/etc/apt/sources.list/DEBIAN create mode 100644 config/files/etc/motd/FAIBASE create mode 100755 config/hooks/debconf.IMAGE create mode 100755 config/hooks/instsoft.DEBIAN create mode 100755 config/hooks/savelog.LAST.sh create mode 100755 config/hooks/setup.DEFAULT.sh create mode 100755 config/hooks/updatebase.DEBIAN create mode 100755 config/hooks/updatebase.PARTICIPANT create mode 100644 config/package_config/CONTESTANT create mode 100644 config/package_config/DEBIAN create mode 100644 config/package_config/DEBIAN.gpg create mode 100644 config/package_config/GNOME create mode 100644 config/package_config/PARTICIPANT create mode 100644 config/package_config/STANDARD create mode 100644 config/package_config/TRAINING create mode 100644 config/package_config/XORG create mode 100755 config/scripts/CONTESTANT/10-config create mode 100755 config/scripts/DEBIAN/10-rootpw create mode 100755 config/scripts/DEBIAN/20-capabilities create mode 100755 config/scripts/DEBIAN/30-interface create mode 100755 config/scripts/DEBIAN/40-misc create mode 100755 config/scripts/FAIBASE/10-misc create mode 100755 config/scripts/FAIBASE/20-removable_media create mode 100755 config/scripts/GRUB_EFI/10-setup create mode 100755 config/scripts/GRUB_PC/10-setup create mode 100755 config/scripts/LAST/50-misc create mode 100755 config/scripts/PARTICIPANT/10-config create mode 100755 config/scripts/TRAINING/10-config create mode 100755 config/setup-bern.sh create mode 100644 config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-idle create mode 100644 config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-screensaver-lock create mode 100644 config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-suspend create mode 100644 config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disallow-updates create mode 100644 config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-gnome-shell-extensions create mode 100644 config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-lock-screen create mode 100644 config/simplefiles/CONTESTANT/etc/firefox/policies/policies.json create mode 100644 config/simplefiles/CONTESTANT/etc/hosts create mode 100755 config/simplefiles/CONTESTANT/etc/nftables.conf create mode 100644 config/simplefiles/CONTESTANT/etc/polkit-1/localauthority/20-org.d/rules.pkla create mode 100644 config/simplefiles/CONTESTANT/etc/systemd/timesyncd.conf.d/ntp-server.conf create mode 100644 config/simplefiles/CONTESTANT/root/.ssh/authorized_keys create mode 100755 config/simplefiles/CONTESTANT/usr/local/bin/install-client-cert create mode 100644 config/simplefiles/CONTESTANT/usr/share/chromium/initial_bookmarks.html create mode 100644 config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/extension.js create mode 100644 config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/metadata.json create mode 100644 config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/stylesheet-always.css create mode 100644 config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/extension.js create mode 100644 config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/metadata.json create mode 100644 config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/stylesheet.css create mode 100644 config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/atom.list create mode 100644 config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/sublime-text.list create mode 100644 config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/vscode.list create mode 100644 config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-background create mode 100644 config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-favorite-apps create mode 100644 config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-input-sources create mode 100644 config/simplefiles/PARTICIPANT/etc/dconf/profile/user create mode 100644 config/simplefiles/PARTICIPANT/etc/ssh/sshd_config.d/sshd.conf create mode 100644 config/simplefiles/PARTICIPANT/usr/local/share/backgrounds/wallpaper-soi.svg create mode 100644 config/simplefiles/PARTICIPANT/usr/share/keyrings/atom-archive-keyring.gpg create mode 100644 config/simplefiles/PARTICIPANT/usr/share/keyrings/microsoft-archive-keyring.gpg create mode 100644 config/simplefiles/PARTICIPANT/usr/share/keyrings/sublimehq-archive-keyring.gpg create mode 100644 readme.md create mode 100755 tools/assign-user.sh create mode 100755 tools/backup-create.sh create mode 100644 tools/contest-lock.json create mode 100755 tools/create-certs.sh create mode 100644 tools/hostlist create mode 100644 tools/hostlist-bern create mode 100644 tools/hostlist-test create mode 100644 tools/usernames.csv diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24a7ff6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +config/downloads/ +config/simplefiles/CONTESTANT/opt/ + +tools/output/ +tools/backups-* +tools/certs/ diff --git a/config/class/10-base-classes b/config/class/10-base-classes new file mode 100755 index 0000000..d312a50 --- /dev/null +++ b/config/class/10-base-classes @@ -0,0 +1,21 @@ +#! /bin/bash + +# do only execute if this is called on the client being installed. Do not use during fai-diskimage +if [ X$FAI_ACTION = Xinstall -a $do_init_tasks -eq 0 ]; then + exit 0 +fi + +# Echo architecture and OS name in uppercase. Do NOT remove these two lines. +uname -s | tr '[:lower:]' '[:upper:]' +command -v dpkg >&/dev/null && dpkg --print-architecture | tr a-z A-Z + +# determin if we are a DHCP client or not +# count the : chars in the argument of ip= +n="${ip//[^:]}" +if [[ $ip =~ ^(on|any|dhcp)$ ]]; then + echo DHCPC +elif [ ${#n} -lt 6 ]; then + echo DHCPC +fi + +exit 0 diff --git a/config/class/20-hwdetect.sh b/config/class/20-hwdetect.sh new file mode 100755 index 0000000..706f9e8 --- /dev/null +++ b/config/class/20-hwdetect.sh @@ -0,0 +1,36 @@ +#! /bin/bash + +# (c) Thomas Lange, 2002-2013, lange@informatik.uni-koeln.de + +# NOTE: Files named *.sh will be evaluated, but their output ignored. + +[ $do_init_tasks -eq 1 ] || return 0 # Do only execute when doing install + +echo 0 > /proc/sys/kernel/printk + +#kernelmodules= +# here, you can load modules depending on the kernel version +case $(uname -r) in + 2.6*) kernelmodules="$kernelmodules mptspi dm-mod md-mod aes dm-crypt" ;; + [3456]*) kernelmodules="$kernelmodules mptspi dm-mod md-mod aes dm-crypt" ;; +esac + +for mod in $kernelmodules; do + [ X$verbose = X1 ] && echo Loading kernel module $mod + modprobe -a $mod 1>/dev/null 2>&1 +done + +# show the basic information about the network interface +ip -br li show up|egrep -v ^lo; ip -br a show up|egrep -v ^lo + +echo $printk > /proc/sys/kernel/printk + +odisklist=$disklist +set_disk_info # recalculate list of available disks +if [ "$disklist" != "$odisklist" ]; then + echo New disklist: $disklist + echo disklist=\"$disklist\" >> $LOGDIR/additional.var +fi + +save_dmesg # save new boot messages (from loading modules) + diff --git a/config/class/41-warning.sh b/config/class/41-warning.sh new file mode 100755 index 0000000..04af016 --- /dev/null +++ b/config/class/41-warning.sh @@ -0,0 +1,32 @@ +#! /bin/bash + +if [ X$FAI_ACTION = Xinstall -o X$FAI_ACTION = X ]; then + : +else + return 0 +fi +if [ X$action = Xdirinstall ]; then + return 0 +fi + +grep -q INSTALL $LOGDIR/FAI_CLASSES || return 0 +[ "$flag_menu" ] || return 0 + +out=$(tty) +red=$(mktemp) +echo 'screen_color = (CYAN,RED,ON)' > $red + +DIALOGRC=$red dialog --colors --clear --aspect 6 --title "FAI - Fully Automatic Installation" --trim \ + --msgbox "\n\n If you continue, \n all your data on the disk \n \n|\Zr\Z1 WILL BE DESTROYED \Z0\Zn|\n\n" 0 0 1>$out + +# stop on any error, or if ESC was hit +if [ $? -ne 0 ]; then + task_error 999 +fi + +rm $red +unset red + +# MENU DISABLED +unset flag_menu +FAI_ACTION=install diff --git a/config/class/50-host-classes b/config/class/50-host-classes new file mode 100755 index 0000000..f5d0212 --- /dev/null +++ b/config/class/50-host-classes @@ -0,0 +1,8 @@ +#! /bin/bash + +# assign classes to hosts based on their hostname + +# do not use this if a menu will be presented +[ "$flag_menu" ] && exit 0 + +echo "FAIBASE DEBIAN XORG GNOME PARTICIPANT CONTESTANT" diff --git a/config/class/55-classes b/config/class/55-classes new file mode 100755 index 0000000..b5b5206 --- /dev/null +++ b/config/class/55-classes @@ -0,0 +1,10 @@ +#! /bin/bash + +[ "$cmdlineclasses" ] || exit 0 + +# define the classes given on the cmdline (using -c) +# Note: In the FAI example config, this script has very low priority, but for +# me it make more sense to make it higher priority than the host classes. +echo $cmdlineclasses + +exit 0 diff --git a/config/class/60-misc b/config/class/60-misc new file mode 100755 index 0000000..1c3b4fd --- /dev/null +++ b/config/class/60-misc @@ -0,0 +1,11 @@ +#! /bin/bash + +ifclass -o CENTOS SLC && exit 0 + +ifclass -o GRUB_PC GRUB_EFI && exit 0 + +if [ -d /sys/firmware/efi ]; then + echo GRUB_EFI +elif ifclass -o I386 AMD64 ; then + echo GRUB_PC +fi diff --git a/config/class/85-efi-classes b/config/class/85-efi-classes new file mode 100755 index 0000000..f8106d0 --- /dev/null +++ b/config/class/85-efi-classes @@ -0,0 +1,14 @@ +#! /bin/bash + +# define classes for disk_config in an EFI enironment + +if [ ! -d /sys/firmware/efi ] || ifclass GRUB_PC; then + exit 0 +fi + +for c in LVM FAIBASE; do + if ifclass $c; then + echo ${c}_EFI + break + fi +done diff --git a/config/class/CONTESTANT.var b/config/class/CONTESTANT.var new file mode 100644 index 0000000..76dd8be --- /dev/null +++ b/config/class/CONTESTANT.var @@ -0,0 +1 @@ +PARTICIPANT_USER_NAME=contestant diff --git a/config/class/DEBIAN.var b/config/class/DEBIAN.var new file mode 100644 index 0000000..a1f9cc2 --- /dev/null +++ b/config/class/DEBIAN.var @@ -0,0 +1,26 @@ +release=bullseye +apt_cdn=http://deb.debian.org +security_cdn=http://security.debian.org + +# since bullseye Debian changed the suite name for security +if [ $release = buster ]; then + secsuite=buster/updates +else + secsuite=$release-security +fi + +CONSOLEFONT= +KEYMAP=us-latin1 + +# MODULESLIST contains modules that will be loaded by the new system, +# not during installation these modules will be written to /etc/modules +# If you need a module during installation, add it to $kernelmodules +# in 20-hwdetect.sh. +MODULESLIST="usbhid psmouse" + +# if you have enough RAM (>2GB) you may want to enable this line. It +# also puts /var/cache into a ramdisk. +#FAI_RAMDISKS="$target/var/lib/dpkg $target/var/cache" + +# if you want to use the faiserver as APT proxy +APTPROXY=http://10.0.0.9:3142 diff --git a/config/class/FAIBASE.var b/config/class/FAIBASE.var new file mode 100644 index 0000000..2df3e11 --- /dev/null +++ b/config/class/FAIBASE.var @@ -0,0 +1,24 @@ +# default values for installation. You can override them in your *.var files + +# disallow installation of packages from unsigned repositories +FAI_ALLOW_UNSIGNED=0 + +# Set UTC=yes if your system clock is set to UTC (GMT), and UTC=no if not. +UTC=yes +TIMEZONE=Europe/Zurich + +# the hash of the root password for the new installed linux system +ROOTPW='' + +# errors in tasks greater than this value will cause the installation to stop +STOP_ON_ERROR=700 + +# set parameter for install_packages(8) +MAXPACKAGES=800 + +PARTICIPANT_USER_NAME=soi +PARTICIPANT_USER_PW='$y$j9T$h5VhMd4KkdmbxdZD1gO0N/$1hvwZgO8pQw13Xd6jaNXbtkbqVOC4W/ia/KXOcCGYvB' + +if [ $FAI_ACTION = "install" ]; then + LOGUSER=fai +fi diff --git a/config/class/TRAINING.var b/config/class/TRAINING.var new file mode 100644 index 0000000..ded9b43 --- /dev/null +++ b/config/class/TRAINING.var @@ -0,0 +1,3 @@ +SUPER_USER_NAME=superstofl +SUPER_USER_DISPLAYNAME="Admin" +SUPER_USER_PW='' diff --git a/config/debconf/DEBIAN b/config/debconf/DEBIAN new file mode 100644 index 0000000..f245a85 --- /dev/null +++ b/config/debconf/DEBIAN @@ -0,0 +1,10 @@ +exim4-config exim4/dc_eximconfig_configtype select local delivery only; not on a network +locales locales/default_environment_locale select en_US.UTF-8 +locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8 +keyboard-configuration keyboard-configuration/xkb-keymap select +keyboard-configuration keyboard-configuration/model select Generic 105-key PC +keyboard-configuration keyboard-configuration/modelcode string pc105 +keyboard-configuration keyboard-configuration/layoutcode string ch +keyboard-configuration keyboard-configuration/layout select Switzerland +keyboard-configuration keyboard-configuration/variant select Switzerland +keyboard-configuration keyboard-configuration/optionscode string diff --git a/config/debconf/PARTICIPANT b/config/debconf/PARTICIPANT new file mode 100644 index 0000000..2c99fa1 --- /dev/null +++ b/config/debconf/PARTICIPANT @@ -0,0 +1,2 @@ +locales locales/default_environment_locale select en_US.UTF-8 +locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8, de_CH.UTF-8 UTF-8, fr_CH.UTF-8 UTF-8, it_CH.UTF-8 UTF-8 diff --git a/config/disk_config/FAIBASE b/config/disk_config/FAIBASE new file mode 100644 index 0000000..0c66cbc --- /dev/null +++ b/config/disk_config/FAIBASE @@ -0,0 +1,9 @@ +# example of new config file for setup-storage +# +# + +disk_config disk1 disklabel:msdos bootable:1 fstabkey:uuid + +primary / 2G-50G ext4 rw,noatime,errors=remount-ro +logical swap 200-10G swap sw +logical /home 100- ext4 rw,noatime,nosuid,nodev createopts="-L home -m 1" tuneopts="-c 0 -i 0" diff --git a/config/disk_config/FAIBASE_EFI b/config/disk_config/FAIBASE_EFI new file mode 100644 index 0000000..8ff0e4b --- /dev/null +++ b/config/disk_config/FAIBASE_EFI @@ -0,0 +1,10 @@ +# example of new config file for setup-storage +# +# + +disk_config disk1 disklabel:gpt bootable:1 fstabkey:uuid + +primary /boot/efi 512M vfat rw +primary / 2G-50G ext4 rw,noatime,errors=remount-ro +primary swap 200-10G swap sw +primary /home 100- ext4 rw,noatime,nosuid,nodev createopts="-L home -m 1" tuneopts="-c 0 -i 0" diff --git a/config/disk_config/LVM b/config/disk_config/LVM new file mode 100644 index 0000000..868970a --- /dev/null +++ b/config/disk_config/LVM @@ -0,0 +1,15 @@ +# + +# entire disk with LVM, separate /home + +disk_config disk1 fstabkey:uuid align-at:1M + +primary /boot 200 ext2 rw,noatime +primary - 4G- - - + +disk_config lvm + +vg vg1 disk1.2 +vg1-root / 3G-50G ext4 noatime,rw +vg1-swap swap 200-4G swap sw +vg1-home /home 600- ext4 noatime,nosuid,nodev,rw diff --git a/config/disk_config/LVM_EFI b/config/disk_config/LVM_EFI new file mode 100644 index 0000000..b2609a5 --- /dev/null +++ b/config/disk_config/LVM_EFI @@ -0,0 +1,16 @@ +# + +# entire disk with LVM, separate /home + +disk_config disk1 disklabel:gpt fstabkey:uuid align-at:1M + +primary /boot/efi 512M vfat rw +primary /boot 200 ext2 rw,noatime +primary - 4G- - - + +disk_config lvm + +vg vg1 disk1.3 +vg1-root / 3G-50G ext4 noatime,rw +vg1-swap swap 200-4G swap sw +vg1-home /home 600- ext4 noatime,nosuid,nodev,rw diff --git a/config/files/etc/apt/apt.conf.d/force_confdef/DEBIAN b/config/files/etc/apt/apt.conf.d/force_confdef/DEBIAN new file mode 100644 index 0000000..deb7948 --- /dev/null +++ b/config/files/etc/apt/apt.conf.d/force_confdef/DEBIAN @@ -0,0 +1,5 @@ +DPkg { + Options { + "--force-confdef"; + } +}; diff --git a/config/files/etc/apt/sources.list/DEBIAN b/config/files/etc/apt/sources.list/DEBIAN new file mode 100644 index 0000000..4f7c9ad --- /dev/null +++ b/config/files/etc/apt/sources.list/DEBIAN @@ -0,0 +1,3 @@ +deb {%apt_cdn%}/debian {%release%} main contrib non-free +deb {%security_cdn%}/debian-security {%secsuite%} main contrib non-free +deb {%apt_cdn%}/debian {%release%}-updates main contrib non-free diff --git a/config/files/etc/motd/FAIBASE b/config/files/etc/motd/FAIBASE new file mode 100644 index 0000000..e69de29 diff --git a/config/hooks/debconf.IMAGE b/config/hooks/debconf.IMAGE new file mode 100755 index 0000000..c396636 --- /dev/null +++ b/config/hooks/debconf.IMAGE @@ -0,0 +1,45 @@ +#! /bin/bash + +# hook for installing a file system image (tar file) +# this works for Ubuntu 14.04 +# +# Copyright (C) 2015 Thomas Lange, lange@informatik.uni-koeln.de + + +# I use this tar command to create the image of an already running and configured machine +# tar -cf /tmp/IMAGE.tar --exclude /tmp/\* --exclude /run/\* --exclude /proc/\* --exclude /sys/\* --exclude /dev/\* / +# add --xattrs --selinux --acls if needed (for CentOS 7) +# Then copy this image to /srv/fai/config/basefiles/IMAGE.tar and make sure your client belongs to the class IMAGE + +skiptask extrbase debconf repository updatebase instsoft +skiptask configure # do not run the usual configure scripts + +# we assume, that the new host will get its hostname and IP via DHCP +# remove old hostname +fgrep -v 127.0.1.1 $target/etc/hosts >> /tmp/fai/hosts +mv /tmp/fai/hosts $target/etc/hosts +rm $target/etc/hostname + +#install grub +mount -t proc proc $FAI_ROOT/proc +mount -t sysfs sysfs $FAI_ROOT/sys +mount --bind /dev $FAI_ROOT/dev + +if [ -f $target/etc/debian_version ]; then + $ROOTCMD grub-install $BOOT_DEVICE + $ROOTCMD update-grub +fi +if [ -f $target/etc/centos-release ]; then + rm $target/etc/grub2/device.map + $FAI/scripts/CENTOS/40-install-grub + $FAI/scripts/CENTOS/30-mkinitrd + $ROOTCMD fixfiles onboot # this fixes the SELinux security contexts during the first boot +fi + + +# things that may be adjusted: +# +# MAC address ?? (not needed for Ubuntu, it uses iftab(5) +# /etc/hosts may contain the IP and name of the original host +# /etc/hostname (for Ubuntu just remove it) +# /var/lib/NetworkManager/dhclient-eth0.conf? diff --git a/config/hooks/instsoft.DEBIAN b/config/hooks/instsoft.DEBIAN new file mode 100755 index 0000000..35ac306 --- /dev/null +++ b/config/hooks/instsoft.DEBIAN @@ -0,0 +1,25 @@ +#! /bin/bash + +# if package locales will be installed, then install it early, before +# other packages +if [ $FAI_ACTION != "install" -a $FAI_ACTION != "dirinstall" ]; then + exit 0 +fi + +fcopy -Bi /etc/apt/apt.conf.d/force_confdef +ainsl -a /etc/ucf.conf "^conf_force_conffold=YES" + +# in case the locales are already included inside the base file (Ubuntu) +if [ -f $target/usr/sbin/locale-gen ]; then + exit +fi + +# if we want to install locales, install them now +install_packages -l 2>/dev/null | egrep -q ' locales|locales ' +if [ $? -eq 0 ]; then + if [ X$verbose = X1 ]; then + $ROOTCMD apt-get -y install locales + else + $ROOTCMD apt-get -y install locales > /dev/null + fi +fi diff --git a/config/hooks/savelog.LAST.sh b/config/hooks/savelog.LAST.sh new file mode 100755 index 0000000..200bd40 --- /dev/null +++ b/config/hooks/savelog.LAST.sh @@ -0,0 +1,222 @@ +#! /bin/bash + +# parse all log files for error messages +# print errors and warnings found to error.log +# WARNING: This will only work with english error messages! + +errfile=$LOGDIR/error.log + +# Define grep patterns. Do not start or end with an empty line! +globalerrorpatterns="error +fail +warn + bad +bad +no space +Couldn't stat +Cannot access + conflict +is bigger than the limit +did not exist +non existent +not found +couldn't +can't +E: Sorry, broken packages +^E: +operator expected +ambiguous redirect +No previous regular expression +No such +Device or resource busy +unknown option +[a-z]\+\.log:E: +No candidate version found +segfault +Couldn't find any package whose name or description matched +cannot create +The following packages have unmet dependencies" + +globalignorepatterns="[a-z]\+\.log:# +Error: Driver 'pcspkr' is already registered, aborting +: bytes packets errors dropped +:+ error=0 +:+ trap error= +task_error_func= +STOP_ON_ERROR= +courier-webadmin +plugins-bad +Enabling conf localized-error-pages +ibwebadmin +kernel-patch-badram +kolab-webadmin +kolabadmin +gstreamer.\+-plugins-really-bad +liberrors.so +liberrors-samba +libsamba-errors +gsambad +libad +libtest-nowarnings-perl +libtest-warn-perl +libclass-errorhandler-perl +zope-ploneerrorreporting +libroxen-errormessage +liberror-perl +perl-Error +libgpg-error-dev +libgpg-error0 +Opts:.\+errors=remount +[RT]X packets: +WARNING: unexpected IO-APIC +warned about = ( ) +daemon.warn +kern.warn +rw,errors= +Expect some cache +no error +failmsg +RPC call returned error 101 +deverror.out +(floppy), sector 0 +mount version older than kernel +Can't locate module +Warning only .\+MB will be used. +hostname: Host name lookup failure +I can't tell the difference. +warning, not much extra random data, consider using the -rand option +confC._FILE +Warning: 3 database(s) sources +were not found, (but were created) +removing exim +The home dir you specified already exists. +No Rule for /usr/lib/ispell/default.hash. +/usr/sbin/update-fonts-.\+: warning: absolute path +hostname: Unknown server error +EXT2-fs warning: checktime reached +RPC: sendmsg returned error 101 +can't print them to stdout. Define these classes +warning: downgrading +suppress emacs errors +echo Error: +Can't open dependencies file +documents in /usr/doc are no longer supported +if you have both a SCSI and an IDE CD-ROM +Warning: /proc/ide/hd?/settings interface is obsolete, and will be removed soon +Monitoring disabled +Error: only one processor found. +Error Recovery Strategy: +sector 0 does not have an +syslogin_perform_logout: logout() returned an error +grub is not in an XFS filesystem. +grub-install: line 374: +grub-probe: error: Cannot open \`/boot/grub/device.map' +is harmless +not updating .\+ font directory data. +register_serial(): autoconfig failed +Fontconfig error: Cannot load default config file +asking for cache data failed +However, I can not read the target: +Warning: The partition table looks like it was made +task_error=0 +task_local_error=0 +^info: Trying to set +warning: /usr/lib/X11/fonts +can't read /etc/udev/rules.d/z25_persistent-net.rules +/cow': No such file or directory +Dummy start-stop-daemon called +X: bytes packets errors +ACPI Error +ACPI Warning +AE_NOT_FOUND +conflicts with ACPI region +cannot stat \`/etc/modprobe.d/\*.conf' +cdrom: open failed. +libgpg-error +process \`kudzu' used the deprecated sysctl system call +PM: Resume from disk failed +JBD: barrier-based sync failed +aufs: module is from the staging directory, the quality is unknown +warning: linuxlogo stop runlevel arguments (none) do not match +insserv: warning: script .\+ missing LSB tags and overrides +live-premount.\+ If this fails +cannot read table of mounted file systems +error: no alternatives for +ERST: Error Record Serialization Table (ERST) support is initialized +ERST: Table is not found +HEST: Table not found +failed to stat /dev/pts +Failed to connect to socket /var/run/dbus/system_bus_socket +fail to add MMCONFIG information +can't initialize iptables table +can't initialize ip6tables table +Authentication warning overridden +41-warning.sh +PCCT header not found +Download is performed unsandboxed as root as file +update-alternatives: warning: skip creation of +loop: module verification failed: signature +Warning: apt-key output should not be parsed +WARNING: Failed to connect to lvmetad. Falling back to device scanning +Warning: The home dir /var/lib/usbmux you specified +diff: /var/lib/apparmor/profiles/.apparmor.md5sums: No such file or directory +error reporting disabled +Enabling Firmware First mode for corrected errors +errors: 0 + 0 errors +Memory Error Correction: +Memory Controller 0 - Channel . Error +IIO RAS/Control Status/Global Errors +RAS: Correctable Errors collector initialized +__stack_chk_fail +grub.cfg.new: Directory nonexistent +can't derive routing for PCI INT A +failed to load isci/isci_firmware.bin +Direct firmware load for isci/isci_firmware.bin failed with error +Loading user firmware failed, using default values +stunnel4 you specified can't be accessed: No such file or directory +install-docs --verbose --check file_name' may give more details about the above errors +cannot open '/etc/ssl/certs/java/cacerts' for reading: No such file or directory +can't claim BAR +disabling ASPM +data block query control method not found +subprocess.py.\+RuntimeWarning: line buffering +Resource conflict.\+ found +update-rc.d: warning: start and stop actions are no longer supported" + +# add pattern on some conditions +if [ -n $FAI_ALLOW_UNSIGNED ] ; then + globalignorepatterns="$globalignorepatterns +WARNING: untrusted versions +WARNING: The following packages cannot be authenticated +Ignoring these trust violations" +fi +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Here you can define your own patterns. Put one pattern in a line, +# do not create empty lines. +myerrorpatterns="X_X-X_XX" +myignorepatterns="X_X-X_XX" +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# The main routine +errorpatterns="$globalerrorpatterns +$myerrorpatterns" +ignorepatterns="$globalignorepatterns +$myignorepatterns" + +cd $LOGDIR || exit 3 +if [ -s $errfile ]; then + echo "Errorfile already exists. Aborting." >&2 + exit +fi + +grep -i "$errorpatterns" *.log | grep -vi "$ignorepatterns" > $errfile +if [ X$verbose = X1 ]; then + egrep -v '^software.log:' $errfile > $LOGDIR/tempfile + mv $LOGDIR/tempfile $errfile +fi + +if [ -s $errfile ]; then + echo "ERRORS found in log files. See $errfile" >&2 +else + echo "Congratulations! No errors found in log files." +fi diff --git a/config/hooks/setup.DEFAULT.sh b/config/hooks/setup.DEFAULT.sh new file mode 100755 index 0000000..00a1df2 --- /dev/null +++ b/config/hooks/setup.DEFAULT.sh @@ -0,0 +1,7 @@ +#! /bin/bash + +# use short hostname instead of FQDN +export HOSTNAME=${HOSTNAME%%.*} +if [ $do_init_tasks -eq 1 ]; then + echo $HOSTNAME > /proc/sys/kernel/hostname +fi diff --git a/config/hooks/updatebase.DEBIAN b/config/hooks/updatebase.DEBIAN new file mode 100755 index 0000000..a6948a7 --- /dev/null +++ b/config/hooks/updatebase.DEBIAN @@ -0,0 +1,16 @@ +#! /bin/bash + +if [ -n "$APTPROXY" ]; then + echo "Acquire::http::Proxy \"$APTPROXY\";" > $target/etc/apt/apt.conf.d/02proxy +else + rm -f $target/etc/apt/apt.conf.d/02proxy +fi + +echo force-unsafe-io > $target/etc/dpkg/dpkg.cfg.d/unsafe-io + +fcopy -iSM /etc/apt/sources.list + +# you may want to add i386 arch to amd64 hosts +# if ifclass AMD64; then +# $ROOTCMD dpkg --add-architecture i386 +# fi diff --git a/config/hooks/updatebase.PARTICIPANT b/config/hooks/updatebase.PARTICIPANT new file mode 100755 index 0000000..638a664 --- /dev/null +++ b/config/hooks/updatebase.PARTICIPANT @@ -0,0 +1,4 @@ +#! /bin/bash + +cp -RT $FAI/simplefiles/PARTICIPANT/usr/share/keyrings $target/usr/share/keyrings +cp -RT $FAI/simplefiles/PARTICIPANT/etc/apt/sources.list.d $target/etc/apt/sources.list.d diff --git a/config/package_config/CONTESTANT b/config/package_config/CONTESTANT new file mode 100644 index 0000000..3d73b4f --- /dev/null +++ b/config/package_config/CONTESTANT @@ -0,0 +1,7 @@ +PACKAGES install-norec +# For fai softupdate +nfs-common netcat fai-client +# For importing client certificate +libnss3-tools +# For screen recording +ffmpeg diff --git a/config/package_config/DEBIAN b/config/package_config/DEBIAN new file mode 100644 index 0000000..1abf6bb --- /dev/null +++ b/config/package_config/DEBIAN @@ -0,0 +1,54 @@ +PACKAGES install-norec +apt-transport-https # is only needed for stretch +debconf-utils +file +less +linuxlogo +rsync +openssh-client openssh-server +time +procinfo +nullmailer +eject +locales +console-setup kbd +pciutils usbutils +systemd-timesyncd +#unattended-upgrades + +PACKAGES install NONFREE +# you may want these non-free kernel drivers +firmware-bnx2 firmware-bnx2x firmware-realtek +firmware-linux-nonfree +# a list of firmware for wifi/wireless +atmel-firmware firmware-atheros firmware-brcm80211 +firmware-iwlwifi firmware-libertas firmware-ralink firmware-zd1211 +firmware-brcm80211 firmware-ti-connectivity +firmware-netronome firmware-netxen firmware-realtek +firmware-cavium +# firmware-ipw2x00 # needs a debconf question + +PACKAGES install I386 +linux-image-686-pae +memtest86+ + +PACKAGES install CHROOT +linux-image-686-pae- +linux-image-amd64- + +PACKAGES install AMD64 +linux-image-amd64 +memtest86+ + +PACKAGES install ARM64 +grub-efi-arm64 +linux-image-arm64 + +PACKAGES install GRUB_PC +grub-pc + +PACKAGES install GRUB_EFI +grub-efi + +PACKAGES install LVM +lvm2 diff --git a/config/package_config/DEBIAN.gpg b/config/package_config/DEBIAN.gpg new file mode 100644 index 0000000000000000000000000000000000000000..0d5b7a903f651c65861986617e62a2be8cb53e70 GIT binary patch literal 2824 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:$error))' ERR # save maximum error code + +cp -RT $FAI/simplefiles/CONTESTANT $target + +$ROOTCMD dconf update + +# Enable firewall +$ROOTCMD systemctl enable nftables.service + +# Disable Bluetooth +$ROOTCMD systemctl disable bluetooth.service + +# Disable sleep +$ROOTCMD systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target + +sed -i 's|"homepage": ".*"|"homepage": "https://finals.soi.ch/"|' $target/etc/chromium/master_preferences + +# Disable panels in gnome-control-center +DISABLE_DESKTOP="$ROOTCMD dpkg-statoverride --force-statoverride-add --update --add root root 640" +$DISABLE_DESKTOP /usr/share/applications/gnome-bluetooth-panel.desktop +$DISABLE_DESKTOP /usr/share/applications/gnome-online-accounts-panel.desktop +$DISABLE_DESKTOP /usr/share/applications/gnome-sharing-panel.desktop + +# Auto login +sed -i 's/# AutomaticLoginEnable = true/AutomaticLoginEnable = true/g' $target/etc/gdm3/daemon.conf +sed -i 's/# AutomaticLogin = user1/AutomaticLogin = contestant/g' $target/etc/gdm3/daemon.conf + +exit $error diff --git a/config/scripts/DEBIAN/10-rootpw b/config/scripts/DEBIAN/10-rootpw new file mode 100755 index 0000000..f927226 --- /dev/null +++ b/config/scripts/DEBIAN/10-rootpw @@ -0,0 +1,12 @@ +#! /bin/bash + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +# set root password +if [ -n "$ROOTPW" ]; then + $ROOTCMD chpasswd --encrypted <<< "root:${ROOTPW}" +else + $ROOTCMD usermod -L root +fi + +exit $error diff --git a/config/scripts/DEBIAN/20-capabilities b/config/scripts/DEBIAN/20-capabilities new file mode 100755 index 0000000..ea650fa --- /dev/null +++ b/config/scripts/DEBIAN/20-capabilities @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Capabilities get lost when creating the fai base.tar.xz image. +# Restore them here. +# + +set -e + +if [ ! -x $target/sbin/setcap ] ; then + exit 0 +fi + +for FILE in /bin/ping /bin/ping6 /usr/bin/fping /usr/bin/fping6; do + if [ -x $target/$FILE -a ! -h $target/$FILE ] ; then + if $ROOTCMD /sbin/setcap cap_net_raw+ep $FILE; then + echo "Setcap worked! $FILE is not suid!" + fi + fi +done +if [ -x $target/usr/bin/systemd-detect-virt ] ; then + $ROOTCMD /sbin/setcap cap_dac_override,cap_sys_ptrace+ep /usr/bin/systemd-detect-virt +fi diff --git a/config/scripts/DEBIAN/30-interface b/config/scripts/DEBIAN/30-interface new file mode 100755 index 0000000..4b0dcf4 --- /dev/null +++ b/config/scripts/DEBIAN/30-interface @@ -0,0 +1,118 @@ +#! /bin/bash + +netplan_yaml() { + # network configuration using ubuntu's netplan.io + local IFNAME="$1" + local METHOD="$2" + echo "Generating netplan configuration for $IFNAME ($METHOD)" >&2 + echo "# generated by FAI" + echo "network:" + echo " version: 2" + echo " renderer: $RENDERER" + case "$RENDERER" in + networkd) + echo " ethernets:" + echo " $IFNAME:" + case "$METHOD" in + dhcp) + echo " dhcp4: true" + ;; + static) + echo " addresses: [$CIDR]" + echo " gateway4: $GATEWAYS_1" + echo " nameservers:" + echo " search: [$DOMAIN]" + echo " addresses: [${DNSSRVS// /, }]" + ;; + esac + esac +} + +iface_stanza() { + # classic network configuration using /etc/network/interfaces + local IFNAME="$1" + local METHOD="$2" + echo "Generating interface configuration for $IFNAME ($METHOD)" >&2 + echo "# generated by FAI" + echo "auto $IFNAME" + echo "iface $IFNAME inet $METHOD" + case "$METHOD" in + static) + echo " address $CIDR" + echo " gateway $GATEWAYS" + ;; + esac +} + +newnicnames() { + + # determine predictable network names only for stretch and above + local name + + [ $do_init_tasks -eq 0 ] && return + [ -z "$NIC1" ] && return + + fields="ID_NET_NAME_FROM_DATABASE ID_NET_NAME_ONBOARD ID_NET_NAME_SLOT ID_NET_NAME_PATH" + for field in $fields; do + name=$(udevadm info /sys/class/net/$NIC1 | sed -rn "s/^E: $field=(.+)/\1/p") + if [[ $name ]]; then + NIC1=$name + return + fi + done + + # try to get altname net dev + name=$(ip link show $NIC1 | awk '/altname / { print $2 }') + if [[ $name ]]; then + NIC1=$name + return + else + echo "$0: error: could not find systemd predictable network name. Using $NIC1." + fi +} + +if [ -z "$NIC1" ]; then + echo "WARNING: \$NIC1 is not defined. Cannot add ethernet to /etc/network/interfaces." +fi +CIDR=$(ip --br ad sh $NIC1|awk '{print $3}') +newnicnames + +case "$FAI_ACTION" in + install|dirinstall) + ifclass DHCPC && METHOD=dhcp || METHOD=static + ifclass XORG && RENDERER=NetworkManager || RENDERER=networkd + + if [ -d $target/etc/netplan ]; then + # Ubuntu >= 17.10 with netplan.io + if [ -n "$NIC1" ]; then + netplan_yaml $NIC1 $METHOD > $target/etc/netplan/01-${NIC1}.yaml + fi + elif [ -d $target/etc/network/interfaces.d ]; then + # ifupdown >= 0.7.41 (Debian >= 8, Ubuntu >= 14.04) + iface_stanza lo loopback > $target/etc/network/interfaces.d/lo + + if [ -n "$NIC1" -a ! -f $target/etc/NetworkManager/NetworkManager.conf ]; then + iface_stanza $NIC1 $METHOD > $target/etc/network/interfaces.d/$NIC1 + fi + else + ( + iface_stanza lo loopback + iface_stanza $NIC1 $METHOD + ) > $target/etc/network/interfaces + fi + + if ! ifclass DHCPC ; then + [ -n "$NETWORK" ] && echo "localnet $NETWORK" > $target/etc/networks + if [ ! -L $target/etc/resolv.conf -a -e /etc/resolv.conf ]; then + cp -p /etc/resolv.conf $target/etc + fi + fi + ;; +esac + +# here fcopy is mostly used, when installing a client for running in a +# different subnet than during the installation +fcopy -iM /etc/resolv.conf +fcopy -iM /etc/network/interfaces /etc/networks + +exit $error diff --git a/config/scripts/DEBIAN/40-misc b/config/scripts/DEBIAN/40-misc new file mode 100755 index 0000000..714be55 --- /dev/null +++ b/config/scripts/DEBIAN/40-misc @@ -0,0 +1,51 @@ +#! /bin/bash + +# (c) Thomas Lange, 2001-2016, lange@debian.org +# (c) Michael Goetze, 2010-2011, mgoetze@mgoetze.net + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +# a list of modules which are loaded at boot time +for module in $MODULESLIST; do + ainsl -a /etc/modules "^$module$" +done + +fcopy -Mv /etc/hostname || echo $HOSTNAME > $target/etc/hostname +ainsl -a /etc/mailname ${HOSTNAME} +if [ ! -e $target/etc/adjtime ]; then + printf "0.0 0 0.0\n0\nUTC\n" > $target/etc/adjtime +fi +if [ "$UTC" = "yes" ]; then + sed -i -e 's:^LOCAL$:UTC:' $target/etc/adjtime +else + sed -i -e 's:^UTC$:LOCAL:' $target/etc/adjtime +fi + +# enable linuxlogo +if [ -f $target/etc/inittab ]; then + sed -i -e 's#/sbin/getty 38400#/sbin/getty -f /etc/issue.linuxlogo 38400#' ${target}/etc/inittab +elif [ -f $target/lib/systemd/system/getty@.service ]; then + sed -i -e 's#sbin/agetty --noclear#sbin/agetty -f /etc/issue.linuxlogo --noclear#' $target/lib/systemd/system/getty@.service +fi + +# make sure a machine-id exists +if [ ! -f $target/etc/machine-id ]; then + > $target/etc/machine-id +fi +# recreate machine-id if the file is empty +if [ X"$(stat -c '%s' $target/etc/machine-id 2>/dev/null)" = X0 -a -f $target/bin/systemd-machine-id-setup ]; then + $ROOTCMD systemd-machine-id-setup +fi + +ln -fs /proc/mounts $target/etc/mtab + +rm -f $target/etc/dpkg/dpkg.cfg.d/fai $target/etc/dpkg/dpkg.cfg.d/unsafe-io + +if [ -d /etc/fai ]; then + if ! fcopy -Mv /etc/fai/fai.conf; then + ainsl -a /etc/fai/fai.conf "FAI_CONFIG_SRC=$FAI_CONFIG_SRC" + fi +fi +fcopy -iv /etc/rc.local + +exit $error diff --git a/config/scripts/FAIBASE/10-misc b/config/scripts/FAIBASE/10-misc new file mode 100755 index 0000000..6c15987 --- /dev/null +++ b/config/scripts/FAIBASE/10-misc @@ -0,0 +1,38 @@ +#! /bin/bash + +# (c) Thomas Lange, 2001-2012, lange@debian.org + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +echo $TIMEZONE > $target/etc/timezone +if [ -L $target/etc/localtime ]; then + ln -sf /usr/share/zoneinfo/${TIMEZONE} $target/etc/localtime +else + cp -f /usr/share/zoneinfo/${TIMEZONE} $target/etc/localtime +fi + +if [ -f $target/etc/hosts.orig ]; then + mv $target/etc/hosts.orig $target/etc/hosts +fi +if [ -n "$IPADDR" ]; then + # ifclass DHCPC || + ainsl -s /etc/hosts "$IPADDR $HOSTNAME.$DOMAIN $HOSTNAME" +else + ifclass DHCPC && ainsl -s /etc/hosts "127.0.0.1 $HOSTNAME" +fi +fcopy -iM /etc/hosts /etc/motd + +# make /root accessible only by root +chmod -c 0700 $target/root +chown -c root:root $target/root +# copy default dotfiles for root account +fcopy -ir /root + +# use tmpfs for /tmp if not defined in disk_config +if ! grep -Pq '\s/tmp\s' $target/etc/fstab; then + ainsl /etc/fstab "tmpfs /tmp tmpfs nodev,nosuid,size=50%,mode=1777 0 0" +fi +chmod -c 1777 ${target}/tmp +chown -c 0:0 ${target}/tmp + +exit $error diff --git a/config/scripts/FAIBASE/20-removable_media b/config/scripts/FAIBASE/20-removable_media new file mode 100755 index 0000000..8d07029 --- /dev/null +++ b/config/scripts/FAIBASE/20-removable_media @@ -0,0 +1,25 @@ +#! /bin/bash + +# (c) Thomas Lange, 2006,2009, lange@debian.org +# create entries for removable media in fstab and directories in /media + +cdromlist() { + [ -f /proc/sys/dev/cdrom/info ] || return + devs=$(grep 'drive name:' /proc/sys/dev/cdrom/info | cut -d ":" -f 2) + for d in $devs; do + echo $d + done +} + +fstabline () { + line=$(printf "%-15s %-15s %-7s %-15s %-7s %s\n" "$1" "$2" "$3" "$4" "$5" "$6") + ainsl /etc/fstab "$line" +} + +i=0 +for cdrom in $(cdromlist | tac); do + [ $i -eq 0 ] && ln -sfn cdrom0 $target/media/cdrom + mkdir -p $target/media/cdrom$i + fstabline /dev/$cdrom /media/cdrom$i udf,iso9660 ro,user,noauto 0 0 + i=$((i + 1)) +done diff --git a/config/scripts/GRUB_EFI/10-setup b/config/scripts/GRUB_EFI/10-setup new file mode 100755 index 0000000..7dd92d4 --- /dev/null +++ b/config/scripts/GRUB_EFI/10-setup @@ -0,0 +1,68 @@ +#! /bin/bash +# support for GRUB version 2 + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +# This script assumes that the disk has a GPT partition table and +# that the extended system partition (ESP) is mounted on /boot/efi. +# When building a disk image, we don't change the NVRAM to point at +# the boot image we made available, because the disk image is likely +# not installed on the current system. As a result, we force +# installation into the removable media paths as well as the standard +# debian path. + +set -a + +# do not set up grub during dirinstall +if [ "$FAI_ACTION" = "dirinstall" ] ; then + exit 0 +fi +# during softupdate use this file +[ -r $LOGDIR/disk_var.sh ] && . $LOGDIR/disk_var.sh + +if [ -z "$BOOT_DEVICE" ]; then + exit 189 +fi + +# disable os-prober because of #802717 +ainsl /etc/default/grub 'GRUB_DISABLE_OS_PROBER=true' + +# skip the rest, if not an initial installation +if [ $FAI_ACTION != "install" ]; then + $ROOTCMD update-grub + exit $error +fi + +GROOT=$($ROOTCMD grub-probe -tdrive -d $BOOT_DEVICE) + +# handle /boot in lvm-on-md +_bdev=$(readlink -f $BOOT_DEVICE) +if [ "${_bdev%%-*}" = "/dev/dm" ]; then + BOOT_DEVICE=$( lvs --noheadings -o devices $BOOT_DEVICE | sed -e 's/^*\([^(]*\)(.*$/\1/' ) +fi + +# Check if RAID is used for the boot device +if [[ $BOOT_DEVICE =~ '/dev/md' ]]; then + raiddev=${BOOT_DEVICE#/dev/} + # install grub on all members of RAID + for device in $(LC_ALL=C perl -ne 'if(/^'$raiddev'\s.+raid\d+\s(.+)/){ $_=$1; s/\d+\[\d+\]//g; print }' /proc/mdstat); do + echo Install grub on /dev/$device + $ROOTCMD grub-install --no-floppy --force-extra-removable "/dev/$device" + done + +elif [[ $BOOT_DEVICE =~ '/dev/loop' ]]; then + # do not update vmram when using a loop device + $ROOTCMD grub-install --no-floppy --force-extra-removable --modules=part_gpt --no-nvram $BOOT_DEVICE + if [ $? -eq 0 ]; then + echo "Grub installed on hostdisk $BOOT_DEVICE" + fi + +else + $ROOTCMD grub-install --no-floppy --modules=part_gpt "$GROOT" + if [ $? -eq 0 ]; then + echo "Grub installed on $BOOT_DEVICE = $GROOT" + fi +fi +$ROOTCMD update-grub + +exit $error diff --git a/config/scripts/GRUB_PC/10-setup b/config/scripts/GRUB_PC/10-setup new file mode 100755 index 0000000..270b356 --- /dev/null +++ b/config/scripts/GRUB_PC/10-setup @@ -0,0 +1,84 @@ +#! /bin/bash +# support for GRUB version 2 + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +set -a + +# do not set up grub during dirinstall +if [ "$FAI_ACTION" = "dirinstall" ] ; then + exit 0 +fi +# during softupdate use this file +[ -r $LOGDIR/disk_var.sh ] && . $LOGDIR/disk_var.sh + +if [ -z "$BOOT_DEVICE" ]; then + exit 189 +fi + +# disable os-prober because of #802717 +ainsl /etc/default/grub 'GRUB_DISABLE_OS_PROBER=true' + +# skip the rest, if not an initial installation +if [ $FAI_ACTION != "install" ]; then + $ROOTCMD update-grub + exit $error +fi + +get_stable_devname() { + + local _DEV="$1" + local i + declare -a _RES + + # prefer SCSI over ATA over WWN over path + # do not use by-path + + for i in $($ROOTCMD udevadm info -r --query=symlink "$_DEV"); do + if [[ "$i" =~ /by-id/scsi ]]; then + _RES[10]="$i" + elif [[ "$i" =~ /by-id/ata ]]; then + _RES[20]="$i" + elif [[ "$i" =~ /by-id/wwn ]]; then + _RES[99]="$i" + fi + done + + echo "${_RES[@]::1}" +} + +# handle /boot in lvm-on-md +_bdev=$(readlink -f $BOOT_DEVICE) +if [ "${_bdev%%-*}" = "/dev/dm" ]; then + BOOT_DEVICE=$( lvs --noheadings -o devices $BOOT_DEVICE | sed -e 's/^*\([^(]*\)(.*$/\1/' ) +fi + +# Check if RAID is used for the boot device +if [[ $BOOT_DEVICE =~ '/dev/md' ]]; then + raiddev=${BOOT_DEVICE#/dev/} + # install grub on all members of RAID + for device in $(LC_ALL=C perl -ne 'if(/^'$raiddev'\s.+raid\d+\s(.+)/){ $_=$1; s/\d+\[\d+\]//g; s/(nvme.+?)p/$1/g; print }' /proc/mdstat); do + pdevice=$(get_stable_devname /dev/$device) + if [ -z "$pdevice" ]; then + # if we cannot find a persistent name (for e.g. in a VM) use old name + pdevice="/dev/$device" + fi + mbrdevices+="$pdevice, " + echo Installing grub on /dev/$device = $pdevice + $ROOTCMD grub-install --no-floppy "/dev/$device" + done + # remove last , + mbrdevices=${mbrdevices%, } +else + mbrdevices=$(get_stable_devname $BOOT_DEVICE) + if [ -z "$mbrdevices" ]; then + # if we cannot find a persistent name (for e.g. in a VM) use old name + mbrdevices=$BOOT_DEVICE + fi + echo "Installing grub on $BOOT_DEVICE = $mbrdevices" + $ROOTCMD grub-install --no-floppy "$mbrdevices" +fi + +echo "grub-pc grub-pc/install_devices multiselect $mbrdevices" | $ROOTCMD debconf-set-selections +$ROOTCMD dpkg-reconfigure grub-pc +exit $error diff --git a/config/scripts/LAST/50-misc b/config/scripts/LAST/50-misc new file mode 100755 index 0000000..2a7271b --- /dev/null +++ b/config/scripts/LAST/50-misc @@ -0,0 +1,103 @@ +#! /bin/bash + +# copyright Thomas Lange 2001-2016, lange@debian.org + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +if [ "$FAI_ACTION" = "dirinstall" -o $do_init_tasks -eq 0 ] ; then + : +else + # check if mdadm has been forgotten + if grep -q active /proc/mdstat 2>/dev/null; then + if [ ! -d $target/etc/mdadm ]; then + echo ERROR: Found Software RAID, but the mdadm package was not installed + error=1 + fi + fi + + usedm=$(dmsetup ls 2>/dev/null | egrep -v '^live-rw|^live-base|^No devices found' | wc -l) + if [ $usedm -ne 0 ]; then + if [ ! -d $target/etc/lvm ]; then + echo ERROR: Found lvm devices, but the lvm2 package was not installed + error=1 + fi + fi +fi + +# remove backup files from cfengine, but only if cfengine is installed +if [ -x /usr/sbin/cfagent ] || [ -x $target/usr/sbin/cfagent ] ; then + dirs="root etc var" + for path in $dirs; do + find $target/$path -maxdepth 20 -name \*.cfedited -o -name \*.cfsaved | xargs -r rm + done +fi + +[ "$FAI_DEBMIRROR" ] && + ainsl /etc/fstab "#$FAI_DEBMIRROR $MNTPOINT nfs ro 0 0" + +# set bios clock +if [ $do_init_tasks -eq 1 ] ; then + case "$UTC" in + no|"") hwopt="--localtime" ;; + yes) hwopt="--utc" ;; + esac + hwclock $hwopt --systohc || true +fi + +# Make sure everything is configured properly +if ifclass DEBIAN ; then + $ROOTCMD apt-get -f install -y +fi + +if [ $FAI_ACTION = "install" ]; then + lskernels=$(echo $target/boot/vmlinu*) + if [ ! -f ${lskernels%% *} ]; then + echo "ERROR: No kernel was installed. Have a look at shell.log" >&2 + error=1 + fi +fi + +# copy sources.list +fcopy -iSM /etc/apt/sources.list + + +setrel() { + + # if release is not set, try to determine it + + if [ -n "$release" ]; then + return + fi + if [ ! -f $target/etc/os-release ]; then + return + fi + + dists="jessie stretch buster bullseye bookworm trixie focal bionic xenial trusty" + for d in $dists; do + if grep -iq $d $target/etc/os-release; then + release=$d + break + fi + done +} + +# if installation was done from CD, replace useless sources.list +setrel +if [ -f $target/etc/apt/sources.list -a -n "$release" ]; then + grep -q 'file generated by fai-cd' $target/etc/apt/sources.list && cat < $target/etc/apt/sources.list +deb $apt_cdn/debian $release main contrib non-free +deb $security_cdn/debian-security ${secsuite} main contrib non-free +#deb [trusted=yes] http://fai-project.org/download $release koeln +EOF + # if the package fai-server was installed, enable the project's repository + if dpkg-query --admindir=$target/var/lib/dpkg -W fai-server >/dev/null 2>&1; then + sed -i -e '/fai-project.org/s/^#//' $target/etc/apt/sources.list + fi +fi + +# for ARM architecture, we may need the kernel and initrd to boot or flash the device +if ifclass ARM64; then + cp -pv $target/boot/vmlinuz* $target/boot/initrd* $FAI_RUNDIR +fi + +exit $error diff --git a/config/scripts/PARTICIPANT/10-config b/config/scripts/PARTICIPANT/10-config new file mode 100755 index 0000000..60626f0 --- /dev/null +++ b/config/scripts/PARTICIPANT/10-config @@ -0,0 +1,56 @@ +#! /bin/bash + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +cp -RT $FAI/simplefiles/PARTICIPANT $target + +$ROOTCMD dconf update + +# Uncomment this to reinstall extensions +# (disabled by default to speed up softupdate): +# rm -rf $target/etc/skel/.vscode + +# VS Code extensions +if [ ! -d $target/etc/skel/.vscode ]; then + # To avoid running VS Code as root, run it as nobody instead. + mkdir $target/etc/skel/.vscode + chown nobody:nogroup $target/etc/skel/.vscode + shopt -s nullglob + for ext in $FAI/downloads/*.vsix; do + # We can't access the config space inside ROOTCMD, so we copy the file to the target. + cp "$ext" $target/tmp/ext.vsix + $ROOTCMD runuser -u nobody -- code --user-data-dir=/tmp/vsc.tmp \ + --extensions-dir=/etc/skel/.vscode/extensions \ + --install-extension=/tmp/ext.vsix + done + chown -R root:root $target/etc/skel/.vscode + rm -rf $target/tmp/vsc.tmp $target/tmp/ext.vsix +fi + +# Install soi header +tar --overwrite -xf $FAI/downloads/soi-header.tar.gz -C $target/usr/local/include --strip-components=2 soi-header/include/ + +# Install codeblocks template +$target/bin/unzip -o $FAI/downloads/soi_template_codeblocks_ubuntu_RzdvSho.zip -d $target/usr/share/codeblocks/templates/wizard/ +if ! grep -q '_T("soi")' $target/usr/share/codeblocks/templates/wizard/config.script ; then + sed -i 's|// project wizards|RegisterWizard(wizProject, _T("soi"), _T("A SOI task"), _T("Console"));|' $target/usr/share/codeblocks/templates/wizard/config.script +fi + +# add super user account +if [ -n "$SUPER_USER_NAME" ]; then +if ! $ROOTCMD getent passwd $SUPER_USER_NAME ; then + $ROOTCMD adduser --disabled-login --gecos "$SUPER_USER_DISPLAYNAME" $SUPER_USER_NAME + $ROOTCMD usermod -p "$SUPER_USER_PW" $SUPER_USER_NAME + $ROOTCMD adduser $SUPER_USER_NAME sudo +fi +fi + +# add participant account +if [ -n "$PARTICIPANT_USER_NAME" ]; then +if ! $ROOTCMD getent passwd $PARTICIPANT_USER_NAME ; then + $ROOTCMD adduser --disabled-login --gecos "$PARTICIPANT_USER_NAME" $PARTICIPANT_USER_NAME + $ROOTCMD usermod -p "$PARTICIPANT_USER_PW" $PARTICIPANT_USER_NAME +fi +fi + +exit $error diff --git a/config/scripts/TRAINING/10-config b/config/scripts/TRAINING/10-config new file mode 100755 index 0000000..6afe110 --- /dev/null +++ b/config/scripts/TRAINING/10-config @@ -0,0 +1,8 @@ +#! /bin/bash + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +# Remove APT proxy +rm -f $target/etc/apt/apt.conf.d/02proxy + +exit $error diff --git a/config/setup-bern.sh b/config/setup-bern.sh new file mode 100755 index 0000000..5887498 --- /dev/null +++ b/config/setup-bern.sh @@ -0,0 +1,41 @@ +#! /bin/bash + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +FAI=/var/lib/bernconfig +target=/ + +apt-get install libnss3-tools gnome-tweaks fonts-firacode + +rsync --archive \ + --exclude /etc/apt \ + --exclude /usr/share/keyrings \ + --exclude /etc/ssh \ + $FAI/simplefiles/PARTICIPANT/ $target + +rsync --archive \ + --exclude /etc/systemd/timesyncd.conf.d \ + --exclude /etc/hosts \ + --exclude /etc/nftables.conf \ + --exclude /root \ + $FAI/simplefiles/CONTESTANT/ $target + +sed -i 's|firefox-esr|firefox_firefox|' $target/etc/dconf/db/local.d/00-favorite-apps + +$ROOTCMD dconf update + +# Install soi header +tar --overwrite -xf $FAI/downloads/soi-header.tar.gz -C $target/usr/local/include --strip-components=2 soi-header/include/ + + +# Disable panels in gnome-control-center +DISABLE_DESKTOP="$ROOTCMD dpkg-statoverride --force-statoverride-add --update --add root root 640" +$DISABLE_DESKTOP /usr/share/applications/gnome-bluetooth-panel.desktop +$DISABLE_DESKTOP /usr/share/applications/gnome-online-accounts-panel.desktop +$DISABLE_DESKTOP /usr/share/applications/gnome-sharing-panel.desktop + +# Auto login +sed -i 's/# AutomaticLoginEnable = true/AutomaticLoginEnable = true/g' $target/etc/gdm3/custom.conf +sed -i 's/# AutomaticLogin = user1/AutomaticLogin = contestant/g' $target/etc/gdm3/custom.conf + +exit $error diff --git a/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-idle b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-idle new file mode 100644 index 0000000..9ae8f36 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-idle @@ -0,0 +1,3 @@ +# Disable blank screen +[org/gnome/desktop/session] +idle-delay=uint32 0 diff --git a/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-screensaver-lock b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-screensaver-lock new file mode 100644 index 0000000..e71be0e --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-screensaver-lock @@ -0,0 +1,3 @@ +# Disable lock on blank screen +[org/gnome/desktop/screensaver] +lock-enabled = false diff --git a/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-suspend b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-suspend new file mode 100644 index 0000000..3486e18 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disable-suspend @@ -0,0 +1,4 @@ +# Disable suspend when inactive +[org/gnome/settings-daemon/plugins/power] +sleep-inactive-ac-type = 'nothing' +sleep-inactive-battery-type = 'nothing' diff --git a/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disallow-updates b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disallow-updates new file mode 100644 index 0000000..61459a5 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-disallow-updates @@ -0,0 +1,3 @@ +# This prevents "Updates available" notifications +[org/gnome/software] +allow-updates = false diff --git a/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-gnome-shell-extensions b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-gnome-shell-extensions new file mode 100644 index 0000000..afe0c96 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-gnome-shell-extensions @@ -0,0 +1,2 @@ +[org/gnome/shell] +enabled-extensions = ['contest-lock@soi.ch', 'user-indicator@soi.ch'] diff --git a/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-lock-screen b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-lock-screen new file mode 100644 index 0000000..fee6b03 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/dconf/db/local.d/00-lock-screen @@ -0,0 +1,3 @@ +# Disable locking the screen +[org/gnome/desktop/lockdown] +disable-lock-screen=true diff --git a/config/simplefiles/CONTESTANT/etc/firefox/policies/policies.json b/config/simplefiles/CONTESTANT/etc/firefox/policies/policies.json new file mode 100644 index 0000000..8fcb0ff --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/firefox/policies/policies.json @@ -0,0 +1,23 @@ +{ + "policies": { + "OverrideFirstRunPage": "", + "NoDefaultBookmarks": true, + "DisableProfileImport": true, + "Preferences": { + "datareporting.policy.dataSubmissionPolicyBypassNotification": true, + "security.default_personal_cert": "Select Automatically" + }, + "Homepage": { + "URL": "https://finals.soi.ch/", + "StartPage": "homepage" + }, + "DisplayBookmarksToolbar": true, + "Bookmarks": [ + { + "Title": "Grader", + "URL": "https://finals.soi.ch/", + "Placement": "toolbar" + } + ] + } +} diff --git a/config/simplefiles/CONTESTANT/etc/hosts b/config/simplefiles/CONTESTANT/etc/hosts new file mode 100644 index 0000000..45483e0 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/hosts @@ -0,0 +1,33 @@ +127.0.0.1 localhost + +# The following lines are desirable for IPv6 capable hosts +::1 ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters + +10.0.0.8 finals.soi.ch +10.0.0.9 contestserver + +10.0.0.10 contestant10 +10.0.0.11 contestant11 +10.0.0.12 contestant12 +10.0.0.13 contestant13 +10.0.0.14 contestant14 +10.0.0.15 contestant15 +10.0.0.16 contestant16 +10.0.0.17 contestant17 +10.0.0.18 contestant18 +10.0.0.19 contestant19 +10.0.0.20 contestant20 +10.0.0.21 contestant21 +10.0.0.22 contestant22 +10.0.0.23 contestant23 +10.0.0.24 contestant24 +10.0.0.25 contestant25 +10.0.0.26 contestant26 +10.0.0.27 contestant27 +10.0.0.28 contestant28 + +10.0.0.40 test40 diff --git a/config/simplefiles/CONTESTANT/etc/nftables.conf b/config/simplefiles/CONTESTANT/etc/nftables.conf new file mode 100755 index 0000000..e12dd71 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/nftables.conf @@ -0,0 +1,45 @@ +#!/usr/sbin/nft -f + +flush ruleset + +table inet filter { + chain input { + type filter hook input priority 0; + + ct state invalid drop + ct state { established, related } accept + + # Accept loopback + iif lo accept + + # Accept ICMP + ip protocol icmp accept + ip6 nexthdr icmpv6 accept + + # Accept incoming connections to these ports + tcp dport { ssh } accept + + reject + } + chain forward { + type filter hook forward priority 0; + reject + } + chain output { + type filter hook output priority 0; + + ct state invalid drop + ct state { established, related } accept + + # Accept loopback + oif lo accept + + # Accept outgoing connections to these addresses + ip daddr { 10.0.0.1-10.0.0.9 } accept + + # Accept any connections by root user + #meta skuid root accept + + reject + } +} diff --git a/config/simplefiles/CONTESTANT/etc/polkit-1/localauthority/20-org.d/rules.pkla b/config/simplefiles/CONTESTANT/etc/polkit-1/localauthority/20-org.d/rules.pkla new file mode 100644 index 0000000..d3e84d6 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/polkit-1/localauthority/20-org.d/rules.pkla @@ -0,0 +1,11 @@ +# Show a root password prompt for these actions: +# - change network settings +# - hibernate +# - change package download proxy +# - mount removable storage, perform other disk operations +[Disallow actions] +Identity=unix-user:* +Action=org.freedesktop.ModemManager1.*;org.freedesktop.NetworkManager.*;org.freedesktop.login1.hibernate;org.freedesktop.packagekit.system-network-proxy-configure;org.freedesktop.udisks2.* +ResultActive=auth_admin +ResultInactive=auth_admin +ResultAny=auth_admin diff --git a/config/simplefiles/CONTESTANT/etc/systemd/timesyncd.conf.d/ntp-server.conf b/config/simplefiles/CONTESTANT/etc/systemd/timesyncd.conf.d/ntp-server.conf new file mode 100644 index 0000000..eeae7b8 --- /dev/null +++ b/config/simplefiles/CONTESTANT/etc/systemd/timesyncd.conf.d/ntp-server.conf @@ -0,0 +1,3 @@ +[Time] +NTP=finals.soi.ch +FallbackNTP=10.0.0.9 diff --git a/config/simplefiles/CONTESTANT/root/.ssh/authorized_keys b/config/simplefiles/CONTESTANT/root/.ssh/authorized_keys new file mode 100644 index 0000000..e69de29 diff --git a/config/simplefiles/CONTESTANT/usr/local/bin/install-client-cert b/config/simplefiles/CONTESTANT/usr/local/bin/install-client-cert new file mode 100755 index 0000000..d486460 --- /dev/null +++ b/config/simplefiles/CONTESTANT/usr/local/bin/install-client-cert @@ -0,0 +1,49 @@ +#!/bin/bash + +# This tool installs the client certificate in Firefox and Chromium. + +username="$1" + +userhome="/home/$username" +certificate="$userhome/.config/clientcert.p12" + +runuser -u "$username" -- mkdir -p "$userhome/.config" +mv "$userhome/clientcert.p12" "$certificate" +chown "$username:$username" "$certificate" + +# Delete all Firefox data +rm -rf "$userhome/.mozilla/" + +# Create an empty profile +runuser -u "$username" -- mkdir -p "$userhome/.mozilla/firefox/main" + +# Tell Firefox to user this profile +cat <"$userhome/.mozilla/firefox/profiles.ini" +[Profile0] +Name=main +IsRelative=1 +Path=main + +[General] +StartWithLastProfile=1 +Version=2 + +[Install3B6073811A6ABF12] +Default=main +Locked=1 + +EOF + +chown "$username:$username" "$userhome/.mozilla/firefox/profiles.ini" + +# Create a certificate database +runuser -u "$username" -- certutil -d "sql:$userhome/.mozilla/firefox/main/" -N --empty-password + +# Import the client certificate +runuser -u "$username" -- pk12util -d "sql:$userhome/.mozilla/firefox/main/" -i "$certificate" -K "" -W "" + +# Do the same for the NSS shared certificate database, used by Chromium +rm -rf "$userhome/.pki/" +runuser -u "$username" -- mkdir -p "$userhome/.pki/nssdb" +runuser -u "$username" -- certutil -d "sql:$userhome/.pki/nssdb/" -N --empty-password +runuser -u "$username" -- pk12util -d "sql:$userhome/.pki/nssdb/" -i "$certificate" -K "" -W "" diff --git a/config/simplefiles/CONTESTANT/usr/share/chromium/initial_bookmarks.html b/config/simplefiles/CONTESTANT/usr/share/chromium/initial_bookmarks.html new file mode 100644 index 0000000..48fbf1b --- /dev/null +++ b/config/simplefiles/CONTESTANT/usr/share/chromium/initial_bookmarks.html @@ -0,0 +1,10 @@ + + +Bookmarks +

Bookmarks

+

+

Bookmarks Bar

+

+

Grader +

+

diff --git a/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/extension.js b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/extension.js new file mode 100644 index 0000000..8e6eaf7 --- /dev/null +++ b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/extension.js @@ -0,0 +1,424 @@ +// Portions of this file are taken from GNOME Shell and adapted. +// Because of that, this gnome extension is distributed under +// the terms of the GNU General Public License, version 2. + + +const { + AccountsService, Atk, Clutter, Gio, + GLib, Graphene, Meta, Shell, St, +} = imports.gi; + +const Background = imports.ui.background; +const Layout = imports.ui.layout; +const Main = imports.ui.main; + +// half of the time for which a frame is displayed +const HALF_FRAME_TIME_MS = 8; + +const BLUR_BRIGHTNESS = 0.55; +const BLUR_SIGMA = 60; + +const POINTER_HIDE_TIMEOUT = 10 * GLib.USEC_PER_SEC; + +let actor; +let lockDialog; +let labelCountdown; +let labelTitle; +let labelMessage; +let labelUser; + +const bgManagers = []; +let backgroundGroup; + +let cursorTracker; +let motionId = 0; +let lastMotionTime = 0; +let pointerHidden = false; +let pointerHideId = 0; + +let user; + +let grab; +let countdownTimeoutId = 0; + +let configFile; +let configMonitor; +let config; +let startTime; + +let isExtensionEnabled = false; +let isActive = false; +let isShellReady = false; +let isActiveChanging = false; + +function extLog (msg) { + log(`[contest-lock] ${msg}`) +} + +function extLogError (msg) { + printerr(`[contest-lock] Error: ${msg}`); +} + +function loadConfig () { + configFile.load_contents_async(null, (obj, res) => { + // If there is a poblem with the config file, log an error and keep + // using the old config. + let newConfig; + try { + const [ok, bytes] = configFile.load_contents_finish(res); + // TextDecoder is used in upstream gnome-shell, but not yet + // supported in current Debian. + const contentStr = imports.byteArray.toString(bytes); + //const contentStr = new TextDecoder().decode(bytes); + newConfig = JSON.parse(contentStr); + } catch (err) { + logError(err, '[contest-lock] config file'); + return; + } + if (!(typeof newConfig === 'object' && newConfig != null)) { + extLogError('config file: invalid format'); + return; + } + if (typeof newConfig.title !== 'string') { + extLogError('config file: "title" must be a string'); + return; + } + if (typeof newConfig.message !== 'string') { + extLogError('config file: "message" must be a string'); + return; + } + if ( + typeof newConfig.startTime !== 'string' || + !/^\d{4,}-\d\d-\d\dT\d\d:\d\d:\d\d\+\d\d:\d\d$/.test(newConfig.startTime) + ) { + extLogError('config file: "startTime" must be a string with format 0000-00-00T00:00:00+00:00'); + return; + } + + extLog('Loaded new config.') + config = newConfig; + startTime = (new Date(newConfig.startTime)).getTime(); + + updateConfig(); + syncActive(); + }); +} + +function syncActive () { + if (isActiveChanging) return; + let beforeStart = false; + if (startTime != null) { + const now = new Date(); + const timeToStart = startTime - now.getTime() - HALF_FRAME_TIME_MS; + beforeStart = timeToStart > 0; + } + // ignore disable event when active + if (beforeStart && isShellReady && (isExtensionEnabled || isActive)) { + activate(); + } else { + deactivate(); + } +} + +function updateConfig () { + if (labelTitle != null) { + labelTitle.text = config.title; + } + if (labelMessage != null) { + labelMessage.text = config.message; + } +} + +function updateUser () { + if (labelUser != null) { + const realName = user.get_real_name(); + if (realName != null) labelUser.text = realName; + } +} + +function updateCountdown () { + countdownTimeoutId = 0; + const now = new Date(); + const nowTime = now.getTime() + HALF_FRAME_TIME_MS; + const timeToStart = startTime - nowTime; + const beforeStart = timeToStart > 0; + if (!beforeStart) { + deactivate(); + return GLib.SOURCE_REMOVE; + } + const allSecondsToStart = Math.floor(timeToStart / 1000); + const secondsToStart = allSecondsToStart % 60 + const allMinutesToStart = Math.floor(allSecondsToStart / 60); + const minutesToStart = allMinutesToStart % 60; + const hoursToStart = Math.floor(allMinutesToStart / 60); + + let hoursString = ''; + if (hoursToStart !== 0) hoursString = `${hoursToStart}∶`; + labelCountdown.text = hoursString + + minutesToStart.toString().padStart(2, '0') + '∶' + + secondsToStart.toString().padStart(2, '0'); + + const nextUpdateTime = 1000 - nowTime % 1000 + countdownTimeoutId = GLib.timeout_add( + GLib.PRIORITY_HIGH, + nextUpdateTime, + updateCountdown + ); + GLib.Source.set_name_by_id(countdownTimeoutId, '[contest-lock] updateCountdown'); + + return GLib.SOURCE_REMOVE; +} + +function updateBackgrounds () { + if (!isActive) return; + while (bgManagers.length) bgManagers.pop().destroy(); + backgroundGroup.destroy_all_children(); + + for (let monitorIndex = 0; monitorIndex < Main.layoutManager.monitors.length; monitorIndex++) { + const monitor = Main.layoutManager.monitors[monitorIndex]; + const widget = new St.Widget({ + style_class: 'screen-shield-background', + x: monitor.x, + y: monitor.y, + width: monitor.width, + height: monitor.height, + effect: new Shell.BlurEffect({ + name: 'blur', + brightness: BLUR_BRIGHTNESS, + sigma: BLUR_SIGMA, + }), + }); + + const bgManager = new Background.BackgroundManager({ + container: widget, + monitorIndex, + controlPosition: false, + }); + + bgManagers.push(bgManager); + + backgroundGroup.add_child(widget); + } +} + +function pointerHideTimer () { + if (pointerHideId !== 0) { + GLib.source_remove(pointerHideId); + pointerHideId = 0; + } + if (!isActive) return GLib.SOURCE_REMOVE; + + const timeToHide = lastMotionTime + POINTER_HIDE_TIMEOUT - GLib.get_monotonic_time(); + if (timeToHide <= 0) { + cursorTracker.set_pointer_visible(false); + pointerHidden = true; + return GLib.SOURCE_REMOVE; + } + + pointerHideId = GLib.timeout_add( + GLib.PRIORITY_HIGH, + timeToHide / 1000 + 20, + pointerHideTimer + ); + GLib.Source.set_name_by_id(pointerHideId, '[contest-lock] pointerHide'); + + return GLib.SOURCE_REMOVE; +} + +function activate () { + if (isActive) return; + isActiveChanging = true; + isActive = true; + + grab = Main.pushModal(Main.uiGroup, { actionMode: Shell.ActionMode.LOCK_SCREEN }); + if (typeof grab === 'boolean') { // gnome 38 + if (!grab) { + grab = Main.pushModal(Main.uiGroup, { + options: Meta.ModalOptions.POINTER_ALREADY_GRABBED, + actionMode: Shell.ActionMode.LOCK_SCREEN + }); + } + if (!grab) { + extLogError('Failed to activate: Could not obtain keyboard grab.'); + return; + } + grab = Main.uiGroup; + } else if ((grab.get_seat_state() & Clutter.GrabState.KEYBOARD) === 0) { + Main.popModal(grab); + grab = null; + extLogError('Failed to activate: Could not obtain keyboard grab.'); + return; + } + + actor.show(); + + Main.sessionMode.pushMode('unlock-dialog'); + + backgroundGroup = new Clutter.Actor(); + + motionId = global.stage.connect('captured-event', (stage, event) => { + if (event.type() === Clutter.EventType.MOTION) { + lastMotionTime = GLib.get_monotonic_time(); + if (pointerHidden) { + cursorTracker.set_pointer_visible(true); + pointerHidden = false; + pointerHideTimer(); + } + } + + return Clutter.EVENT_PROPAGATE; + }); + cursorTracker.set_pointer_visible(false); + pointerHidden = true; + + labelCountdown = new St.Label({ + style_class: 'contest-lock-countdown', + x_align: Clutter.ActorAlign.CENTER, + }); + labelTitle = new St.Label({ + style_class: 'contest-lock-title', + x_align: Clutter.ActorAlign.CENTER, + }); + labelMessage = new St.Label({ + style_class: 'contest-lock-message', + x_align: Clutter.ActorAlign.CENTER, + }); + labelUser = new St.Label({ + style_class: 'contest-lock-user', + x_align: Clutter.ActorAlign.CENTER, + }); + + const stack = new St.BoxLayout({ + style_class: 'contest-lock-stack', + vertical: true, + x_expand: true, + y_expand: true, + x_align: Clutter.ActorAlign.CENTER, + y_align: Clutter.ActorAlign.CENTER, + }) + stack.add_child(labelUser); + stack.add_child(labelCountdown); + stack.add_child(labelTitle); + stack.add_child(labelMessage); + + const mainBox = new St.BoxLayout(); + mainBox.add_constraint(new Layout.MonitorConstraint({ primary: true })); + mainBox.add_child(stack); + + lockDialog = new St.Widget({ + name: 'contestLockDialog', + accessible_role: Atk.Role.WINDOW, + visible: false, + reactive: true, + can_focus: true, + x_expand: true, + y_expand: true, + pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }), + }); + lockDialog.add_child(backgroundGroup); + lockDialog.add_child(mainBox); + + updateConfig(); + updateUser(); + updateCountdown(); + updateBackgrounds(); + + // countdown may have just expired before we called updateCountdown + if (!isActive) return; + + actor.add_child(lockDialog); + lockDialog.show(); + + extLog('Activated.') + isActiveChanging = false; +} + +function deactivate () { + if (!isActive) return; + isActiveChanging = true; + isActive = false; + + if (Main.sessionMode.currentMode === 'unlock-dialog') { + Main.sessionMode.popMode('unlock-dialog'); + } + + Main.popModal(grab); + grab = null; + + if (countdownTimeoutId !== 0) { + GLib.source_remove(countdownTimeoutId); + countdownTimeoutId = 0; + } + + actor.hide(); + labelCountdown = null; + labelTitle = null; + labelMessage = null; + labelUser = null; + while (bgManagers.length) bgManagers.pop().destroy(); + lockDialog.destroy(); + lockDialog = null; + + if (motionId) { + global.stage.disconnect(motionId); + motionId = 0; + } + cursorTracker.set_pointer_visible(true); + + extLog('Deactivated.'); + isActiveChanging = false; +} + +function init (extension) { + actor = Main.layoutManager.screenShieldGroup; + + const userName = GLib.get_user_name(); + user = AccountsService.UserManager.get_default().get_user(userName); + if (!user) return; + + user.connect('notify::is-loaded', updateUser); + user.connect('changed', updateUser); + updateUser(); + + Main.layoutManager.connect('monitors-changed', updateBackgrounds); + + cursorTracker = Meta.CursorTracker.get_for_display(global.display); + + if (!Main.layoutManager._startingUp) { + isShellReady = true; + } else { + Main.layoutManager.connect('startup-complete', () => { + isShellReady = true; + syncActive(); + }); + } + + // TODO: When we drop compatibility with gnome <42, remove this code, + // rename the stylesheet back to stylesheet.css (so that it is loaded + // by the extension system) and add a session-modes property which + // includes unlock-dialog to metadata.json. + const theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); + const stylesheetFile = extension.dir.get_child('stylesheet-always.css'); + theme.load_stylesheet(stylesheetFile); + + // TODO: When we drop compatibility with gnome <42, remove this code. + // gnome 38 has a bug that causes extensions to break when running + // `dconf update` while the screen is locked. + Main.extensionManager.reloadExtension = function () {}; + + configFile = Gio.File.new_for_path('/etc/contest-lock.json'); + configMonitor = configFile.monitor_file(Gio.FileMonitorFlags.NONE, null); + configMonitor.set_rate_limit(1000); + configMonitor.connect('changed', loadConfig); + loadConfig(); +} + +function enable () { + isExtensionEnabled = true; + syncActive(); +} + +function disable () { + isExtensionEnabled = false; + syncActive(); +} diff --git a/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/metadata.json b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/metadata.json new file mode 100644 index 0000000..f0a58cb --- /dev/null +++ b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/metadata.json @@ -0,0 +1,8 @@ +{ + "extension-id": "contest-lock", + "uuid": "contest-lock@soi.ch", + "name": "Contest lock screen", + "description": "A custom lock screen for contests.", + "shell-version": [ "3.38", "42" ], + "url": "" + } diff --git a/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/stylesheet-always.css b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/stylesheet-always.css new file mode 100644 index 0000000..49350b8 --- /dev/null +++ b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/contest-lock@soi.ch/stylesheet-always.css @@ -0,0 +1,24 @@ +.contest-lock-stack { + color: white; + text-align: center; + spacing: 24px; +} + +.contest-lock-countdown { + font-size: 64pt; + font-weight: 300; + font-feature-settings: "tnum"; /* tabular figures */ +} + +.contest-lock-title { + font-size: 16pt; +} + +.contest-lock-user { + font-size: 20pt; +} + +.contest-lock-message { + padding-top: 24px; + font-size: 16pt; +} diff --git a/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/extension.js b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/extension.js new file mode 100644 index 0000000..ae54cea --- /dev/null +++ b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/extension.js @@ -0,0 +1,39 @@ +const { St, Clutter, GLib, Gio, AccountsService } = imports.gi; +const Main = imports.ui.main; + +let panelBin; +let userLabel; + +let user; + +function updateUser () { + const realName = user.get_real_name(); + if (realName != null) userLabel.text = realName; +} + +function init () { + panelBin = new St.Bin({ + style_class: 'panel-bin', + }); + userLabel = new St.Label({ + text: 'No user', + y_align: Clutter.ActorAlign.CENTER, + }); + panelBin.set_child(userLabel); + + const userName = GLib.get_user_name(); + user = AccountsService.UserManager.get_default().get_user(userName); + if (!user) return; + + user.connect('notify::is-loaded', updateUser); + user.connect('changed', updateUser); + updateUser(); +} + +function enable () { + Main.panel._rightBox.insert_child_at_index(panelBin, 0); +} + +function disable () { + Main.panel._rightBox.remove_child(panelBin); +} diff --git a/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/metadata.json b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/metadata.json new file mode 100644 index 0000000..22eb6f7 --- /dev/null +++ b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/metadata.json @@ -0,0 +1,8 @@ +{ + "extension-id": "user-indicator", + "uuid": "user-indicator@soi.ch", + "name": "User indicator", + "description": "Shows the user's real name in the top bar.", + "shell-version": [ "3.38", "42" ], + "url": "" + } diff --git a/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/stylesheet.css b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/stylesheet.css new file mode 100644 index 0000000..77ffc06 --- /dev/null +++ b/config/simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/stylesheet.css @@ -0,0 +1,3 @@ +.panel-bin { + padding-left: 12px; + padding-right: 12px; } diff --git a/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/atom.list b/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/atom.list new file mode 100644 index 0000000..d24e670 --- /dev/null +++ b/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/atom.list @@ -0,0 +1 @@ +deb [arch=amd64 signed-by=/usr/share/keyrings/atom-archive-keyring.gpg] http://packagecloud.io/AtomEditor/atom/any/ any main diff --git a/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/sublime-text.list b/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/sublime-text.list new file mode 100644 index 0000000..e34de97 --- /dev/null +++ b/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/sublime-text.list @@ -0,0 +1 @@ +deb [arch=amd64 signed-by=/usr/share/keyrings/sublimehq-archive-keyring.gpg] http://download.sublimetext.com/ apt/stable/ diff --git a/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/vscode.list b/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/vscode.list new file mode 100644 index 0000000..2efd65a --- /dev/null +++ b/config/simplefiles/PARTICIPANT/etc/apt/sources.list.d/vscode.list @@ -0,0 +1 @@ +deb [arch=amd64,arm64,armhf signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] http://packages.microsoft.com/repos/code stable main diff --git a/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-background b/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-background new file mode 100644 index 0000000..c012346 --- /dev/null +++ b/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-background @@ -0,0 +1,5 @@ +[org/gnome/desktop/background] +picture-uri = 'file:///usr/local/share/backgrounds/wallpaper-soi.svg' +picture-options = 'scaled' +primary-color = '#e6e6e6' +secondary-color = '#555555' diff --git a/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-favorite-apps b/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-favorite-apps new file mode 100644 index 0000000..324cf65 --- /dev/null +++ b/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-favorite-apps @@ -0,0 +1,2 @@ +[org/gnome/shell] +favorite-apps = ['firefox-esr.desktop', 'gnome-terminal.desktop', 'nautilus.desktop'] diff --git a/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-input-sources b/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-input-sources new file mode 100644 index 0000000..bd847a7 --- /dev/null +++ b/config/simplefiles/PARTICIPANT/etc/dconf/db/local.d/00-input-sources @@ -0,0 +1,5 @@ +# Configure the default keyboard layouts shown in the switcher +# According to Wikipedia, the Italian-speaking part of Switzerland also uses the ch+fr layout. +# The first option is the default. +[org/gnome/desktop/input-sources] +sources = [('xkb', 'ch'), ('xkb', 'ch+fr'), ('xkb', 'us')] diff --git a/config/simplefiles/PARTICIPANT/etc/dconf/profile/user b/config/simplefiles/PARTICIPANT/etc/dconf/profile/user new file mode 100644 index 0000000..aca0641 --- /dev/null +++ b/config/simplefiles/PARTICIPANT/etc/dconf/profile/user @@ -0,0 +1,2 @@ +user-db:user +system-db:local diff --git a/config/simplefiles/PARTICIPANT/etc/ssh/sshd_config.d/sshd.conf b/config/simplefiles/PARTICIPANT/etc/ssh/sshd_config.d/sshd.conf new file mode 100644 index 0000000..87f9b80 --- /dev/null +++ b/config/simplefiles/PARTICIPANT/etc/ssh/sshd_config.d/sshd.conf @@ -0,0 +1,2 @@ +PasswordAuthentication no +AllowUsers root diff --git a/config/simplefiles/PARTICIPANT/usr/local/share/backgrounds/wallpaper-soi.svg b/config/simplefiles/PARTICIPANT/usr/local/share/backgrounds/wallpaper-soi.svg new file mode 100644 index 0000000..4599c65 --- /dev/null +++ b/config/simplefiles/PARTICIPANT/usr/local/share/backgrounds/wallpaper-soi.svg @@ -0,0 +1,26 @@ + + + + + + image/svg+xml + + Swiss Olympiad in Informatics + + + + + + Swiss Olympiad in Informatics + + + + + + + + + + + + diff --git a/config/simplefiles/PARTICIPANT/usr/share/keyrings/atom-archive-keyring.gpg b/config/simplefiles/PARTICIPANT/usr/share/keyrings/atom-archive-keyring.gpg new file mode 100644 index 0000000000000000000000000000000000000000..2ab845b97ecc9c9a783d390e894a9a040c3b333e GIT binary patch literal 2826 zcmZ|Pc{CJ^8U}DPcEi}RgcwGQr5RhYWgARnNy%0S!wklZ4B2WBm54qug)A{hglx%9 zD0?)TB5O?cb&xG?-@WIa@0@$i{qH^JdC&9LbAIVS9u{W}s1$&Yi6*?^kty(mcLi)I zUE&!{5*Kj@POq(&-SRwfnLvYFfCB8(g(E$3)kvk2zL z#^Vg3w;Bh?)VNZ<x)Kb!&n}gG$|2al zpW3(0irY`4CX`yHd`^2@FF1T3;w4N$EKSl-O3Zxbm-(Ch(FSQxB^>4iif@l@wRA}2 z18|%B9%po#n{n!{O}v%6+d?0g@yYkflD~+3+(J6`M8q0o8j081wH&RIc%`|%wcrZ% zLqa4*Z3_mvKr&`9B?G6o=S1(*v-eeH^0M=czZ%O+7w^jUypaA0vvfOERQzK06W5dW zq$2l%#rfBfNDyaZdRO0p~sU|1qBdw5QqSGPd|5z zmnV)8jE4IV5Jo`+e^azi5FrrZ{^x|i{@){-;7NpH0x)hw9}M0Hk5Pc=5rYE)2!TO{ z|I?}e5U9l>2mmt4umb-cAy6E_2IAykX9ltfaR52FKrF&QW<U02GO0;^O41wKHy* z$kycy+2=jdHpv5X<;&+b{I#2HVSbqUmq=9Lq4k{Fqk;=%z()&O17CoPW!5>X?9S>A z?DW1{AslR$Q>!Wc#7{=^Qd_oHs#A1P`&k!k+)*oRG%4Pr8xh@c@h&a87O*yTCGj_G zlm1I}T|PROyn<}rxOa3;eh+VYn@Ln&w2hexQl6UF50D;#(d*sc)wEA18kYOzBG1=G zT|@R>FcK58y2dl2p0}2?)v^=(dU$E@4a4gqEo)e+vE@GNqWdNRbH+H#i+!fsqcSCD zYN_(ugz#$vO4`j6RG}7Sc9iLl?R1L7PK~)X9;3qXbWhCEuyxBP-vM*?6|EQoyrqV<;hg|A~RpgQbG&HH$JdMd8Agq1ln(O=H7zYwDOgtZ zW=PH^odY3)2qulfev9;$(1qOnr1gAfg~2d;1^tmFwpA>2FZZ)S^_9?xgcM6}eX*=i zx2@XiYP~jTY!SU?3UVd2Zpa&4du8*+fU9*yjB(X^ z$>5j|wO$7=kJCfLBx8{hueJeqo8hfE>~Yw25iNl2UF0e612iw`VEnr+%eZ;92DgwC zg!_?#xuBDr*}{OsYxQ|VtXwN?g5JsPIrd8$CGrsd8B=AyZ$^@JfkqiA7J+4K(Qa1m zL2$iGBdU|%y&n;!1$rbiW>%zLhDC}{Htw?~E!)Y`yh5aOHcG$|;;gZ`81J>m5nwt1 zp69^)%BNquUn~ZEGZ!O#_4+TX!j&}FVq~_?$=0WMH^rf*Rol|P8rb0v+uOZ7?{}Mu z^#>@GcgIAaFw?$GO68#`^AD{+r5|$Avw%C|mFO8fgDaS8{nlm1Du=~Ph}1hlVo$1K zjPTLdDOlv>Tp(;#`&HI}C5KQ$tY{h~;_$Zo(yzK)?i9Uvv{Bi3f$NPHg0HT7vz!J) z@HE?5&M8qjG0H+Ze;laPOVjJAlhT&4*O0gg^Dy>jHcX%^{P}>EXyN=);=kc~$fD08 z`iBzE|55@6D*Pixn+t^HDW?Dr-)4yE9J4I8!pPOa@#~jHhmSS`b>PZ$ zfxuJ-wkTSD_RH1zIG2;YjBET4{3i6kb>*7uZkIc=S1Mg=YTU$aSmUZt=VY{(^{d2B zVPZkJi5d@pyvv=SvYM9mqrHZ88^3EO#-1ggBB?5bcE(gJ5D&ADRr%t?WYP8*EeheN z*DC2Y2C_`D=-W&<(@{iU1Fq5^2@G9PDP!V2GI-*$ib!ci_$M+x8s1SS3(^)w@&yO| zEZ*fJaqCQ9q}wL&eHqVO-vIXGs~3m zq`*A$#6>5;8L@AncVp~z^xl*Q3I-cUjGUHP#6J7-TzVN6KS&ivKA(Fgdh=lmB>1K6 z^!d&Pp=(8Vzz&%#WBk)r4jhX8`O>4)i8>jq`3KBU}F=aUQmJr;IkTe($I zf@O>9g@=)j&hlfAYz9FaZDqNY3NTdSm!K7}Hu==O#91&+Z0Z>RGnCQyTX>s7Db}ch ze2Us;u9&fVTMy`>T0cI~bu=|Y@>SxD5n~PidBKILy-^2}bw})z=MV8tgJHZ<04~|* z{`63krnoNmj&#DUfp6Fjv)Id|!Vq7qe_x#<9YO;Sd6+z?b?6y+rO6yqx{aS!60 zFgDM)8xS=ox}qdKRx5P+ma&kY6t%ubvj9^`&|Hb0`Q3T-R_&ciy3^0E1Dw<`7=^}b ZfkM@C7=jR7mmJ5eTVCjualcdl@h|k-JSzYI literal 0 HcmV?d00001 diff --git a/config/simplefiles/PARTICIPANT/usr/share/keyrings/microsoft-archive-keyring.gpg b/config/simplefiles/PARTICIPANT/usr/share/keyrings/microsoft-archive-keyring.gpg new file mode 100644 index 0000000000000000000000000000000000000000..0cffae08d061d6ae8959b4442dd2dbce26c340e8 GIT binary patch literal 641 zcmV-{0)G9O0SyFJF<6WN2mrt;hGAw>aTw8-&ZU0T;kCvj9-@p2hRX&3tKIp#mk44K zWSkQ%c4{HQA}s#tsn;1=(LHS^JIEF`F{wkR(&D>9o|7yP=~Y+NKK3;C`4axI=rYyq zrB<*k)BskBDEsDx5Yd^pAvz|*XxLN^Rs1tKcJz?E$yQpt@e`p4a|{c zMCET7wg8i5k#M`dMmXStEMdYRelqXC@i+Karv74@Qsaue67_2{MmJAUtPq zXLDs^b#iHRc|dJxV{&hEZ)S8ZV{dIfi2*eP69EDM9|ZzdF<6WO8v_Ol2?z%R0t6KT z2m=Ea0s#UZ0Rk6*0162Z>pqmNz7i?V8k-0IeXlDmy&evAAJ<zH{duFkO6N3 z&j)GB_6-&>FO*4L(_oK+UEBCNPtqruWb}jtrH<swVkcmkOXxDZta^P4?LQzpSiBd)8vY7{^|QKM#=Rx}B2)KAOc@8S z7Mzv0t^$1t%K~S0RO)*r^H@1F;Q+7l_%^y-I(|o4A8~%iYgyKWXs$SQq3%TuLWerz zb0pl&4*4)XfvKk#57{k%@0(*X$u%!k*^=0cJ;qsI!s?a~ytl{z=13#aaydm)^lWpk zIpB5#Ro`uOrS06fnAvQaGN1XF63$(^x+BU@K8u)zWVb;fhTw4wwj`o$#pA$C*MDap z1$|tQvih1W(&k45XYPBiD%Io?$L3dwLlt8S0%s>$rS>lw#OKHDz z7goCp`C}nuvs+b(*A&@pb(`qWTNyin0p!0m9=x{@xAsaR8P%ypd+#|g)1#Y3@4$Mbj_|}!@DO2^0m9(0vj22R z-vq3JzL9)K)p^25h?VpV06h2UWHUCF{kAHMaSn_#&&a-bhO%UTXlUU;ptD?P$XUw> zg9v{mlbCkco13d)CBQHu#*8s^GWy3hBTj1;=~L5%+v3E&Df{^#U163G`ix~t%VzmP zz+eXz*C6taFIpzk{yxb7T`OY4js#50IRCJ2PK63Q4uVf4!A6NeOR*4|f5mJ+Xm=@B zK0I}2SH1y00R&iPM}g8B@A0E1Ct~G!?h^Zw{YADM!ZD3J>H|ij9&f4=hvG z!>UzMuB^UT6sSvt*$j@cKsz8A!FcrR(~_In%W4c-bz8Qsj}Y55*KD-62t9NR9Q@=uCy=Ne2yRyP_O z{)48cOq(PyN>#53SCCb1^&Rk+7O=d^$3Rj~6vxs(UJ94NE-6`NX>|kJ`vL{Iw62F# z)2@C*bq>Mn0E7ua+^z6(lwFNK?rqbXzxveUV=23ZXo6U-Lrj9b59|_+6u=|MkVV0* zm4B@wb^KC>?<~JN*ac*fTA4%!d?m#qZ*>Ir6RLFbL!E(D_Z5yL^q3|xSwz*FG9l4? zh00$==4bnKTt2(4yv7UUES&3nZiy8mXu{C0hIv777|oHgsWhpGF5Gz5k%TjmXwwEK{u=7+?gQQ%-2!`K^7NQ+Vc#4WyeFjgV> z*e0z{ST>)t2f^9Pw$Cw0CxB>2R?dd))O0x6ZvEX$3IJ} zQWZ;HI5IFjtP;W6)MhebC1|yS{3?Eo^wpT}>xhYMq|9J^Tu8Oi z$EA)Xj57~(^6rZAcKJ36H*!K)@u;loCC%*eQ|y_OKDXy}C|{z?7_<&-9>BT;3viRV zX_?GC+Jf&2AMIGyXDdd(05pl-(u(JAiw#In>|@u89=zCIG<+g)RMV9$ADz#<@!dcG zy(5}pvaa`9!1Ly~aE_wHKgwm=oC=M{_0)P%uOy_03&^*M*p+NI0Io)ruL=a)Ev^6k z0KF@0n(~ZCwFLPcF6=LVm9;jQ2BvJnWOG&Xb}<{f0QuyTDvC}3UH~cq8QF2=e_}%O zsFAx(vG4T+ukPJNgI=IfZObf&(Q1FJMgez28RjHEaW=g45R1q~BB2z2gkSd%01xt0 z4*VZR9w=!~rF#xIdVH7mOJ2Z&D`amlS&muooS+dix+7=gkG3&NB3?wKcEEDfT~67Y zhD;6Hh167AdM*#c(uJx?uOADZvpE1fvWb%rTG-X zw downloads/soi-header.tar.gz +``` + + +Create an ssh key and add the public key to `/srv/soifai/config/simplefiles/CONTESTANT/root/.ssh/authorized_keys`. +``` +ssh-keygen -t ed25519 +``` + + +Invent a password for root on the machines. +Create a password hash for it: +``` +sudo apt install whois +mkpasswd +``` +Take the hash and put it in the `ROOTPW` variable in `class/FAIBASE.var`. + + +## Installing the machines + +Add the required number of hosts to `simplefiles/CONTESTANT/etc/hosts`, and install that file locally: +``` +sudo cp simplefiles/CONTESTANT/etc/hosts /etc/hosts +``` + + +Collect MAC addresses of clients ([guide](https://fai-project.org/fai-guide/#_a_id_mac_a_collecting_ethernet_addresses_for_multiple_hosts)). +Start this command: +``` +tcpdump -qtel broadcast and port bootpc | tee /tmp/mac.list +``` +Now boot all the machines, then press Ctrl+C. +Get a list of all MAC addresses with: +``` +perl -ane 'print "\U$F[0]\n"' /tmp/mac.list|sort|uniq +``` + + +For each machine, run this with the correct hostname and MAC address. +This assigns the hostname and enables installation: +``` +sudo dhcp-edit contestant10 3c:97:0e:1a:09:05 +sudo fai-chboot -IFv -u nfs://10.0.0.9/srv/soifai/config contestant10 +``` + +`dhcp-edit` adds a line to `/etc/dhcp/dhcpd.conf`. +If a you want to change the MAC address associated with a hostname later, you need to edit that file. + +Note: Network booting is disabled after installation completes. To reenable: +``` +sudo fai-chboot -e contestant10 +``` + + +Run FAI monitor to monitor installations: +``` +fai-monitor | fai-monitor-gui - +``` + +Now you are ready to install the machines. +For this, you need to interrupt the boot process and select network booting as booting method. +For network booting to work, Secure Boot needs to be disabled on the machines. + + +Check `/etc/exports` if NFS doesn't work. The IP address range must be correct. +To reload nfs config: `sudo exportfs -ra`. + +Logs are stored in `/var/log/fai/remote-logs`. +Run this so you can read them: +``` +sudo chmod o+rx /var/log/fai/remote-logs +``` + + +In case network booting does not work, you can also boot with a USB stick (FAI-CD): +``` +sudo fai-cd -A autodiscover.iso +sudo dd if=autodiscover.iso of=/dev/sdx bs=1M conv=fsync +``` + +For this to work, `fai-monitor` needs to be running. +The IP address in `/var/log/fai/variables` needs to be correct. + + +## Administrating running machines + +For administrating all machines at the same time, use `parallel-ssh`. +For this, you need a file containing a list of hosts; see `tools/hostlist` for an example. + +Add host keys to your `known_hosts`: +``` +parallel-ssh -h hostlist -O StrictHostKeyChecking=accept-new true +``` + +Disable wifi: +``` +parallel-ssh -h hostlist nmcli radio wifi off +``` +(Comment: Wifi devices are turned on by default, and if you turn it off (through the UI, or with nmcli or rfkill), systemd-rfkill will create a file called e.g. `/var/lib/systemd/rfkill/pci-0000\:02\:00.0-bcma-1\:wlan` with content 1, to remember that *this* device should be turned off. I have not found a way to have *all* wifi devices turned off by default.) + +Test time sync: +``` +parallel-ssh -h hostlist -i date +``` + + +### Performing a soft update + +Do this to apply configuration after you have changed it. + +Open FAI monitor to see progress: +``` +fai-monitor | fai-monitor-gui - +``` +Then: +``` +parallel-ssh -h hostlist -o output --timeout 0 fai -v softupdate +``` +The output of each machine is stored in the folder `output`. + + +While working on the config and testing on a single machine, you can also run a single script, which is faster: +``` +mount -t nfs 10.0.0.9:/srv/soifai/config /var/lib/fai/config +FAI=/var/lib/fai/config target=/ /var/lib/fai/config/scripts/CONTESTANT/10-config +``` + + +### Preparing client certificates + +Prepare the `usernames.csv`. +Each line should contain a username and real name. + +Then run: + +``` +sudo apt install golang-cfssl +./create-certs.sh +``` + +You will need `certs/ca.pem` on the grader. + + +To test the client certificates, you can set up a test server: +``` +sudo apt install nginx +``` + +Edit `/etc/nginx/sites-enabled/default`: + +``` +server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + + include snippets/snakeoil.conf; + ssl_client_certificate /srv/soifai/tools/certs/ca.pem; + ssl_verify_client on; + + root /var/www/html; + index index.html index.htm index.nginx-debian.html; + server_name _; +} +``` + +Then: `sudo systemctl restart nginx.service` + +With this configuration, you should now get an error if you access the server without a valid client certificate. + + +### Starting the contest + +You should stop apt-cacher-ng during contests: `sudo systemctl stop apt-cacher-ng.service` + +Run these commands to prepare the contest +```sh +# Kill user session +parallel-ssh -h hostlist loginctl kill-session 1 +parallel-ssh -h hostlist pkill -KILL -u contestant +# Delete user +parallel-ssh -h hostlist userdel -r contestant +# Recreate user +parallel-ssh -h hostlist adduser --disabled-password --gecos "\"SOI Finals\"" contestant +# Assign users to machines +./assign-user.sh contestant10 stofl +./assign-user.sh contestant11 binna1 +... + +# Adjust the contest lock screen configuration and copy it to all machines +parallel-scp -h hostlist ./contest-lock.json /etc/contest-lock.json + +# Reboot to trigger autologin and clear `/tmp` +parallel-ssh -h hostlist reboot +``` + + +Start backups: +``` +./backup-create.sh timer +``` + + +### If backup machine needed + +Replace `contestant25` with the backup machine name. +Replace `contestantxx` with the old machine (prepare by keeping the assignment of users to machines close by). + +``` +./assign-user.sh contestant25 username +rsync -av --chown contestant:contestant backups/contestantxx/xxxx/ root@contestant25:/home/contestant/ +``` + + +## Replacement exam setup + +We used the laptops owned by SOI for the replacement exams. + +For this, we manually set a static IP address (same as the DHCP assigned one) in the settings on each laptop (it will prompt you for the root password). +That way, it works without the FAI server. + +All the commands in the section "Starting the contest" can then be run from the grader. +You just need to install: `sudo apt install ntp pssh` + + +## Contest setup at Uni Bern + +At Uni Bern, we don't set up the machines from scratch. +Most of the software is already installed for us. + +Copy this repository to the server, and run admin commands from there. +We don't use FAI, instead we just run a script. + +Test on one machine: +``` +rsync --archive --chown root:root --delete --verbose config/ root@chagall.soi:/var/lib/bernconfig/ +ssh root@chagall.soi /var/lib/bernconfig/setup-bern.sh +``` + +Deploy to all machines: +``` +parallel-rsync -h hostlist -x "--archive --chown root:root --delete" config/ /var/lib/bernconfig/ +parallel-ssh -h hostlist -o output /var/lib/bernconfig/setup-bern.sh +``` + +We need to add finals.soi.ch to the hosts file, so copy the file from any machine, add the entry and then deploy it: +``` +parallel-rsync -h hostlist -x "--archive --chown root:root" hosts /etc/hosts +``` + +Otherwise, contest administration works the same. +Run the backup script on the server inside a tmux, so that it continues when your ssh connection breaks. + + +## Training setup + +We also use FAI to set up the SOI laptops for non-contest use. + +In `config/class/50-host-classes`, replace `CONTESTANT` with `TRAINING`. + +You need to set the password for the admin account. +You can find the password in the internal wiki. +If you reinstall all laptops, you can choose a new password and update it in the wiki. +Hash the password with `mkpasswd`, and put the hash in `SUPER_USER_PW` in the file `config/class/TRAINING.var`. +This repo is public, so don't commit the hash. + +Then, install the laptops as in the section "Installing the machines". + + +## Problems and solutions + +This is a list of problems that we had and how we solved them. + +**cpptools VS code extension crashes.** +Fixed by using an older of cpptools, which you can download in the "Version History" tab on the marketplace website. +This happened because we were unknowingly using a pre-release. + +**Network booting fails.** +Fixed by disabling Secure Boot in the system settings. + +**Installed system does not boot.** +Fixed by changing boot mode from legacy/BIOS to UEFI. + +**The first time you boot the installed system, everything is fine, but after a reboot, the screen just shows a blinking cursor.** +Linux is actually running and you can ssh into the machine, but for some unknown reason gdm failed to start. +We don't know why this happens yet, but we have a workaround: Just run `systemctl start gdm` via ssh. +``` +parallel-ssh -h hostlist systemctl start gdm +``` + +**dhcp server not running.** +This happens if the network cable was not plugged in when booting. +``` +systemctl status isc-dhcp-server.service +systemctl restart isc-dhcp-server.service +``` + +**User indicator does not appear** +Fixed by adding the gnome shell version from `gnome-shell --version` to the list of supported versions: `shell-version` in `simplefiles/CONTESTANT/usr/share/gnome-shell/extensions/user-indicator@soi.ch/metadata.json`. +The same applies for the contest-lock extension. + + +## Config space + +The config space defines how the machines are setup. +It is mounted with nfs on the target machine. + +FAI has the concept of *classes*. +Classes are defined by a list of strings. +Order matters, classes are applied in the order in which they are defined. + +We have defined these classes: + +- `PARTICIPANT`: This sets up things that are used for both contest and training. + - various code editors and other tools + - VS Code extensions + - soi header + - Code::Blocks template + - wallpaper + - default favorite apps + - default list of keyboard layouts + - only allow ssh login as root, and disable password auth +- `CONTESTANT`: + - firewall (configured in `simplefiles/CONTESTANT/etc/nftables.conf`) + - disable bluetooth + - disable sleep + - disable lock on blank screen + - disable software update notifications + - disable some panels in gnome-control-center + - add polkit rules which block changing network settings and mounting storage devices (it prompts for the root password) + - configure NTP server + - set `authorized_keys` for root + - enable automatic login + - set browser homepage and bookmarks to https://finals.soi.ch + - add a gnome shell extension which displays the user name in the top bar + - add contest lock gnome shell extension + - add some management scripts to be run via ssh + - add some packages +- `TRAINING`: + - add admin user with sudo rights + - remove APT proxy after packages are installed + +Here is an overview of the file structure: + +- `class`: + First, all scripts in this folder which start with two digits are run. + Of these files, the ones which do not have a `.sh` suffix define the classes. + + FAI then goes through the list of classes and reads variables from the `$class.var` file (if it exists). +- `script`: + This contains a folder of scripts for each class. + In these scripts, we can use these variables: + - `$FAI`: Path to the config space. + - `$target`: The root of the system being installed. + For soft update, this is `/`. + - `$ROOTCMD`: `chroot $target` during install. + For soft update, this is empty. +- `simplefiles`: + This contains a bunch of files for each class that are copied over the root of the target. + (The FAI example config only has `files`, but that is annoying because classes are at the end of the path.) +- `package_config`: + This defines which packages are installed. + + +During the warmup, some participants requested additional VS code extensions. +Because we didn't want them to be enabled for everyone, we put the .vsix files into `simplefiles/CONTESTANT/opt/` and did a soft update, so that they could manually install it from `/opt`. + + +Whenever you add a new script, don't forget to make it executable with `chmod +x script.sh`, otherwise it will silently not be executed. + + +Third-party apt repos are already setup. This is how it was done: +``` +wget -qO - https://packagecloud.io/AtomEditor/atom/gpgkey | gpg --dearmor > simplefiles/PARTICIPANT/usr/share/keyrings/atom-archive-keyring.gpg +wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | gpg --dearmor > simplefiles/PARTICIPANT/usr/share/keyrings/sublimehq-archive-keyring.gpg +wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > simplefiles/PARTICIPANT/usr/share/keyrings/microsoft-archive-keyring.gpg + +echo "deb [arch=amd64 signed-by=/usr/share/keyrings/atom-archive-keyring.gpg] http://packagecloud.io/AtomEditor/atom/any/ any main" > simplefiles/PARTICIPANT/etc/apt/sources.list.d/atom.list +echo "deb [arch=amd64 signed-by=/usr/share/keyrings/sublimehq-archive-keyring.gpg] http://download.sublimetext.com/ apt/stable/" > simplefiles/PARTICIPANT/etc/apt/sources.list.d/sublime-text.list +echo "deb [arch=amd64,arm64,armhf signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] http://packages.microsoft.com/repos/code stable main" > simplefiles/PARTICIPANT/etc/apt/sources.list.d/vscode.list +``` + + +### Contest lock screen + +The contest lock screen is a gnome extension which can lock the screen and show a countdown until the contest starts. +The screen is unlocked when the contest starts. +The lock screen also displays the user name and a title. +It is configured in the file `/etc/contest-lock.json`. +It watches this file, and when it changes the new configuration is instantly applied. + +If there is an error in the config file, it will continue to use the old config and print a message. +To see the logs, run this on a contestant machine: +``` +journalctl -f -o cat /usr/bin/gnome-shell +``` + +An additional text can be shown with the `message` field. It can contain newlines (`\n`). + + +In case there is a problem with the contest lock screen and you can't fix it, the backup solution is to turn off `AutomaticLoginEnable` and set a password instead, that you announce when the contest starts: +``` +parallel-ssh -h hostlist 'chpasswd <<< contestant:stofl' +``` + + +**Development notes** + +Links: +- https://www.codeproject.com/Articles/5271677/How-to-Create-A-GNOME-Extension +- https://gjs.guide/ + +Regular lock screen (contest-lock is based on this): +- https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/screenShield.js +- https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/unlockDialog.js + +Developer commands: +- Restart gnome-shell: Press Alt+F2, enter `r`. Only works if you log in with Xorg. +- Open the gnome-shell developer tools: Press Alt+F2, enter `lg`. + + +## TODO + +- It would be useful to have something like lineinfile from ansible. + FAI has ainsl, but it's not powerful enough. + We could just copy the ansible code and make a cli out of it: + https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/lineinfile.py +- Allow locale change. + The problem is that this requires logging out and back in. + Maybe this could be a feature of contest-lock. + You may also want to install task-german, firefox-esr-l10n-de + (and same for other languages). + + +## License + +This project is distributed under the terms of the GNU General +Public License, version 2. diff --git a/tools/assign-user.sh b/tools/assign-user.sh new file mode 100755 index 0000000..f2e10d6 --- /dev/null +++ b/tools/assign-user.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +machinename="$1" +username="$2" + +machineusername=contestant + +userline=$(grep "^$username;" usernames.csv) +if [ $? -ne 0 ]; then + echo "User $username not found" + exit 1 +fi +fullname=$(echo "$userline" | cut "-d;" -f2) + +# Set real name of machine user +ssh root@"$machinename" chfn --full-name "\"$fullname\"" $machineusername + +# Install client certificate +scp "certs/$username.p12" "root@$machinename:/home/$machineusername/clientcert.p12" +ssh root@"$machinename" install-client-cert $machineusername diff --git a/tools/backup-create.sh b/tools/backup-create.sh new file mode 100755 index 0000000..ac61299 --- /dev/null +++ b/tools/backup-create.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +sleep_secs=120 + +do_backup() { + for hostlogin in $(cat hostlist); do + host=$(echo $hostlogin | cut "-d@" -f2) + echo $host + target=backups/$host/$(date --iso-8601=seconds) + mkdir -p $target + rsync --archive --verbose --prune-empty-dirs --exclude ".*" --exclude "/snap" --exclude "Screenshot from *" --max-size 200K $hostlogin:/home/contestant/ $target + chmod o+rx $target + done +} + +if [ $1 == timer ]; then + while true; do + do_backup + echo + echo "Finished, next backup in $sleep_secs seconds." + echo + echo + sleep $sleep_secs + done +else + do_backup +fi diff --git a/tools/contest-lock.json b/tools/contest-lock.json new file mode 100644 index 0000000..3f34912 --- /dev/null +++ b/tools/contest-lock.json @@ -0,0 +1,5 @@ +{ + "title": "SOI Finals 2023 · Day 1", + "message": "", + "startTime": "2023-05-05T12:00:00+02:00" +} diff --git a/tools/create-certs.sh b/tools/create-certs.sh new file mode 100755 index 0000000..b9dd7d0 --- /dev/null +++ b/tools/create-certs.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# install cfssl + +set -e + +usernames=$(cat usernames.csv | cut "-d;" -f1) + +mkdir -p certs +cd certs + +cat < ca.json +{ + "CN": "SOI Finals Root CA", + "key": { + "algo": "rsa", + "size": 2048 + } +} + +EOF + +cfssl gencert -initca ca.json | cfssljson -bare ca + +cat <client-config.json +{ + "signing": { + "default": { + "expiry": "438000h" + }, + "profiles": { + "client": { + "usages": ["signing", "key encipherment", "digital signature", "client auth"], + "expiry": "438000h" + } + } + } +} + +EOF + +for username in $usernames; do + +cat <client-csr-$username.json +{ + "CN": "$username", + "key": { + "algo": "rsa", + "size": 2048 + } +} + +EOF + +cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=client-config.json -profile=client client-csr-$username.json | cfssljson --bare $username-cert + +openssl pkcs12 -export -in $username-cert.pem -inkey $username-cert-key.pem -out $username.p12 -passout pass: + +done diff --git a/tools/hostlist b/tools/hostlist new file mode 100644 index 0000000..4837b64 --- /dev/null +++ b/tools/hostlist @@ -0,0 +1,19 @@ +root@contestant10 +root@contestant11 +root@contestant12 +root@contestant13 +root@contestant14 +root@contestant15 +root@contestant16 +root@contestant17 +root@contestant18 +root@contestant19 +root@contestant20 +root@contestant21 +root@contestant22 +root@contestant23 +root@contestant24 +root@contestant25 +root@contestant26 +root@contestant27 +root@contestant28 diff --git a/tools/hostlist-bern b/tools/hostlist-bern new file mode 100644 index 0000000..0c4e6f5 --- /dev/null +++ b/tools/hostlist-bern @@ -0,0 +1,21 @@ +root@amiet.soi +root@cezanne.soi +root@muenter.soi +root@yoshitoshi.soi +root@bruegel.soi +root@haring.soi +root@giger.soi +root@constable.soi +root@elgreco.soi +root@helnwein.soi +root@rubens.soi +root@escher.soi + +root@tizian.soi +root@courbet.soi +root@rembrandt.soi +root@duerer.soi + +root@macke.soi +root@chagall.soi +root@renoir.soi diff --git a/tools/hostlist-test b/tools/hostlist-test new file mode 100644 index 0000000..6616a5b --- /dev/null +++ b/tools/hostlist-test @@ -0,0 +1 @@ +root@test40 diff --git a/tools/usernames.csv b/tools/usernames.csv new file mode 100644 index 0000000..094e38a --- /dev/null +++ b/tools/usernames.csv @@ -0,0 +1,2 @@ +stofl;Mouse Stofl +binna1;Mouse Binna