From 06092b947ee3a83e87c35332b3d339a94c0df865 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 15 Aug 2025 22:15:11 +0200 Subject: [PATCH] first version to manage sshkeys This does not yet get autostarted, but this should already allow you to manage your ssh keys in forgejo, and they should work... --- appinfo.yml | 5 ++ forgejo-watch-sshkeys.j2 | 83 ++++++++++++++++++++++++++++++++ forgejo-watch-sshkeys.service.j2 | 13 +++++ 3 files changed, 101 insertions(+) create mode 100644 forgejo-watch-sshkeys.j2 create mode 100644 forgejo-watch-sshkeys.service.j2 diff --git a/appinfo.yml b/appinfo.yml index 8e3fc6e..95c4616 100644 --- a/appinfo.yml +++ b/appinfo.yml @@ -5,6 +5,11 @@ ports: templatefiles: - src: compose.yml.j2 dest: ~/compose.yml + - src: forgejo-watch-sshkeys.j2 + dest: ~/forgejo-watch-sshkeys + mode: "0755" + - src: forgejo-watch-sshkeys.service.j2 + dest: ~/.config/systemd/user/forgejo-watch-sshkeys.service exports: web: sites: diff --git a/forgejo-watch-sshkeys.j2 b/forgejo-watch-sshkeys.j2 new file mode 100644 index 0000000..6c8af01 --- /dev/null +++ b/forgejo-watch-sshkeys.j2 @@ -0,0 +1,83 @@ +#!/usr/bin/python3 + +import os +import time +import re +import sys + +try: + from watchdog.observers import Observer + from watchdog.events import FileSystemEventHandler +except ImportError: + watchdog_installed = False +else: + watchdog_installed = True + +def rewrite_ssh_command(original_command): + return "/usr/bin/podman exec -i -e SSH_ORIGINAL_COMMAND -u git forgejo " + original_command + +def process_file(input_file_path, output_file_path): + with open(input_file_path, 'r') as file: + lines = file.readlines() + + new_lines = [] + for line in lines: + match = re.search(r'(command="([^"]+)")', line.strip()) + if match: + original_command = match.group(2) + new_command = rewrite_ssh_command(original_command) + new_line = line.replace(original_command, new_command) + new_lines.append(new_line) + else: + new_lines.append(line) + + with open(output_file_path, 'w') as file: + file.writelines(new_lines) + + os.chmod(output_file_path, 0o600) + +def watch_file(file_to_watch, callback): + if watchdog_installed: + event_handler = FileChangeHandler(callback) + observer = Observer() + observer.schedule(event_handler, path=os.path.dirname(file_to_watch), recursive=False) + observer.start() + try: + while True: + time.sleep(3600) + except KeyboardInterrupt: + observer.stop() + observer.join() + else: + print("Watchdog not installed. Using polling method. This is not optimal, please install the python module watchdog for better performance") + last_modified_time = os.path.getmtime(file_to_watch) + + while True: + current_modified_time = os.path.getmtime(file_to_watch) + if current_modified_time != last_modified_time: + print(f"{file_to_watch} has been modified. Executing callback...") + callback() + last_modified_time = current_modified_time + time.sleep(3) + +if __name__ == "__main__": + if os.getuid() != 0 or '_CONTAINERS_ROOTLESS_UID' not in os.environ: + print("This program needs to be root of your user namespace in order to have the correct permissions") + print("start this program with podman unshare " + sys.argv[0]) + sys.exit(1) + + input_file = "{{ homedir }}/data/git/.ssh/authorized_keys" + output_file = "{{ homedir }}/.ssh/authorized_keys" + + output_dir = os.path.dirname(output_file) + if not os.path.exists(output_dir): + os.makedirs(output_dir) + os.chmod(output_dir, 0o700) + + def callback_function(): + process_file(input_file, output_file) + + # ensure it is at least processed once... + process_file(input_file, output_file) + + watch_file(input_file, callback_function) diff --git a/forgejo-watch-sshkeys.service.j2 b/forgejo-watch-sshkeys.service.j2 new file mode 100644 index 0000000..6441366 --- /dev/null +++ b/forgejo-watch-sshkeys.service.j2 @@ -0,0 +1,13 @@ +[Unit] +Description=Podman Compose based service +After=network.target + +[Service] +Type=exec +# The command must be executed as "root", as the git directory is not readable by a regular user +ExecStart=podman unshare {{ homedir }}/forgejo-watch-sshkeys +Restart=always +WorkingDirectory={{ homedir }} + +[Install] +WantedBy=default.target