From 52167db085392ef4cbc40bc9d1707966faed4475 Mon Sep 17 00:00:00 2001 From: Wyatt Date: Mon, 17 Aug 2026 11:22:24 -0400 Subject: [PATCH] Re-assert 0600 on deploy key files at every materialize O_CREAT's mode only applies to brand-new files, so a key whose permissions were widened externally (e.g. a k8s fsGroup remount chmodding volume files to group-rw) stayed 0660 forever and ssh refused it. fchmod on each rewrite makes materialize_private_key self-heal. --- src/handler/sshkeys.py | 4 ++++ tests/test_git_servers.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/handler/sshkeys.py b/src/handler/sshkeys.py index 8a6cf8d..5528892 100644 --- a/src/handler/sshkeys.py +++ b/src/handler/sshkeys.py @@ -53,6 +53,10 @@ def materialize_private_key(hostname: str, private_key: str) -> str: private_key += "\n" fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) with os.fdopen(fd, "w") as fh: + # O_CREAT's mode only applies to brand-new files; an existing file keeps + # whatever mode something else gave it (e.g. a k8s fsGroup remount adding + # group rw), and ssh refuses keys readable beyond the owner. + os.fchmod(fd, 0o600) fh.write(private_key) return path diff --git a/tests/test_git_servers.py b/tests/test_git_servers.py index c5f5c76..a42e1b4 100644 --- a/tests/test_git_servers.py +++ b/tests/test_git_servers.py @@ -80,6 +80,18 @@ def test_materialize_private_key_is_0600_under_projects_root(env): assert fh.read() == "KEYDATA\n" +def test_materialize_resets_mode_on_existing_file(env): + # A k8s fsGroup remount (fsGroupChangePolicy: Always) chmods volume files to + # group-rw between pod starts; rematerializing must restore 0600 or ssh + # refuses the key. + from handler import sshkeys + + path = sshkeys.materialize_private_key("github.com", "KEYDATA") + os.chmod(path, 0o660) + path = sshkeys.materialize_private_key("github.com", "KEYDATA") + assert stat.S_IMODE(os.stat(path).st_mode) == 0o600 + + def test_materialize_sanitizes_hostname(env): from handler import sshkeys