Compare commits

...

10 Commits

22 changed files with 122 additions and 45 deletions

1
.gitignore vendored
View File

@ -2,4 +2,5 @@
/osbuild/ /osbuild/
/contestops/certs/ /contestops/certs/
/contestops/backups*
/contestops/local.known_hosts /contestops/local.known_hosts

View File

@ -3,7 +3,7 @@
set -ex set -ex
# Disable WiFi. # Disable WiFi.
parallel-ssh -x "-F local.ssh_config" -h hostlist nmcli radio wifi off # parallel-ssh -x "-F local.ssh_config" -h hostlist nmcli radio wifi off
# Create hosts file so we don't need DNS. # Create hosts file so we don't need DNS.
parallel-scp -x "-F local.ssh_config" -h hostlist ./config-hosts /etc/hosts parallel-scp -x "-F local.ssh_config" -h hostlist ./config-hosts /etc/hosts

View File

@ -2,8 +2,8 @@
Here are instructions and various scripts and files for running contests. Here are instructions and various scripts and files for running contests.
The setup consists of a machine for each contestant, a machine running the grader, and an admin machine. The setup consists of a machine for each contestant, a machine running the grader, and an admin machine (e.g. your personal laptop).
All these should be connected through a network, preferably wired. All these should be connected through a network.
The grader can be a machine accessible over the internet or in the local network. The grader can be a machine accessible over the internet or in the local network.
## Grader setup ## Grader setup
@ -17,7 +17,7 @@ sudo apt install ntpsec
``` ```
Configure the grader to accept client certificates. Configure the grader to accept client certificates.
The CA certificate (`certs/ca.pem`) is generated as part of the admin setup. The CA certificate (`certs/ca.pem`) is generated as part of the admin setup below.
## Contestant machine setup ## Contestant machine setup
@ -36,15 +36,30 @@ The OS is loaded into RAM during boot, so you can remove the stick once the boot
## Network setup ## Network setup
If there is not already an existing network, you need to set it up yourself. If there is not already an existing network, you need to set it up yourself.
Connect all contestant machines and the admin machine to a network switch with LAN cables. You can use either WiFi or wired Ethernet.
If you use multiple switches, don't forget to also link the switches together. WiFi has the advantage that you don't need to bring and install all those Ethernet cables, and avoids the ugly cable mess.
If the grader must be accessed over the internet, you can connect the admin machine to WiFi or USB tethering with a phone. **Ethernet:**
You can then share the internet with the local network. Connect all contestant machines and the admin machine to a network switch with Ethernet cables.
If you use multiple switches, don't forget to also link the switches together, such that the entire network forms a tree.
If you have Gnome, go to Network settings, click on the gear on the Ethernet connection, go to IPv4 tab, and select "Shared to other computers". **WiFi:**
The contestant OS already has a WiFi pre-configured.
The SSID is `contest`, and the password is configured in the `contestant_wifi_password` variable in `os/config/config.toml`.
Configure the access point with this SSID and password, and the machines will connect automatically.
If you have docker installed, this doesn't work yet, because docker blocks routing. For larger contests (10 or more contestants) it's recommended to use a dedicated device as the Internet router.
SOI has a FRITZ!Box 4040 which can be used for this.
Here, you can easily get the list of IP addresses of contestant machines from the web interface.
It's best to connect the admin machine to the router box over LAN instead of WiFi, such that admin traffic only takes one wireless hop instead of two.
For smaller contests, you can also use the admin machine as a router.
For Ethernet, if you have Gnome, go to Network settings, click on the gear on the Ethernet connection, go to IPv4 tab, and select "Shared to other computers".
For WiFi, you can set up a WiFi hotspot in the WiFi settings.
However, with a hotspot enabled, Gnome does not let you connect to a WiFi network for Internet access at the same time, even though the hardware would in many cases support it.
Instead, you can connect a phone to WiFi and to your laptop with USB and enable USB tethering on the phone.
If you have Docker installed, this doesn't work yet, because docker blocks routing.
You can fix it by running the following commands. You can fix it by running the following commands.
```bash ```bash
@ -81,6 +96,8 @@ sudo apt install golang-cfssl
./create-certs.sh ./create-certs.sh
``` ```
## Before the contest
Edit `local.ssh_config` and create an entry with hostname and IP address for each contestant machine. Edit `local.ssh_config` and create an entry with hostname and IP address for each contestant machine.
You can get the IP address by running `ip addr` in a terminal on the contestant machine. You can get the IP address by running `ip addr` in a terminal on the contestant machine.
@ -118,7 +135,16 @@ Assign users to machines.
./assign-user.sh contestant02 binna1 ./assign-user.sh contestant02 binna1
``` ```
You may want to test on one machine that the certificate was properly installed and the grader is accessible.
This should only be done after the machines are configured and users assigned, but with a contest lock start time before the current time.
You can then set the start time and apply the contest lock config again.
```bash
parallel-scp -x "-F local.ssh_config" -h hostlist ./contest-lock.json /etc/contest-lock.json
```
Start periodic backup of contestant machines. Start periodic backup of contestant machines.
Backups are stored every 2 minutes in the folder `backups`.
```bash ```bash
./backup-create.sh timer ./backup-create.sh timer
@ -138,6 +164,19 @@ replacing `contestant03` in the commands below with the spare machine hostname.
rsync -e "ssh -F local.ssh_config" -av --chown contestant:contestant backups/contestantxx/xxxx/ contestant03:/home/contestant/ rsync -e "ssh -F local.ssh_config" -av --chown contestant:contestant backups/contestantxx/xxxx/ contestant03:/home/contestant/
``` ```
## After the contest
Stop the periodic backup command with Ctrl+C.
Rename the `backups` folder to e.g. `backups-day1`.
You can shut down all machines.
```
parallel-ssh -x "-F local.ssh_config" -h hostlist poweroff
```
Machines should be shut down and booted again from USB stick between contests (e.g. between practice and actual contest) to ensure all data is erased.
## Contest lock screen ## 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 contest lock screen is a gnome extension which can lock the screen and show a countdown until the contest starts.

View File

@ -138,6 +138,8 @@ def main():
# Add our own configuration on top. # Add our own configuration on top.
run(["cp", "-rT", f"{script_dir}/layers/participant", "config"]) run(["cp", "-rT", f"{script_dir}/layers/participant", "config"])
if args.variant != "training-installer":
run(["cp", "-rT", f"{script_dir}/layers/live", "config"])
run(["cp", "-rT", f"{script_dir}/layers/{args.variant}", "config"]) run(["cp", "-rT", f"{script_dir}/layers/{args.variant}", "config"])
if args.variant == "training-installer": if args.variant == "training-installer":
@ -172,6 +174,9 @@ def main():
mkdir("config/includes.chroot/root/.ssh") mkdir("config/includes.chroot/root/.ssh")
run(["cp", f"{script_dir}/config/contestant_authorized_keys", "config/includes.chroot/root/.ssh/authorized_keys"]) run(["cp", f"{script_dir}/config/contestant_authorized_keys", "config/includes.chroot/root/.ssh/authorized_keys"])
edit_file("config/includes.chroot/etc/NetworkManager/system-connections/contest.nmconnection",
lambda s: s.replace("@wifi_password@", config["contestant_wifi_password"]))
# Configure boot options. # Configure boot options.
grub_boot_options = '\n'.join( grub_boot_options = '\n'.join(
f'menuentry "{option["label"]}" {{\n' f'menuentry "{option["label"]}" {{\n'

View File

@ -4,3 +4,6 @@ install_admin_password = "$y$j9T$h5VhMd4KkdmbxdZD1gO0N/$1hvwZgO8pQw13Xd6jaNXbtkb
# Example password: soi # Example password: soi
contestant_root_password = "$y$j9T$h5VhMd4KkdmbxdZD1gO0N/$1hvwZgO8pQw13Xd6jaNXbtkbqVOC4W/ia/KXOcCGYvB" contestant_root_password = "$y$j9T$h5VhMd4KkdmbxdZD1gO0N/$1hvwZgO8pQw13Xd6jaNXbtkbqVOC4W/ia/KXOcCGYvB"
# WiFi passwords must be at least 8 characters
contestant_wifi_password = "12345678"

View File

@ -21,10 +21,10 @@ $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-online-accounts-panel.desktop
$DISABLE_DESKTOP /usr/share/applications/gnome-sharing-panel.desktop $DISABLE_DESKTOP /usr/share/applications/gnome-sharing-panel.desktop
# Enable the live system configuration script at boot.
systemctl enable live-config.service
# Disable kexec-tools services. # Disable kexec-tools services.
# We want to load kexec manually, and execution of kexec is already done by systemd. # We want to load kexec manually, and execution of kexec is already done by systemd.
systemctl disable kexec-load.service systemctl disable kexec-load.service
systemctl disable kexec.service systemctl disable kexec.service
# Restrict access to the config which contains the WiFi password.
chmod og= /etc/NetworkManager/system-connections/contest.nmconnection

View File

@ -0,0 +1,20 @@
[connection]
id=contest
uuid=b4b09615-f7b9-4777-baa0-7812d58a01dd
type=wifi
[wifi]
mode=infrastructure
ssid=contest
[wifi-security]
auth-alg=open
key-mgmt=wpa-psk
psk=@wifi_password@
[ipv4]
method=auto
[ipv6]
addr-gen-mode=default
method=auto

View File

@ -7,7 +7,8 @@
polkit.addRule(function (action, subject) { polkit.addRule(function (action, subject) {
if ( if (
action.id.indexOf("org.freedesktop.ModemManager1.") === 0 || action.id.indexOf("org.freedesktop.ModemManager1.") === 0 ||
action.id.indexOf("org.freedesktop.NetworkManager.") === 0 || (action.id.indexOf("org.freedesktop.NetworkManager.") === 0 &&
action.id !== "org.freedesktop.NetworkManager.wifi.scan") ||
action.id === "org.freedesktop.login1.hibernate" || action.id === "org.freedesktop.login1.hibernate" ||
action.id === "org.freedesktop.packagekit.system-network-proxy-configure" || action.id === "org.freedesktop.packagekit.system-network-proxy-configure" ||
action.id.indexOf("org.freedesktop.udisks2.") === 0 action.id.indexOf("org.freedesktop.udisks2.") === 0

View File

@ -10,6 +10,7 @@ const {
const Background = imports.ui.background; const Background = imports.ui.background;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
const ScreenShield = imports.ui.screenShield;
// half of the time for which a frame is displayed // half of the time for which a frame is displayed
const HALF_FRAME_TIME_MS = 8; const HALF_FRAME_TIME_MS = 8;
@ -254,6 +255,14 @@ function activate () {
return; return;
} }
// Monkeypatch disable regular lock screen deactivation.
// It is possible to trigger this function while contest lock is active,
// by pressing Ctrl+Alt+F1. This switches to GDM, which, after the automatic
// login timeout, switches back to our session and emits an Unlock signal.
// If we did not disable it here, this would then partially unlock the screen,
// such that you can interact with the Gnome Shell but not with applications.
ScreenShield.ScreenShield.prototype.deactivate = () => {};
actor.show(); actor.show();
Main.sessionMode.pushMode('unlock-dialog'); Main.sessionMode.pushMode('unlock-dialog');

View File

@ -0,0 +1,13 @@
#!/bin/bash
set -eu
# Enable the live system configuration script at boot.
systemctl enable live-config.service
# Disable automatic apt update.
systemctl disable apt-daily.timer
systemctl disable apt-daily-upgrade.timer
# Disable autostart of Gnome Software background process.
rm /etc/xdg/autostart/org.gnome.Software.desktop

View File

@ -0,0 +1,4 @@
# Disable Gnome Software search provider.
# This is needed to stop Gnome Software from always running in the background.
[org/gnome/desktop/search-providers]
disabled = ['org.gnome.Software.desktop']

View File

@ -0,0 +1,4 @@
{
// Limit cache size to 800 MB to stop it from eating all your RAM.
"C_Cpp.intelliSenseCacheSize": 800
}

View File

@ -32,6 +32,10 @@ for ext in *; do
fi fi
done done
popd popd
# Some extensions contain binaries which must be made executable.
# Because the files are now owned by root, extensions can't do that themselves.
# This just makes all files executable.
chmod --recursive +x /usr/local/lib/vscode-extensions/
# Enable codeblocks template. # Enable codeblocks template.
sed -i 's|// project wizards|RegisterWizard(wizProject, _T("soi"), _T("A SOI task"), _T("Console"));|' /usr/share/codeblocks/templates/wizard/config.script sed -i 's|// project wizards|RegisterWizard(wizProject, _T("soi"), _T("A SOI task"), _T("Console"));|' /usr/share/codeblocks/templates/wizard/config.script

View File

@ -26,6 +26,8 @@ gcc g++ gdb ddd valgrind python3 pypy3
evince gnome-terminal konsole xterm byobu make cmake evince gnome-terminal konsole xterm byobu make cmake
nautilus-extension-gnome-terminal nautilus-extension-gnome-terminal
file-roller file-roller
# video codecs for grader gifs
libavcodec59
# for drawing on screenshots # for drawing on screenshots
drawing drawing
# documentation # documentation

View File

@ -1,6 +0,0 @@
#!/bin/bash
set -eu
# Enable the live system configuration script at boot.
systemctl enable live-config.service

View File

@ -1,3 +0,0 @@
# Disable lock on blank screen
[org/gnome/desktop/screensaver]
lock-enabled = false

View File

@ -1,5 +0,0 @@
# Disable "Updates available" notifications and auto updates.
# Updates which require reboot are useless on live systems,
# and other updates would be installed on each boot.
[org/gnome/software]
allow-updates = false

View File

@ -1,14 +0,0 @@
[Unit]
Description=custom configuration of live system during boot.
Before=basic.target
After=local-fs.target systemd-tmpfiles-setup.service
DefaultDependencies=no
ConditionKernelCommandLine=boot=live
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/live-config
[Install]
WantedBy=basic.target

View File

@ -93,9 +93,10 @@ Here is a list of features.
- timezone - timezone
- list of locales - list of locales
- bootloader background image - bootloader background image
- `training-live` - `live` (all live variants)
- disable lock on blank screen - disable lock on blank screen
- disable software update notifications - disable software update notifications
- `training-live`
- automatic login - automatic login
- sudo without password - sudo without password
- `training-installer` - `training-installer`
@ -111,8 +112,6 @@ Here is a list of features.
- `contestant` - `contestant`
- disable bluetooth - disable bluetooth
- disable sleep - disable sleep
- disable lock on blank screen
- disable software update notifications
- disable some panels in gnome-control-center - disable some panels in gnome-control-center
- disable automatic mounting of storage media - disable automatic mounting of storage media
- polkit rules which block changing network settings and mounting storage media (it prompts for the root password) - polkit rules which block changing network settings and mounting storage media (it prompts for the root password)
@ -120,6 +119,7 @@ Here is a list of features.
- install and configure ssh server - install and configure ssh server
- set root password - set root password
- set `authorized_keys` for root - set `authorized_keys` for root
- contest WiFi connection
- automatic login - automatic login
- set browser homepage and bookmarks to https://contest.soi.ch - set browser homepage and bookmarks to https://contest.soi.ch
- Gnome Shell extension which displays the user name in the top bar - Gnome Shell extension which displays the user name in the top bar