authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-05-15 20:26:18-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-05-15 20:35:26-07:00
log8f1d2e181c2e47008364c10edc1a6692e4ca1bca
tree0b47020cccdc9edf436b607f80a8accbd96504f2
parentf9eb79553ff10e71e7957c722bd47c7e82ccc543
signaturebadge-check Signed by SSH key SHA256:xbd+BjjhyBfwk7GVoURf9Yx0gzDerHbvYv7SddNWmAs

feat: route knot ssh repos through shared git endpoint


2 files changed, 90 insertions(+), 12 deletions(-)

config/forgejo/ssh/keys.py+34-1
...@@ -2,6 +2,7 @@...@@ -2,6 +2,7 @@
2import sys2import sys
3import subprocess3import subprocess
4import re4import re
5import json
56
6user, key_type, key = sys.argv[1:4]7user, key_type, key = sys.argv[1:4]
78
...@@ -41,8 +42,38 @@ def get_key_id(container: str):...@@ -41,8 +42,38 @@ def get_key_id(container: str):
4142
42clover_id = get_key_id("forgejo")43clover_id = get_key_id("forgejo")
43evil_id = get_key_id("evil-forgejo")44evil_id = get_key_id("evil-forgejo")
45knot_did = None
4446
45if not clover_id and not evil_id:47try:
48 result = subprocess.run(
49 [
50 "sudo",
51 "/usr/bin/docker",
52 "exec",
53 "knot",
54 "/usr/bin/knot",
55 "keys",
56 "-output",
57 "json",
58 "-internal-api",
59 "http://localhost:5444",
60 "-git-dir",
61 "/home/git/repositories",
62 "-log-path",
63 "/tmp/knotguard.log",
64 ],
65 capture_output=True,
66 text=True,
67 check=False,
68 )
69 for entry in json.loads(result.stdout):
70 if entry.get("key") == f"{key_type} {key}":
71 knot_did = entry.get("did")
72 break
73except:
74 pass
75
76if not clover_id and not evil_id and not knot_did:
46 sys.exit(0)77 sys.exit(0)
4778
48args: list[str] = []79args: list[str] = []
...@@ -50,6 +81,8 @@ if clover_id:...@@ -50,6 +81,8 @@ if clover_id:
50 args.extend(["--clover", clover_id])81 args.extend(["--clover", clover_id])
51if evil_id:82if evil_id:
52 args.extend(["--evil", evil_id])83 args.extend(["--evil", evil_id])
84if knot_did:
85 args.extend(["--knot", knot_did])
5386
54cmd = "/mnt/storage1/apps/home-infra/config/forgejo/ssh/route.sh " + " ".join(args)87cmd = "/mnt/storage1/apps/home-infra/config/forgejo/ssh/route.sh " + " ".join(args)
55print(88print(
config/forgejo/ssh/route.sh+56-11
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1#!/bin/bash1#!/bin/bash
2clover_id=""2clover_id=""
3evil_id=""3evil_id=""
4knot_did=""
45
5while [ $# -gt 0 ]; do6while [ $# -gt 0 ]; do
6 case "$1" in7 case "$1" in
...@@ -12,6 +13,10 @@ while [ $# -gt 0 ]; do...@@ -12,6 +13,10 @@ while [ $# -gt 0 ]; do
12 evil_id="$2"13 evil_id="$2"
13 shift 214 shift 2
14 ;;15 ;;
16 --knot)
17 knot_did="$2"
18 shift 2
19 ;;
15 *) shift ;;20 *) shift ;;
16 esac21 esac
17done22done
...@@ -20,29 +25,69 @@ repo="${SSH_ORIGINAL_COMMAND#* }"...@@ -20,29 +25,69 @@ repo="${SSH_ORIGINAL_COMMAND#* }"
20repo="${repo%\'*}"25repo="${repo%\'*}"
21repo="${repo#\'}"26repo="${repo#\'}"
22repo="${repo#/}"27repo="${repo#/}"
28repo="${repo%.git}"
29
30if [ -z "$repo" ]; then
31 echo "your git ssh key works :3" >&2
32 exit 1
33fi
34
35git_command="${SSH_ORIGINAL_COMMAND%% *}"
36
37case "$git_command" in
38git-receive-pack | git-upload-pack | git-upload-archive) ;;
39*)
40 echo "invalid git command" >&2
41 exit 1
42 ;;
43esac
2344
24case "$repo" in45case "$repo" in
46did:plc:*)
47 case "${repo#did:plc:}" in
48 *[!a-zA-Z0-9]* | "")
49 echo "invalid repo name: $repo" >&2
50 exit 1
51 ;;
52 esac
53 ;;
25*[!a-zA-Z0-9/_.-]*)54*[!a-zA-Z0-9/_.-]*)
26 echo "invalid repo name: $repo" >&255 echo "invalid repo name: $repo" >&2
27 exit 156 exit 1
28 ;;57 ;;
29*..*)58esac
59
60case "$repo" in
61*..* | /*)
30 echo "invalid repo name: $repo" >&262 echo "invalid repo name: $repo" >&2
31 exit 163 exit 1
32 ;;64 ;;
33/*)65esac
34 echo "invalid repo name: $repo" >&266
35 exit 167route_knot() {
68 [ -z "$knot_did" ] && echo "ssh key is not configured for repository on knot.paperclover.net" >&2 && exit 1
69 exec sudo docker exec -i -u git knot /usr/bin/env \
70 SSH_ORIGINAL_COMMAND="$git_command '$repo'" \
71 SSH_CONNECTION="$SSH_CONNECTION" \
72 /usr/bin/knot guard \
73 -git-dir /home/git/repositories \
74 -user "$knot_did" \
75 -log-path /tmp/knotguard.log \
76 -internal-api http://localhost:5444
77}
78
79case "$repo" in
80did:plc:*)
81 route_knot
82 ;;
83*/*)
84 if [ ! -d "/mnt/storage1/apps/forgejo/git/repositories/${repo}.git" ] && [ ! -d "/mnt/storage1/apps/evil-infra/forgejo/git/repositories/${repo}.git" ]; then
85 route_knot
86 fi
36 ;;87 ;;
37esac88esac
3889
39if [ -z "$repo" ]; then90repo="$repo.git"
40 echo "your git ssh key works :3" >&2
41 exit 1
42fi
43if [[ "$repo" != *".git" ]]; then
44 repo="$repo.git"
45fi
4691
47if [ -d "/mnt/storage1/apps/forgejo/git/repositories/${repo}" ]; then92if [ -d "/mnt/storage1/apps/forgejo/git/repositories/${repo}" ]; then
48 [ -z "$clover_id" ] && echo "ssh key is not configured for repository on git.paperclover.net" >&2 && exit 193 [ -z "$clover_id" ] && echo "ssh key is not configured for repository on git.paperclover.net" >&2 && exit 1