|
|
|
@ -3,7 +3,7 @@
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
sys.path.insert(0, "/opt/opengnsys/python3/dist-packages")
|
|
|
|
|
sys.path.insert(0, "/usr/share/opengnsys-modules/python3/dist-packages")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import shutil
|
|
|
|
@ -27,6 +27,7 @@ import time
|
|
|
|
|
import requests
|
|
|
|
|
import tempfile
|
|
|
|
|
import hashlib
|
|
|
|
|
import datetime
|
|
|
|
|
|
|
|
|
|
#FORGEJO_VERSION="8.0.3"
|
|
|
|
|
FORGEJO_VERSION="9.0.0"
|
|
|
|
@ -81,6 +82,7 @@ class Oglive:
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.__logger = logging.getLogger("Oglive")
|
|
|
|
|
|
|
|
|
|
self.binary = "/opt/opengnsys/bin/oglivecli"
|
|
|
|
|
self.__logger.debug("Inicializando")
|
|
|
|
|
|
|
|
|
@ -292,7 +294,65 @@ class OpengnsysGitInstaller:
|
|
|
|
|
raise TimeoutError("Timed out waiting for connection!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _extract_ssh_key(self):
|
|
|
|
|
def add_ssh_key_from_squashfs(self, oglive_num = None):
|
|
|
|
|
|
|
|
|
|
if oglive_num is None:
|
|
|
|
|
self.__logger.info("Using default oglive")
|
|
|
|
|
oglive_num = int(self.oglive.get_default())
|
|
|
|
|
else:
|
|
|
|
|
self.__logger.info("Using oglive %i", oglive_num)
|
|
|
|
|
|
|
|
|
|
oglive_client = self.oglive.get_clients()[str(oglive_num)]
|
|
|
|
|
self.__logger.info("Oglive is %s", oglive_client)
|
|
|
|
|
|
|
|
|
|
keys = installer.extract_ssh_keys(oglive_num = oglive_num)
|
|
|
|
|
for k in keys:
|
|
|
|
|
timestamp = '{:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())
|
|
|
|
|
installer.add_forgejo_sshkey(k, f"Key for {oglive_client} ({timestamp})")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extract_ssh_keys(self, oglive_num = None):
|
|
|
|
|
public_keys = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
squashfs = "ogclient.sqfs"
|
|
|
|
|
|
|
|
|
|
tftp_dir = os.path.join(self.base_path, "tftpboot")
|
|
|
|
|
|
|
|
|
|
if oglive_num is None:
|
|
|
|
|
self.__logger.info("Reading from default oglive")
|
|
|
|
|
oglive_num = self.oglive.get_default()
|
|
|
|
|
else:
|
|
|
|
|
self.__logger.info("Reading from oglive %i", oglive_num)
|
|
|
|
|
|
|
|
|
|
oglive_client = self.oglive.get_clients()[str(oglive_num)]
|
|
|
|
|
self.__logger.info("Oglive is %s", oglive_client)
|
|
|
|
|
|
|
|
|
|
client_squashfs_path = os.path.join(tftp_dir, oglive_client, squashfs)
|
|
|
|
|
|
|
|
|
|
self.__logger.info("Mounting %s", client_squashfs_path)
|
|
|
|
|
mount_tempdir = tempfile.TemporaryDirectory()
|
|
|
|
|
ssh_keys_dir = os.path.join(mount_tempdir.name, "root", ".ssh")
|
|
|
|
|
|
|
|
|
|
subprocess.run(["mount", client_squashfs_path, mount_tempdir.name], check=True)
|
|
|
|
|
for file in os.listdir(ssh_keys_dir):
|
|
|
|
|
full_path = os.path.join(ssh_keys_dir, file)
|
|
|
|
|
|
|
|
|
|
if file.endswith(".pub"):
|
|
|
|
|
self.__logger.info("Found public key: %s", full_path)
|
|
|
|
|
|
|
|
|
|
with open(full_path, "r", encoding="utf-8") as keyfile:
|
|
|
|
|
keydata = keyfile.read().strip()
|
|
|
|
|
public_keys = public_keys + [keydata]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
subprocess.run(["umount", mount_tempdir.name], check=True)
|
|
|
|
|
|
|
|
|
|
return public_keys
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _extract_ssh_key_from_initrd(self):
|
|
|
|
|
public_key=""
|
|
|
|
|
|
|
|
|
|
INITRD = "oginitrd.img"
|
|
|
|
@ -335,7 +395,7 @@ class OpengnsysGitInstaller:
|
|
|
|
|
|
|
|
|
|
return public_key
|
|
|
|
|
|
|
|
|
|
def set_ssh_key(self, client_num = None):
|
|
|
|
|
def set_ssh_key_in_initrd(self, client_num = None):
|
|
|
|
|
INITRD = "oginitrd.img"
|
|
|
|
|
|
|
|
|
|
tftp_dir = os.path.join(self.base_path, "tftpboot")
|
|
|
|
@ -420,12 +480,21 @@ class OpengnsysGitInstaller:
|
|
|
|
|
relpath = proot.relative_to(temp_dir_path)
|
|
|
|
|
|
|
|
|
|
for file in files:
|
|
|
|
|
abs_path = os.path.join(root, file)
|
|
|
|
|
full_path = os.path.join(relpath, file)
|
|
|
|
|
|
|
|
|
|
#self.__logger.debug("%s", full_path)
|
|
|
|
|
#self.__logger.debug("%s", abs_path)
|
|
|
|
|
digest = None
|
|
|
|
|
|
|
|
|
|
stat_data = os.stat(full_path)
|
|
|
|
|
if os.path.islink(abs_path):
|
|
|
|
|
self.__logger.debug("%s is a symlink", abs_path)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(abs_path):
|
|
|
|
|
self.__logger.debug("%s does not exist", abs_path)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
stat_data = os.stat(abs_path)
|
|
|
|
|
with open(full_path, "rb") as in_file:
|
|
|
|
|
digest = hashlib.file_digest(in_file, "sha256").hexdigest()
|
|
|
|
|
|
|
|
|
@ -461,7 +530,9 @@ class OpengnsysGitInstaller:
|
|
|
|
|
self.__logger.info("Updated initrd %s", client_initrd_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.add_forgejo_sshkey(oglive_public_key, "Key for " + ogclient)
|
|
|
|
|
timestamp = '{:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())
|
|
|
|
|
|
|
|
|
|
self.add_forgejo_sshkey(oglive_public_key, f"Key for {ogclient} ({timestamp})")
|
|
|
|
|
|
|
|
|
|
def install(self):
|
|
|
|
|
"""Instalar
|
|
|
|
@ -507,67 +578,6 @@ class OpengnsysGitInstaller:
|
|
|
|
|
self.__logger.debug("Instalando dependencias")
|
|
|
|
|
subprocess.run(["apt-get", "install", "-y", "git"], check=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Autenticación del usuario opengnsys con clave pública desde los ogLive
|
|
|
|
|
# Requiere que todos los ogLive tengan la misma clave publica (utilizar setsslkey)
|
|
|
|
|
|
|
|
|
|
# Tomamos la clave publica del cliente por defecto
|
|
|
|
|
default_num = self.oglive.get_default()
|
|
|
|
|
default_client = self.oglive.get_clients()[default_num]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client_initrd_path = os.path.join(tftp_dir, default_client, INITRD)
|
|
|
|
|
self.__logger.debug("Ruta de initrd: %s", client_initrd_path)
|
|
|
|
|
# Si me salgo con error borro el directorio temporal
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not self.ignoresshkey:
|
|
|
|
|
public_key = self._extract_ssh_key()
|
|
|
|
|
|
|
|
|
|
# Si la clave publica no existe me salgo con error
|
|
|
|
|
if not public_key:
|
|
|
|
|
raise RequirementException(f"No se encuentra clave pública dentro del ogLive en {self.temp_dir}, imagen {client_initrd_path}. Rutas buscadas: {self.key_paths}\n" +
|
|
|
|
|
"Los oglive deben tener la misma clave pública (utilizar setsslkey)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ssh_dir = os.path.join(self.ssh_homedir, ".ssh")
|
|
|
|
|
authorized_keys_file = os.path.join(ssh_dir, "authorized_keys")
|
|
|
|
|
|
|
|
|
|
self.__logger.debug("Configurando ssh: Agregando clave %s a %s", public_key, authorized_keys_file)
|
|
|
|
|
self.__logger.debug("Key: %s", public_key)
|
|
|
|
|
os.makedirs(ssh_dir, exist_ok=True)
|
|
|
|
|
self._add_line_to_file(authorized_keys_file, public_key)
|
|
|
|
|
|
|
|
|
|
os.chmod(authorized_keys_file, 0o600)
|
|
|
|
|
os.chown(ssh_dir, uid=self.ssh_uid, gid=self.ssh_gid)
|
|
|
|
|
os.chown(authorized_keys_file, uid=self.ssh_uid, gid=self.ssh_gid)
|
|
|
|
|
|
|
|
|
|
# Configuramos el servicio ssh para que permita el acceso con clave pública
|
|
|
|
|
self.__logger.info(" Configuramos el servicio ssh para que permita el acceso con clave pública.")
|
|
|
|
|
with open("/etc/ssh/sshd_config", "r") as f:
|
|
|
|
|
sshd_config = f.read()
|
|
|
|
|
sshd_config = sshd_config.replace("PubkeyAuthentication no", "PubkeyAuthentication yes")
|
|
|
|
|
with open("/etc/ssh/sshd_config", "w") as f:
|
|
|
|
|
f.write(sshd_config)
|
|
|
|
|
os.system("systemctl reload ssh")
|
|
|
|
|
|
|
|
|
|
# Instalamos git
|
|
|
|
|
os.system("apt install git")
|
|
|
|
|
|
|
|
|
|
# Para que el usuario sólo pueda usar git (no ssh)
|
|
|
|
|
SHELL = shutil.which("git-shell")
|
|
|
|
|
os.system(f"usermod -s {SHELL} opengnsys")
|
|
|
|
|
|
|
|
|
|
# Creamos repositorios
|
|
|
|
|
#self.init_git_repo('windows.git')
|
|
|
|
|
#self.init_git_repo('linux.git')
|
|
|
|
|
#self.init_git_repo('mac.git')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Damos permiso al usuario opengnsys
|
|
|
|
|
#for DIR in ["base.git", "linux.git", "windows.git"]: #, "LinAcl", "WinAcl"]:
|
|
|
|
|
# self._recursive_chown(os.path.join(ogdir_images, DIR), ouid=self.ssh_uid, ogid=self.ssh_gid)
|
|
|
|
|
|
|
|
|
|
def _install_template(self, template, destination, keysvalues):
|
|
|
|
|
|
|
|
|
|
self.__logger.info("Writing template %s into %s", template, destination)
|
|
|
|
@ -615,12 +625,9 @@ class OpengnsysGitInstaller:
|
|
|
|
|
self.__logger.debug("Stopping opengnsys-forgejo service")
|
|
|
|
|
subprocess.run(["systemctl", "stop", "opengnsys-forgejo"], check=False)
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(bin_path):
|
|
|
|
|
self.__logger.debug("Downloading from %s into %s", FORGEJO_URL, bin_path)
|
|
|
|
|
urllib.request.urlretrieve(FORGEJO_URL, bin_path)
|
|
|
|
|
os.chmod(bin_path, 0o755)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.__logger.debug("Downloading from %s into %s", FORGEJO_URL, bin_path)
|
|
|
|
|
urllib.request.urlretrieve(FORGEJO_URL, bin_path)
|
|
|
|
|
os.chmod(bin_path, 0o755)
|
|
|
|
|
|
|
|
|
|
if os.path.exists(forgejo_db_path):
|
|
|
|
|
self.__logger.debug("Removing old configuration")
|
|
|
|
@ -709,7 +716,7 @@ class OpengnsysGitInstaller:
|
|
|
|
|
token_file.write(token)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ssh_key = self._extract_ssh_key()
|
|
|
|
|
ssh_key = self._extract_ssh_key_from_initrd()
|
|
|
|
|
|
|
|
|
|
self.add_forgejo_sshkey(ssh_key, "Default key")
|
|
|
|
|
|
|
|
|
@ -742,7 +749,7 @@ class OpengnsysGitInstaller:
|
|
|
|
|
with open(os.path.join(self.base_path, "etc", "ogGitApiToken.cfg"), "r", encoding='utf-8') as token_file:
|
|
|
|
|
token = token_file.read().strip()
|
|
|
|
|
|
|
|
|
|
self.__logger.info("Adding SSH key to Forgejo: %s", pubkey)
|
|
|
|
|
self.__logger.info("Adding SSH key to Forgejo: %s (%s)", pubkey, description)
|
|
|
|
|
|
|
|
|
|
r = requests.post(
|
|
|
|
|
f"http://localhost:{self.forgejo_port}/api/v1/user/keys",
|
|
|
|
@ -819,8 +826,11 @@ if __name__ == '__main__':
|
|
|
|
|
parser.add_argument('--ignoresshkey', action='store_true', help="Ignorar clave de SSH")
|
|
|
|
|
parser.add_argument('--usesshkey', type=str, help="Usar clave SSH especificada")
|
|
|
|
|
parser.add_argument('--test-createuser', action='store_true')
|
|
|
|
|
parser.add_argument('--extract-ssh-key', action='store_true', help="Extract SSH key from oglive")
|
|
|
|
|
parser.add_argument('--set-ssh-key', action='store_true', help="Configure SSH key in oglive")
|
|
|
|
|
parser.add_argument('--extract-ssh-key', action='store_true', help="Extract SSH key from oglive squashfs")
|
|
|
|
|
parser.add_argument('--set-ssh-key', action='store_true', help="Read SSH key from oglive squashfs and set it in Forgejo")
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--extract-ssh-key-from-initrd', action='store_true', help="Extract SSH key from oglive initrd (obsolete)")
|
|
|
|
|
parser.add_argument('--set-ssh-key-in-initrd', action='store_true', help="Configure SSH key in oglive (obsolete)")
|
|
|
|
|
parser.add_argument('--oglive', type=int, metavar='NUM', help = "Do SSH key manipulation on this oglive")
|
|
|
|
|
parser.add_argument('--quiet', action='store_true', help="Quiet console output")
|
|
|
|
|
parser.add_argument("-v", "--verbose", action="store_true", help = "Verbose console output")
|
|
|
|
@ -850,11 +860,15 @@ if __name__ == '__main__':
|
|
|
|
|
elif args.test_createuser:
|
|
|
|
|
installer.set_ssh_user_group("oggit2", "oggit2")
|
|
|
|
|
elif args.extract_ssh_key:
|
|
|
|
|
key = installer._extract_ssh_key()
|
|
|
|
|
keys = installer.extract_ssh_keys(oglive_num = args.oglive)
|
|
|
|
|
print(f"{keys}")
|
|
|
|
|
elif args.extract_ssh_key_from_initrd:
|
|
|
|
|
key = installer._extract_ssh_key_from_initrd()
|
|
|
|
|
print(f"{key}")
|
|
|
|
|
|
|
|
|
|
elif args.set_ssh_key:
|
|
|
|
|
installer.set_ssh_key()
|
|
|
|
|
installer.add_ssh_key_from_squashfs(oglive_num=args.oglive)
|
|
|
|
|
elif args.set_ssh_key_in_initrd:
|
|
|
|
|
installer.set_ssh_key_in_initrd()
|
|
|
|
|
else:
|
|
|
|
|
installer.install()
|
|
|
|
|
installer.install_forgejo()
|
|
|
|
|