From 44a2d83ae63ba49792295ba5320d89bbf63d6ca9 Mon Sep 17 00:00:00 2001 From: Zebreus Date: Sun, 25 Oct 2026 13:52:32 +0100 Subject: [PATCH] Install the key of the deployer for both accounts The personal key of the deployer goes into the authorized_keys of the root user together with the key of the website, and the deployment makes sure it is in the authorized_keys of the Administrator. Co-Authored-By: Claude Code --- server/README.md | 16 +++++++++------- server/home/.ssh/authorized_keys | 1 + server/resources/.ssh/authorized_keys | 1 + server/scripts/deploy.sh | 25 +++++++++++++++++-------- server/scripts/restore_ssh_access.cmd | 2 ++ 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/server/README.md b/server/README.md index 549af3d..63d668d 100644 --- a/server/README.md +++ b/server/README.md @@ -22,7 +22,8 @@ We only keep the basic user journey working. - `cat README`, `cat README.en`, `cat CODE_OF_CONDUCT` and `cat CODE_OF_CONDUCT.en` always work. The four files are always there and always regular text files. - The website can log in: the key it uses is in `~/.ssh/authorized_keys`. That key gets access to the `root` user - only, never to the Administrator account, whose keys belong to the people who deploy. + only, never to the Administrator account. The keys of the people who deploy - their own key, not the key of the + website - are in the authorized_keys of both accounts. Modifying the four files is allowed; the next cleanup undoes it. Deleting them is not permanent either. @@ -61,8 +62,9 @@ undoes that. ## This directory -- `home/` - the files that belong in the home directory of the user: `~/.zshrc`, `~/.zshenv` and the key in - `~/.ssh/authorized_keys` that the website logs in with. This is where they are edited. +- `home/` - the files that belong in the home directory of the user: `~/.zshrc`, `~/.zshenv` and the keys in + `~/.ssh/authorized_keys` - the one the website logs in with and the ones of the people who deploy. This is where + they are edited. - `resources/` - the copies the cleanup restores from: the four text files and the files of `home/`. - `scripts/make_files.py` - builds the resources. - `scripts/deploy.sh` - deploys the cleanup to the server and installs it. @@ -78,10 +80,10 @@ The resources are built from the website's pages and the files of `home/`: server/scripts/deploy.sh The script logs in as `Administrator` - whose shell is a Windows one - copies the scripts and the resources to the -Administrator's home directory and runs the installer there. It logs in with the personal key of the deployer, from -the agent or from `-i`; the key of the website never gets administrator rights, it only logs in as the root user. -It checks the host key against the one the website pins, and checks that the key in `home/.ssh/authorized_keys` is -the one the website uses. `--uninstall` removes the task again. +Administrator's home directory and runs the installer there. It logs in with the personal key of the deployer, +`~/.ssh/id_ed25519` by default and `-i` for another one; the key of the website never gets administrator rights, it +only logs in as the root user. It checks the host key against the one the website pins, and checks that the key in +`home/.ssh/authorized_keys` is the one the website uses. `--uninstall` removes the task again. The installer can also be run by hand, in an elevated PowerShell on the server: diff --git a/server/home/.ssh/authorized_keys b/server/home/.ssh/authorized_keys index 873f53b..9b81cf8 100644 --- a/server/home/.ssh/authorized_keys +++ b/server/home/.ssh/authorized_keys @@ -1 +1,2 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJDweEH8bhZAHVaAedhTVDb2j/oMEn3vm97xCwCw9LC9 root@nowhere.wirs.ing cygwin-2222 +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBTHzLm8QMhHIo7kFAvtAFnqpspeR3L3gM8kLoG1137 lennart@erms diff --git a/server/resources/.ssh/authorized_keys b/server/resources/.ssh/authorized_keys index 873f53b..9b81cf8 100644 --- a/server/resources/.ssh/authorized_keys +++ b/server/resources/.ssh/authorized_keys @@ -1 +1,2 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJDweEH8bhZAHVaAedhTVDb2j/oMEn3vm97xCwCw9LC9 root@nowhere.wirs.ing cygwin-2222 +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBTHzLm8QMhHIo7kFAvtAFnqpspeR3L3gM8kLoG1137 lennart@erms diff --git a/server/scripts/deploy.sh b/server/scripts/deploy.sh index 5a312c7..03bdaf6 100755 --- a/server/scripts/deploy.sh +++ b/server/scripts/deploy.sh @@ -6,13 +6,13 @@ # The job runs on the box as SYSTEM, never as the root user. The Administrator account sets it up; its shell is a # Windows one, so the commands we run there are Windows commands. # -# The Administrator logs in with the personal key of the deployer, from the agent or from -i. The key of the website -# never gets administrator rights: it only logs in as the root user. +# The Administrator logs in with the personal key of the deployer, by default ~/.ssh/id_ed25519. The key of the +# website never gets administrator rights: it only logs in as the root user. set -euo pipefail HOST=nowhere.wirs.ing USER=Administrator -KEYFILE='' +KEYFILE="$HOME/.ssh/id_ed25519" UNINSTALL=0 while [ $# -gt 0 ]; do @@ -27,9 +27,14 @@ done repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) server="$repo/server" remote='C:\Users\Administrator\kik' # where the installer is put, in the home of the Administrator -remotePath='/c/Users/Administrator/kik' # the same place, as the file transfer sees it +remotePath='/c/Users\Administrator\kik' # the same place, as the file transfer sees it temporary=() +if [ ! -f "$KEYFILE" ]; then + echo "no key file for the login as $USER: $KEYFILE" >&2 + exit 1 +fi + # The host key is the one the website pins, so that the deployment cannot be intercepted. expected=$(sed -n "s/.*const HOST_KEY = '\([^']*\)'.*/\1/p" "$repo/src/scripts/terminal.ts") known=$(mktemp) @@ -49,14 +54,12 @@ temporary+=("$site") boring=$(sed -n "s/.*const boringData = '\([^']*\)'.*/\1/p" "$repo/src/scripts/terminal.ts") printf '%s' "$boring" | base64 -d | tr 'A-Za-z' 'N-ZA-Mn-za-m' > "$site" public=$(ssh-keygen -y -f "$site" | awk 'NF {print $1" "$2}') -authorized=$(awk 'NF {print $1" "$2; exit}' "$server/resources/.ssh/authorized_keys") -if [ "$public" != "$authorized" ]; then +if ! awk 'NF {print $1" "$2}' "$server/resources/.ssh/authorized_keys" | grep -qxF "$public"; then echo "the key in server/resources/.ssh/authorized_keys is not the one the website uses" >&2 exit 1 fi -options=(-o "UserKnownHostsFile=$known" -o StrictHostKeyChecking=yes) -if [ -n "$KEYFILE" ]; then options+=(-i "$KEYFILE"); fi +options=(-i "$KEYFILE" -o "UserKnownHostsFile=$known" -o StrictHostKeyChecking=yes) ssh=(ssh "${options[@]}" "$USER@$HOST") scp=(scp "${options[@]}") @@ -69,3 +72,9 @@ fi "${ssh[@]}" "if not exist $remote mkdir $remote" "${scp[@]}" -r "$server/scripts" "$server/resources" "$USER@$HOST:$remotePath/" "${ssh[@]}" "powershell -NoProfile -ExecutionPolicy Bypass -File $remote\\scripts\\install_restore_task.ps1" + +# The Administrator logs in with the key of the deployer, so that it is there after every deployment. +keyline=$(ssh-keygen -y -f "$KEYFILE") +blob=$(echo "$keyline" | awk 'NF {print $2}') +"${ssh[@]}" "if not exist C:\\Users\\Administrator\\.ssh mkdir C:\\Users\\Administrator\\.ssh" +"${ssh[@]}" "findstr /c:\"$blob\" C:\\Users\\Administrator\\.ssh\\authorized_keys >nul 2>&1 || echo $keyline >> C:\\Users\\Administrator\\.ssh\\authorized_keys" diff --git a/server/scripts/restore_ssh_access.cmd b/server/scripts/restore_ssh_access.cmd index 188d7b4..01e61b6 100644 --- a/server/scripts/restore_ssh_access.cmd +++ b/server/scripts/restore_ssh_access.cmd @@ -4,9 +4,11 @@ REM home of the root user. Run it as Administrator on the box, for example over REM back by itself from then on. setlocal EnableDelayedExpansion set KEY=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJDweEH8bhZAHVaAedhTVDb2j/oMEn3vm97xCwCw9LC9 root@nowhere.wirs.ing cygwin-2222 +set OWN=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBTHzLm8QMhHIo7kFAvtAFnqpspeR3L3gM8kLoG1137 lennart@erms if not exist C:\msys2\home\root\.ssh mkdir C:\msys2\home\root\.ssh > C:\msys2\home\root\.ssh\authorized_keys echo %KEY% +echo %OWN% >> C:\msys2\home\root\.ssh\authorized_keys REM The user owns their .ssh, so that they can add keys of their own. for /f "tokens=5" %%i in ('findstr /b "root:" C:\msys2\etc\passwd') do set SID=%%i