diff --git a/app/modules/common/common.py b/app/modules/common/common.py index f0e35579..fb3e7337 100644 --- a/app/modules/common/common.py +++ b/app/modules/common/common.py @@ -4,6 +4,7 @@ import cgi form = cgi.FieldStorage() error_mess = 'error: All fields must be completed' + def is_ip_or_dns(server_from_request: str) -> str: ip_regex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" dns_regex = "^(?!-)[A-Za-z0-9-]+([\\-\\.]{1}[a-z0-9]+)*\\.[A-Za-z]{2,6}$" diff --git a/app/modules/server/server.py b/app/modules/server/server.py index 2ce40fc5..3bd174dc 100644 --- a/app/modules/server/server.py +++ b/app/modules/server/server.py @@ -1,43 +1,11 @@ import json import modules.db.sql as sql +import modules.server.ssh as mod_ssh import modules.common.common as common import modules.roxywi.common as roxywi_common -from modules.server import ssh_connection -import modules.roxy_wi_tools as roxy_wi_tools form = common.form -get_config_var = roxy_wi_tools.GetConfigVar() - - -def return_ssh_keys_path(server_ip: str, **kwargs) -> dict: - lib_path = get_config_var.get_config_var('main', 'lib_path') - ssh_settings = {} - - if kwargs.get('id'): - sshs = sql.select_ssh(id=kwargs.get('id')) - else: - sshs = sql.select_ssh(serv=server_ip) - - for ssh in sshs: - ssh_settings.setdefault('enabled', ssh.enable) - ssh_settings.setdefault('user', ssh.username) - ssh_settings.setdefault('password', ssh.password) - ssh_key = f'{lib_path}/keys/{ssh.name}.pem' if ssh.enable == 1 else '' - ssh_settings.setdefault('key', ssh_key) - - ssh_port = [str(server[10]) for server in sql.select_servers(server=server_ip)] - ssh_settings.setdefault('port', ssh_port[0]) - - return ssh_settings - - -def ssh_connect(server_ip): - ssh_settings = return_ssh_keys_path(server_ip) - ssh = ssh_connection.SshConnection(server_ip, ssh_settings['port'], ssh_settings['user'], - ssh_settings['password'], ssh_settings['enabled'], ssh_settings['key']) - - return ssh def ssh_command(server_ip: str, commands: list, **kwargs): @@ -48,7 +16,7 @@ def ssh_command(server_ip: str, commands: list, **kwargs): else: timeout = 1 try: - with ssh_connect(server_ip) as ssh: + with mod_ssh.ssh_connect(server_ip) as ssh: for command in commands: try: stdin, stdout, stderr = ssh.run_command(command, timeout=timeout) diff --git a/app/modules/server/ssh.py b/app/modules/server/ssh.py new file mode 100644 index 00000000..c0df0b05 --- /dev/null +++ b/app/modules/server/ssh.py @@ -0,0 +1,158 @@ +import os + +import paramiko + +import modules.db.sql as sql +import modules.common.common as common +from modules.server import ssh_connection +import modules.roxywi.common as roxywi_common +import modules.roxy_wi_tools as roxy_wi_tools + +form = common.form +error_mess = common.error_mess +get_config_var = roxy_wi_tools.GetConfigVar() + + +def return_ssh_keys_path(server_ip: str, **kwargs) -> dict: + lib_path = get_config_var.get_config_var('main', 'lib_path') + ssh_settings = {} + + if kwargs.get('id'): + sshs = sql.select_ssh(id=kwargs.get('id')) + else: + sshs = sql.select_ssh(serv=server_ip) + + for ssh in sshs: + ssh_settings.setdefault('enabled', ssh.enable) + ssh_settings.setdefault('user', ssh.username) + ssh_settings.setdefault('password', ssh.password) + ssh_key = f'{lib_path}/keys/{ssh.name}.pem' if ssh.enable == 1 else '' + ssh_settings.setdefault('key', ssh_key) + + ssh_port = [str(server[10]) for server in sql.select_servers(server=server_ip)] + ssh_settings.setdefault('port', ssh_port[0]) + + return ssh_settings + + +def ssh_connect(server_ip): + ssh_settings = return_ssh_keys_path(server_ip) + ssh = ssh_connection.SshConnection(server_ip, ssh_settings['port'], ssh_settings['user'], + ssh_settings['password'], ssh_settings['enabled'], ssh_settings['key']) + + return ssh + + +def create_ssh_cred() -> None: + from jinja2 import Environment, FileSystemLoader + + user_group = roxywi_common.get_user_group() + name = common.checkAjaxInput(form.getvalue('new_ssh')) + name = f'{name}_{user_group}' + enable = common.checkAjaxInput(form.getvalue('ssh_enable')) + group = common.checkAjaxInput(form.getvalue('new_group')) + username = common.checkAjaxInput(form.getvalue('ssh_user')) + password = common.checkAjaxInput(form.getvalue('ssh_pass')) + page = common.checkAjaxInput(form.getvalue('page')) + page = page.split("#")[0] + + if username is None or name is None: + print(error_mess) + else: + if sql.insert_new_ssh(name, enable, group, username, password): + env = Environment(loader=FileSystemLoader('templates/ajax'), autoescape=True) + template = env.get_template('/new_ssh.html') + output_from_parsed_template = template.render(groups=sql.select_groups(), sshs=sql.select_ssh(name=name), + page=page) + print(output_from_parsed_template) + roxywi_common.logging('Roxy-WI server', f'A new SSH credentials {name} has created', roxywi=1, login=1) + + +def upload_ssh_key() -> None: + user_group = roxywi_common.get_user_group() + name = common.checkAjaxInput(form.getvalue('name')) + + try: + key = paramiko.pkey.load_private_key(form.getvalue('ssh_cert')) + except Exception as e: + print(f'error: Cannot save SSH key file: {e}') + return + + lib_path = get_config.get_config_var('main', 'lib_path') + full_dir = f'{lib_path}/keys/' + ssh_keys = f'{name}.pem' + + try: + check_split = name.split('_')[1] + split_name = True + except Exception: + split_name = False + + if not os.path.isfile(ssh_keys) and not split_name: + name = f'{name}_{user_group}' + + if not os.path.exists(full_dir): + os.makedirs(full_dir) + + ssh_keys = f'{full_dir}{name}.pem' + + try: + key.write_private_key_file(ssh_keys) + except Exception as e: + print(f'error: Cannot save SSH key file: {e}') + return + else: + print(f'success: SSH key has been saved into: {ssh_keys}') + + try: + os.chmod(ssh_keys, 0o600) + except IOError as e: + roxywi_common.logging('Roxy-WI server', e.args[0], roxywi=1) + + roxywi_common.logging("Roxy-WI server", f"A new SSH cert has been uploaded {ssh_keys}", roxywi=1, login=1) + + +def update_ssh_key() -> None: + ssh_id = common.checkAjaxInput(form.getvalue('id')) + name = common.checkAjaxInput(form.getvalue('name')) + enable = common.checkAjaxInput(form.getvalue('ssh_enable')) + group = common.checkAjaxInput(form.getvalue('group')) + username = common.checkAjaxInput(form.getvalue('ssh_user')) + password = common.checkAjaxInput(form.getvalue('ssh_pass')) + new_ssh_key_name = '' + + if username is None: + print(error_mess) + else: + lib_path = get_config.get_config_var('main', 'lib_path') + + for sshs in sql.select_ssh(id=ssh_id): + ssh_enable = sshs.enable + ssh_key_name = f'{lib_path}/keys/{sshs.name}.pem' + new_ssh_key_name = f'{lib_path}/keys/{name}.pem' + + if ssh_enable == 1: + os.rename(ssh_key_name, new_ssh_key_name) + os.chmod(new_ssh_key_name, 0o600) + + sql.update_ssh(ssh_id, name, enable, group, username, password) + roxywi_common.logging('Roxy-WI server', f'The SSH credentials {name} has been updated ', roxywi=1, login=1) + + +def delete_ssh_key() -> None: + lib_path = get_config.get_config_var('main', 'lib_path') + sshdel = common.checkAjaxInput(form.getvalue('sshdel')) + name = '' + ssh_enable = 0 + ssh_key_name = '' + + for sshs in sql.select_ssh(id=sshdel): + ssh_enable = sshs.enable + name = sshs.name + ssh_key_name = f'{lib_path}/keys/{sshs.name}.pem' + + if ssh_enable == 1: + os.remove(ssh_key_name) + if sql.delete_ssh(sshdel): + print("Ok") + roxywi_common.logging('Roxy-WI server', f'The SSH credentials {name} has deleted', roxywi=1, login=1) \ No newline at end of file diff --git a/app/modules/service/exporter_installation.py b/app/modules/service/exporter_installation.py index 09ea46c8..75a01d84 100644 --- a/app/modules/service/exporter_installation.py +++ b/app/modules/service/exporter_installation.py @@ -4,7 +4,7 @@ import modules.db.sql as sql import modules.common.common as common import modules.server.server as server_mod from modules.service.installation import show_installation_output -from modules.server.server import return_ssh_keys_path +from modules.server.ssh import return_ssh_keys_path form = common.form diff --git a/app/modules/service/installation.py b/app/modules/service/installation.py index 05326209..1f345057 100644 --- a/app/modules/service/installation.py +++ b/app/modules/service/installation.py @@ -5,7 +5,7 @@ import modules.service.common as service_common import modules.common.common as common import modules.server.server as server_mod import modules.roxywi.common as roxywi_common -from modules.server.server import return_ssh_keys_path +from modules.server.ssh import return_ssh_keys_path form = common.form diff --git a/app/options.py b/app/options.py index a9df844b..e8622c92 100644 --- a/app/options.py +++ b/app/options.py @@ -10,6 +10,7 @@ import requests from jinja2 import Environment, FileSystemLoader import modules.db.sql as sql +import modules.server.ssh as ssh_mod import modules.common.common as common import modules.config.config as config_mod import modules.roxywi.common as roxywi_common @@ -831,8 +832,6 @@ if serv is not None and act == "configShow": os.remove(cfg) if act == 'configShowFiles': - import modules.server.server as server_mod - service = form.getvalue('service') config_dir = get_config.get_config_var('configs', f'{service}_save_configs_dir') @@ -853,8 +852,6 @@ if act == 'configShowFiles': print(template) if act == 'showRemoteLogFiles': - import modules.server.server as server_mod - service = form.getvalue('service') log_path = sql.get_setting(f'{service}_path_logs') return_files = server_mod.get_remote_files(serv, log_path, 'log') @@ -930,7 +927,7 @@ if form.getvalue('backup') or form.getvalue('deljob') or form.getvalue('backupup update = form.getvalue('backupupdate') description = form.getvalue('description') script = 'backup.sh' - ssh_settings = server_mod.return_ssh_keys_path('localhost', id=int(cred)) + ssh_settings = ssh_mod.return_ssh_keys_path('localhost', id=int(cred)) if deljob: time = '' @@ -1004,7 +1001,7 @@ if form.getvalue('git_backup'): service_config_dir = sql.get_setting(service_name + '_dir') script = 'git_backup.sh' proxy_serv = '' - ssh_settings = server_mod.return_ssh_keys_path('localhost', id=int(cred)) + ssh_settings = ssh_mod.return_ssh_keys_path('localhost', id=int(cred)) os.system(f"cp scripts/{script} .") @@ -1474,8 +1471,6 @@ if form.getvalue('updatepassowrd') is not None: roxywi_user.update_user_password() if form.getvalue('newserver') is not None: - import modules.server.server as server_mod - hostname = common.checkAjaxInput(form.getvalue('servername')) ip = form.getvalue('newip') ip = common.is_ip_or_dns(ip) @@ -1657,23 +1652,15 @@ if form.getvalue('updategroup') is not None: print('error: ' + str(e)) if form.getvalue('new_ssh'): - import modules.server.ssh as ssh_mod - ssh_mod.create_ssh_cred() if form.getvalue('sshdel') is not None: - import modules.server.ssh as ssh_mod - ssh_mod.delete_ssh_key() if form.getvalue('updatessh'): - import modules.server.ssh as ssh_mod - ssh_mod.update_ssh_key() if form.getvalue('ssh_cert'): - import modules.server.ssh as ssh_mod - ssh_mod.upload_ssh_key() if form.getvalue('newtelegram'): @@ -2008,7 +1995,7 @@ if form.getvalue('lets_domain'): haproxy_dir = sql.get_setting('haproxy_dir') script = "letsencrypt.sh" proxy_serv = '' - ssh_settings = server_mod.return_ssh_keys_path(serv) + ssh_settings = ssh_mod.return_ssh_keys_path(serv) os.system(f"cp scripts/{script} .") @@ -3382,11 +3369,9 @@ if act == 'showListOfVersion': print(template) if act == 'getSystemInfo': - import modules.server.server as server_mod server_mod.show_system_info() if act == 'updateSystemInfo': - import modules.server.server as server_mod server_mod.update_system_info() if act == 'findInConfigs':