Fix SSH key generation and extraction

fixes2
Vadim vtroshchinskiy 2024-11-12 13:29:35 +01:00
parent e4d954ef4e
commit 36f9dee503
1 changed files with 104 additions and 37 deletions

View File

@ -2,6 +2,10 @@
"""Script para la instalación del repositorio git"""
import os
import sys
sys.path.insert(0, "/opt/opengnsys/python3/dist-packages")
import shutil
import argparse
import tempfile
@ -13,6 +17,8 @@ import grp
from termcolor import cprint
import git
import libarchive
from libarchive.extract import *
#from libarchive.entry import FileType
import urllib.request
import pathlib
@ -20,6 +26,7 @@ import socket
import time
import requests
import tempfile
import hashlib
#FORGEJO_VERSION="8.0.3"
FORGEJO_VERSION="9.0.0"
@ -126,8 +133,13 @@ class OpengnsysGitInstaller:
self.temp_dir = None
self.script_path = os.path.realpath(os.path.dirname(__file__))
# Possible names for SSH key
# Possible names for SSH public keys
self.ssh_key_users = ["root", "opengnsys"]
self.key_names = ["id_rsa.pub", "id_ed25519.pub", "id_ecdsa.pub", "id_ed25519_sk.pub", "id_ecdsa_sk.pub"]
# Possible names for SSH key in oglive
self.key_paths = ["scripts/ssl/id_rsa.pub", "scripts/ssl/id_ed25519.pub", "scripts/ssl/id_ecdsa.pub", "scripts/ssl/id_ed25519_sk.pub", "scripts/ssl/id_ecdsa_sk.pub"]
self.key_paths_dict = {}
for kp in self.key_paths:
@ -306,7 +318,11 @@ class OpengnsysGitInstaller:
for file in initrd:
self.__logger.debug("Archivo: %s", file)
if file.pathname in self.key_paths_dict:
pathname = file.pathname;
if pathname.startswith("./"):
pathname = pathname[2:]
if pathname in self.key_paths_dict:
data = bytearray()
for block in file.get_blocks():
data = data + block
@ -340,51 +356,102 @@ class OpengnsysGitInstaller:
temp_dir = tempfile.TemporaryDirectory()
#temp_dir_path = temp_dir.name()
client_key = os.path.join(temp_dir.name, "id_ed25519")
self.__logger.debug("Writing new SSH key into %s", client_key)
subprocess.run(["/usr/bin/ssh-keygen", "-t", "ed25519", "-N", "", "-f", client_key], check=True)
keydata_priv = None
with open(client_key, "rb") as client_file:
keydata_priv = client_file.read()
keydata_pub = None
with open(client_key + ".pub", "rb") as client_file:
keydata_pub = client_file.read()
temp_dir_path = "/tmp/extracted"
if os.path.exists(temp_dir_path):
shutil.rmtree(temp_dir_path)
self.__logger.debug("Writing new initrd into %s", client_initrd_path_new)
pathlib.Path(temp_dir_path).mkdir(parents=True, exist_ok = True)
with libarchive.file_reader(client_initrd_path) as orig_initrd:
#self.__logger.debug("Original initrd was format %s", orig_initrd.format_name)
with libarchive.file_writer(client_initrd_path_new, "cpio") as new_initrd:
self.__logger.info("Uncompressing initrd %s into %s", client_initrd_path, temp_dir_path)
os.chdir(temp_dir_path)
libarchive.extract_file(client_initrd_path, flags = EXTRACT_UNLINK | EXTRACT_OWNER | EXTRACT_PERM | EXTRACT_FFLAGS | EXTRACT_TIME)
ssh_key_dir = os.path.join(temp_dir_path, "scripts", "ssl")
for file in orig_initrd:
self.__logger.debug("File: %s, type %i", file, file.filetype)
client_key_path = os.path.join(ssh_key_dir, "id_ed25519")
authorized_keys_path = os.path.join(ssh_key_dir, "authorized_keys")
if file.isreg():
data = bytearray()
for block in file.get_blocks():
data = data + block
pathlib.Path(ssh_key_dir).mkdir(parents=True, exist_ok=True)
if os.path.exists(client_key_path):
self.__logger.debug("Creating SSH key not necessary, it already is in the initrd")
else:
self.__logger.debug("Writing new SSH key into %s", client_key_path)
subprocess.run(["/usr/bin/ssh-keygen", "-t", "ed25519", "-N", "", "-f", client_key_path], check=True)
self.__logger.debug("Adding pathname %s, len %i", file.pathname, len(data))
new_initrd.add_file_from_memory(file.pathname, len(data), bytes(data), permission = file.mode, mtime=file.mtime, ctime=file.ctime)
elif file.isdir():
file.modi
self.__logger.debug("Pathname %s is a directory", file.pathname)
elif file.islnk():
self.__logger.debug("Pathname %s is a symlink", file.pathname)
None
else:
self.__logger.error("Unhandled file type %s", str(file.filetype))
public_keys = ""
new_initrd.add_file_from_memory("scripts/ssl/id_ed25519.pub", len(keydata_pub), keydata_pub)
new_initrd.add_file_from_memory("scripts/ssl/id_ed25519", len(keydata_priv), keydata_priv)
new_initrd.add_file_from_memory()
for username in self.ssh_key_users:
self.__logger.debug("Looking for keys in user %s", username)
homedir = pwd.getpwnam(username).pw_dir
for key in self.key_names:
key_path = os.path.join(homedir, ".ssh", key)
self.__logger.debug("Checking if we have %s...", key_path)
if os.path.exists(key_path):
with open(key_path, "r", encoding='utf-8') as public_key_file:
self.__logger.info("Adding %s to authorized_keys", key_path)
public_key = public_key_file.read()
public_keys = public_keys + public_key + "\n"
self.__logger.debug("Writing %s", authorized_keys_path)
with open(authorized_keys_path, "w", encoding='utf-8') as auth_keys:
auth_keys.write(public_keys)
# hardlinks in the source package are not correctly packaged back as hardlinks.
# Taking the easy option of turning them into symlinks for now.
file_hashes = {}
with libarchive.file_writer(client_initrd_path_new, "cpio_newc", "zstd") as writer:
file_list = []
for root, subdirs, files in os.walk(temp_dir_path):
proot = pathlib.PurePosixPath(root)
relpath = proot.relative_to(temp_dir_path)
for file in files:
full_path = os.path.join(relpath, file)
#self.__logger.debug("%s", full_path)
digest = None
stat_data = os.stat(full_path)
with open(full_path, "rb") as in_file:
digest = hashlib.file_digest(in_file, "sha256").hexdigest()
if stat_data.st_size > 0 and not os.path.islink(full_path):
if digest in file_hashes:
target_path = pathlib.Path(file_hashes[digest])
link_path = target_path.relative_to(relpath, walk_up=True)
self.__logger.debug("%s was a duplicate of %s, linking to %s", full_path, file_hashes[digest], link_path)
os.unlink(full_path)
#os.link(file_hashes[digest], full_path)
os.symlink(link_path, full_path)
else:
file_hashes[digest] = full_path
writer.add_files(".", recursive=True )
os.rename(client_initrd_path, client_initrd_path + ".old")
if os.path.exists(client_initrd_path + ".sum"):
os.rename(client_initrd_path + ".sum", client_initrd_path + ".sum.old")
os.rename(client_initrd_path_new, client_initrd_path)
with open(client_initrd_path, "rb") as initrd_file:
hexdigest = hashlib.file_digest(initrd_file, "sha256").hexdigest()
with open(client_initrd_path + ".sum", "w", encoding="utf-8") as digest_file:
digest_file.write(hexdigest)
self.__logger.info("Updated initrd %s", client_initrd_path)
def install(self):
"""Instalar