From a1e941276ec9e89931e2b8b8048e0c4cc8183361 Mon Sep 17 00:00:00 2001 From: "Michael N. Lipp" Date: Wed, 26 Feb 2025 21:59:38 +0100 Subject: [PATCH] Working login script. --- dev-example/vmop-agent/vmop-agent | 103 ++++++++++++++++++++++++++++-- webpages/vm-operator/pools.md | 65 +++++++++++++++++++ 2 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 webpages/vm-operator/pools.md diff --git a/dev-example/vmop-agent/vmop-agent b/dev-example/vmop-agent/vmop-agent index b3157b9..ad5f427 100755 --- a/dev-example/vmop-agent/vmop-agent +++ b/dev-example/vmop-agent/vmop-agent @@ -1,19 +1,110 @@ #!/usr/bin/bash -hostSerial="/dev/virtio-ports/org.jdrupes.vmop_agent.0" +while [ "$#" -gt 0 ]; do + case "$1" in + --path) shift; ttyPath="$1";; + --path=*) IFS='=' read -r option value <<< "$1"; ttyPath="$value";; + esac + shift +done -if [ ! -w "$hostSerial" ]; then - echo >&2 "Device $hostSerial not writable" +ttyPath="${ttyPath:-/dev/virtio-ports/org.jdrupes.vmop_agent.0}" + +if [ ! -w "$ttyPath" ]; then + echo >&2 "Device $ttyPath not writable" exit 1 fi -if ! exec {con}<>"$hostSerial"; then - echo >&2 "Cannot open device $hostSerial" +if ! exec {con}<>"$ttyPath"; then + echo >&2 "Cannot open device $ttyPath" exit 1 fi +temperr=$(mktemp) +clear >/dev/tty1 echo >&${con} "220 Hello" +createUser() { + local missing=$1 + local uid + local userHome="/home/$missing" + local createOpts="" + if [ -d "$userHome" ]; then + uid=$(ls -ldn "$userHome" | head -n 1 | awk '{print $3}') + createOpts="--no-create-home" + else + uid=$(ls -ln "/home" | tail -n +2 | awk '{print $3}' | sort | tail -1) + uid=$(( $uid + 1 )) + if [ $uid -lt 1000 ]; then + uid=1000 + fi + createOpts="--create-home" + fi + groupadd -g $uid $missing + useradd $missing -u $uid -g $uid $createOpts +} + +doLogin() { + user=$1 + if [ "$user" = "root" ]; then + echo >&${con} "504 Won't log in root" + return + fi + uid=$(id -u ${user} 2>/dev/null) + if [ $? != 0 ]; then + ( flock 200 + createUser ${user} + ) 200>/home/.gen-uid-lock + uid=$(id -u ${user} 2>/dev/null) + if [ $? != 0 ]; then + echo >&${con} "451 Cannot determine uid" + return + fi + fi + systemd-run 2>$temperr \ + --unit vmop-user-desktop --uid=$uid --gid=$uid \ + --working-directory="/home/$user" -p TTYPath=/dev/tty1 \ + -p PAMName=login -p StandardInput=tty -p StandardOutput=journal \ + -E XDG_RUNTIME_DIR="/run/user/$uid" \ + -p ExecStartPre="/usr/bin/chvt 1" \ + dbus-run-session -- gnome-shell --display-server --wayland + if [ $? -eq 0 ]; then + echo >&${con} "201 User logged in" + else + echo >&${con} "451 $(<${temperr})" + fi +} + +attemptLogout() { + systemctl status vmop-user-desktop > /dev/null 2>&1 + if [ $? = 0 ]; then + systemctl stop vmop-user-desktop + echo >&${con} "102 Desktop stopped" + fi +} + +doLogout() { + attemptLogout + loginctl -j | jq -r '.[] | select(.tty=="tty1") | .session' \ + | while read sid; do + loginctl kill-session $sid + done + echo >&${con} "202 User logged out" +} + while read line <&${con}; do - true + case $line in + "login "*) IFS=' ' read -ra args <<< "$line"; doLogin ${args[1]};; + logout) doLogout;; + esac done + +onExit() { + attemptLogout + if [ -n "$temperr" ]; then + rm -f $temperr + fi + echo >&${con} "240 Quit" +} + +trap onExit EXIT diff --git a/webpages/vm-operator/pools.md b/webpages/vm-operator/pools.md new file mode 100644 index 0000000..290d0fd --- /dev/null +++ b/webpages/vm-operator/pools.md @@ -0,0 +1,65 @@ +--- +title: "VM-Operator: VM pools — assigning VMs to users dynamically" +layout: vm-operator +--- + +# VM Pools + +*Since 4.0.0* + +## Prepare the VM + +### Shared file system + +Mount a shared file system as home file system on all VMs in the pool. + +### Restrict access + +The only possibility to access the VMs should be via a desktop started by +the VM-Operator. + + * Disable the display manager. + + ```console + # systemctl disable gdm + # systemctl stop gdm + ``` + + * Disable `getty` on tty1. + + ```console + # systemctl mask getty@tty1 + # systemctl stop getty@tty1 + ``` + + You can, of course, disable `getty` completely. If you do this, make sure + that you can still access your master VM through `ssh`, else you have + locked yourself out. + + * Prevent suspend/hibernate, because it will lock the VM. + + ```console + # systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target + ``` + +### Install the VM-Operator agent + +The VM-Operator agent runs as a systemd service. Sample configuration +files can be found +[here](https://github.com/mnlipp/VM-Operator/tree/main/dev-example/vmop-agent). +Copy + + * `99-vmop-agent.rules` to `/usr/local/lib/udev/rules.d/99-vmop-agent.rules`, + * `vmop-agent` to `/usr/local/libexec/vmop-agent` and + * `vmop-agent.service` to `/usr/local/lib/systemd/system/vmop-agent.service`. + +Note that some of the target directories do not exist by default and have to +be created first. Don't forget to run `restorecon` on systems with SELinux. + +Enable everything: + +```console +# udevadm control --reload-rules +# systemctl enable vmop-agent +# udevadm trigger + ```