Merge pull request #1199 from pikasTech/fix/1190-ssh-identity-owner

fix: preserve deploy ssh identity target ownership
This commit is contained in:
Lyon
2026-06-28 12:40:58 +08:00
committed by GitHub
+17 -2
View File
@@ -480,6 +480,16 @@ ssh_dir = home_dir / ".ssh"
private_key = str(data.get("privateKey") or "")
public_key = str(data.get("publicKey") or "").strip()
known_hosts = str(data.get("knownHosts") or "")
home_stat = home_dir.stat()
owner_uid = home_stat.st_uid
owner_gid = home_stat.st_gid
def chown_to_home_owner(path):
try:
os.chown(path, owner_uid, owner_gid)
except PermissionError:
if os.geteuid() == 0:
raise
if "PRIVATE KEY-----" not in private_key:
raise SystemExit("invalid private key payload")
@@ -488,6 +498,7 @@ if not public_key.startswith(("ssh-ed25519 ", "ssh-rsa ", "ecdsa-sha2-nistp256 "
ssh_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
os.chmod(ssh_dir, 0o700)
chown_to_home_owner(ssh_dir)
private_path = ssh_dir / "id_ed25519"
public_path = ssh_dir / "id_ed25519.pub"
known_hosts_path = ssh_dir / "known_hosts"
@@ -496,6 +507,8 @@ private_path.write_text(private_key if private_key.endswith("\n") else private_k
public_path.write_text(public_key + "\n")
os.chmod(private_path, stat.S_IRUSR | stat.S_IWUSR)
os.chmod(public_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
chown_to_home_owner(private_path)
chown_to_home_owner(public_path)
derived = subprocess.run(["ssh-keygen", "-y", "-f", str(private_path)], text=True, capture_output=True)
if derived.returncode != 0:
@@ -504,6 +517,7 @@ if derived.stdout.strip() != public_key:
raise SystemExit("installed private key does not match public key")
known_hosts_path.touch(mode=0o600, exist_ok=True)
chown_to_home_owner(known_hosts_path)
subprocess.run(["ssh-keygen", "-R", host, "-f", str(known_hosts_path)], text=True, capture_output=True)
subprocess.run(["ssh-keygen", "-R", f"[{host}]:22", "-f", str(known_hosts_path)], text=True, capture_output=True)
existing = known_hosts_path.read_text().splitlines()
@@ -522,6 +536,7 @@ for line in existing + known_hosts.splitlines():
rows.append(line)
known_hosts_path.write_text("\n".join(rows) + "\n")
os.chmod(known_hosts_path, stat.S_IRUSR | stat.S_IWUSR)
chown_to_home_owner(known_hosts_path)
print(f"github_ssh_identity_written path={private_path} known_hosts_rows={len(rows)}")
`;
}
@@ -610,9 +625,9 @@ async function distributeGithubIdentity(config: UniDeskConfig, target: DeploySsh
`proxy_url=${target.egress.mode === "http-connect-proxy" ? shellQuote(target.egress.proxyUrl) : "''"}`,
"git_ssh_proxy=/tmp/unidesk-git-ssh-http-connect.py",
"if [ \"$egress_mode\" = \"http-connect-proxy\" ]; then",
" curl -fsSI --max-time 20 -x \"$proxy_url\" \"https://$host\" >/dev/null",
" curl -fsSL --max-time 20 -x \"$proxy_url\" \"https://$host\" -o /dev/null",
"else",
" curl -fsSI --max-time 20 \"https://$host\" >/dev/null",
" curl -fsSL --max-time 20 \"https://$host\" -o /dev/null",
"fi",
"if [ \"$egress_mode\" = \"http-connect-proxy\" ]; then",
" cat > \"$git_ssh_proxy\" <<'UNIDESK_GIT_SSH_PROXY'",