2022-12-07 07:47:47 +00:00
|
|
|
import os
|
2024-02-04 07:28:17 +00:00
|
|
|
from cryptography.fernet import Fernet
|
2022-12-07 07:47:47 +00:00
|
|
|
|
|
|
|
import paramiko
|
2023-09-17 09:42:39 +00:00
|
|
|
from flask import render_template, request
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-03-03 07:11:48 +00:00
|
|
|
import app.modules.db.cred as cred_sql
|
|
|
|
import app.modules.db.group as group_sql
|
|
|
|
import app.modules.db.server as server_sql
|
2024-02-24 08:05:31 +00:00
|
|
|
import app.modules.common.common as common
|
2024-02-04 07:28:17 +00:00
|
|
|
from app.modules.server import ssh_connection
|
2024-02-24 08:05:31 +00:00
|
|
|
import app.modules.roxywi.common as roxywi_common
|
|
|
|
import app.modules.roxy_wi_tools as roxy_wi_tools
|
2022-12-07 07:47:47 +00:00
|
|
|
|
|
|
|
error_mess = common.error_mess
|
2022-12-07 07:55:21 +00:00
|
|
|
get_config = roxy_wi_tools.GetConfigVar()
|
2022-12-07 07:47:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
def return_ssh_keys_path(server_ip: str, **kwargs) -> dict:
|
2022-12-07 07:55:21 +00:00
|
|
|
lib_path = get_config.get_config_var('main', 'lib_path')
|
2022-12-07 07:47:47 +00:00
|
|
|
ssh_settings = {}
|
|
|
|
if kwargs.get('id'):
|
2024-03-03 07:11:48 +00:00
|
|
|
sshs = cred_sql.select_ssh(id=kwargs.get('id'))
|
2022-12-07 07:47:47 +00:00
|
|
|
else:
|
2024-03-03 07:11:48 +00:00
|
|
|
sshs = cred_sql.select_ssh(serv=server_ip)
|
2022-12-07 07:47:47 +00:00
|
|
|
|
|
|
|
for ssh in sshs:
|
2024-02-04 07:28:17 +00:00
|
|
|
if ssh.password:
|
|
|
|
try:
|
|
|
|
password = decrypt_password(ssh.password)
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
|
|
|
else:
|
|
|
|
password = ssh.password
|
|
|
|
if ssh.passphrase:
|
|
|
|
try:
|
|
|
|
passphrase = decrypt_password(ssh.passphrase)
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
|
|
|
else:
|
|
|
|
passphrase = ssh.passphrase
|
|
|
|
|
2022-12-07 07:47:47 +00:00
|
|
|
ssh_settings.setdefault('enabled', ssh.enable)
|
|
|
|
ssh_settings.setdefault('user', ssh.username)
|
2024-02-04 07:28:17 +00:00
|
|
|
ssh_settings.setdefault('password', password)
|
2022-12-07 07:47:47 +00:00
|
|
|
ssh_key = f'{lib_path}/keys/{ssh.name}.pem' if ssh.enable == 1 else ''
|
|
|
|
ssh_settings.setdefault('key', ssh_key)
|
2024-02-04 07:28:17 +00:00
|
|
|
ssh_settings.setdefault('passphrase', passphrase)
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2023-09-17 09:42:39 +00:00
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ssh_port = [str(server[10]) for server in server_sql.select_servers(server=server_ip)]
|
2023-09-17 09:42:39 +00:00
|
|
|
ssh_settings.setdefault('port', ssh_port[0])
|
|
|
|
except Exception as e:
|
2024-07-06 08:14:01 +00:00
|
|
|
raise Exception(f'error: Cannot get SSH port: {e}')
|
2022-12-07 07:47:47 +00:00
|
|
|
|
|
|
|
return ssh_settings
|
|
|
|
|
|
|
|
|
|
|
|
def ssh_connect(server_ip):
|
|
|
|
ssh_settings = return_ssh_keys_path(server_ip)
|
2024-02-04 07:28:17 +00:00
|
|
|
ssh = ssh_connection.SshConnection(server_ip, ssh_settings)
|
2022-12-07 07:47:47 +00:00
|
|
|
|
|
|
|
return ssh
|
|
|
|
|
|
|
|
|
2024-06-16 16:20:18 +00:00
|
|
|
def create_ssh_cred(json_data: dict) -> dict:
|
|
|
|
name = common.checkAjaxInput(json_data['ssh'])
|
|
|
|
enable = int(json_data['enabled'])
|
|
|
|
group = common.checkAjaxInput(json_data['group'])
|
2024-03-03 07:11:48 +00:00
|
|
|
group_name = group_sql.get_group_name_by_id(group)
|
2024-06-16 16:20:18 +00:00
|
|
|
username = common.checkAjaxInput(json_data['user'])
|
|
|
|
password = common.checkAjaxInput(json_data['pass'])
|
2023-09-17 09:42:39 +00:00
|
|
|
lang = roxywi_common.get_user_lang_for_flask()
|
2023-02-22 07:36:20 +00:00
|
|
|
name = f'{name}_{group_name}'
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-02-04 07:28:17 +00:00
|
|
|
if password != '':
|
|
|
|
try:
|
|
|
|
password = crypt_password(password)
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
|
|
|
|
2022-12-07 07:47:47 +00:00
|
|
|
if username is None or name is None:
|
2023-09-17 09:42:39 +00:00
|
|
|
return error_mess
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-06-16 16:20:18 +00:00
|
|
|
try:
|
|
|
|
last_id = cred_sql.insert_new_ssh(name, enable, group, username, password)
|
|
|
|
except Exception as e:
|
|
|
|
roxywi_common.handle_exceptions(e, 'Roxy-WI server', 'Cannot create new SSH credentials', roxywi=1, login=1)
|
|
|
|
roxywi_common.logging('Roxy-WI server', f'New SSH credentials {name} has been created', roxywi=1, login=1)
|
|
|
|
rendered_template = render_template('ajax/new_ssh.html', groups=group_sql.select_groups(), sshs=cred_sql.select_ssh(name=name), lang=lang)
|
|
|
|
return {'id': last_id, 'template': rendered_template}
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-06-16 16:20:18 +00:00
|
|
|
|
|
|
|
def create_ssh_cred_api(name: str, enable: str, group: str, username: str, password: str) -> bool:
|
2024-03-03 07:11:48 +00:00
|
|
|
group_name = group_sql.get_group_name_by_id(group)
|
2022-12-22 19:19:43 +00:00
|
|
|
name = common.checkAjaxInput(name)
|
2024-02-04 07:28:17 +00:00
|
|
|
name = f'{name}_{group_name}'
|
2022-12-22 19:19:43 +00:00
|
|
|
enable = common.checkAjaxInput(enable)
|
|
|
|
username = common.checkAjaxInput(username)
|
|
|
|
password = common.checkAjaxInput(password)
|
|
|
|
|
2024-02-04 07:28:17 +00:00
|
|
|
if password != '':
|
|
|
|
try:
|
|
|
|
password = crypt_password(password)
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
|
|
|
|
2022-12-22 19:19:43 +00:00
|
|
|
if username is None or name is None:
|
|
|
|
return False
|
|
|
|
else:
|
2024-03-03 07:11:48 +00:00
|
|
|
try:
|
|
|
|
cred_sql.insert_new_ssh(name, enable, group, username, password)
|
|
|
|
roxywi_common.logging('Roxy-WI server', f'New SSH credentials {name} has been created', roxywi=1)
|
2022-12-22 19:19:43 +00:00
|
|
|
return True
|
2024-03-03 07:11:48 +00:00
|
|
|
except Exception as e:
|
|
|
|
roxywi_common.handle_exceptions(e, 'Roxy-WI server', f'Cannot create SSH credentials {name}', roxywi=1)
|
2022-12-22 19:19:43 +00:00
|
|
|
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-06-16 16:20:18 +00:00
|
|
|
def upload_ssh_key(name: str, user_group: int, key: str, passphrase: str) -> str:
|
2023-02-22 07:36:20 +00:00
|
|
|
if '..' in name:
|
2023-05-03 16:14:13 +00:00
|
|
|
raise Exception('error: nice try')
|
2023-02-22 07:36:20 +00:00
|
|
|
|
2023-03-25 09:01:26 +00:00
|
|
|
if name == '':
|
2023-05-03 16:14:13 +00:00
|
|
|
raise Exception('error: please select credentials first')
|
2023-03-25 09:01:26 +00:00
|
|
|
|
2022-12-07 07:47:47 +00:00
|
|
|
try:
|
2024-05-03 14:19:16 +00:00
|
|
|
key = paramiko.pkey.load_private_key(key, password=passphrase)
|
2022-12-07 07:47:47 +00:00
|
|
|
except Exception as e:
|
2024-05-03 14:19:16 +00:00
|
|
|
raise Exception(f'error: Cannot save SSH key file: {e}')
|
2022-12-07 07:47:47 +00:00
|
|
|
|
|
|
|
lib_path = get_config.get_config_var('main', 'lib_path')
|
|
|
|
full_dir = f'{lib_path}/keys/'
|
|
|
|
ssh_keys = f'{name}.pem'
|
|
|
|
|
|
|
|
try:
|
2022-12-07 07:55:21 +00:00
|
|
|
_check_split = name.split('_')[1]
|
2022-12-07 07:47:47 +00:00
|
|
|
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:
|
2023-05-03 16:14:13 +00:00
|
|
|
raise Exception(f'error: Cannot save SSH key file: {e}')
|
2024-02-04 07:28:17 +00:00
|
|
|
try:
|
|
|
|
os.chmod(ssh_keys, 0o600)
|
|
|
|
except IOError as e:
|
|
|
|
roxywi_common.logging('Roxy-WI server', e.args[0], roxywi=1)
|
|
|
|
raise Exception(f'error: something went wrong: {e}')
|
|
|
|
|
|
|
|
if passphrase != '':
|
2023-09-17 09:42:39 +00:00
|
|
|
try:
|
2024-02-04 07:28:17 +00:00
|
|
|
passphrase = crypt_password(passphrase)
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
|
|
|
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
cred_sql.update_ssh_passphrase(name, passphrase)
|
2024-02-04 07:28:17 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
2024-02-04 07:28:17 +00:00
|
|
|
roxywi_common.logging("Roxy-WI server", f"A new SSH cert has been uploaded {ssh_keys}", roxywi=1, login=1)
|
|
|
|
return f'success: SSH key has been saved into: {ssh_keys}'
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
2024-06-16 16:20:18 +00:00
|
|
|
def update_ssh_key(json_data: dict):
|
|
|
|
ssh_id = int(json_data['id'])
|
|
|
|
name = common.checkAjaxInput(json_data['name'])
|
|
|
|
enable = common.checkAjaxInput(json_data['ssh_enable'])
|
|
|
|
group = int(json_data['group'])
|
|
|
|
username = common.checkAjaxInput(json_data['ssh_user'])
|
|
|
|
password = common.checkAjaxInput(json_data['ssh_pass'])
|
2022-12-07 07:47:47 +00:00
|
|
|
new_ssh_key_name = ''
|
2024-02-04 07:28:17 +00:00
|
|
|
ssh_key_name = ''
|
|
|
|
ssh_enable = 0
|
|
|
|
|
|
|
|
if password != '':
|
|
|
|
try:
|
|
|
|
password = crypt_password(password)
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
2022-12-07 07:47:47 +00:00
|
|
|
|
|
|
|
if username is None:
|
2023-09-17 09:42:39 +00:00
|
|
|
return error_mess
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-02-04 07:28:17 +00:00
|
|
|
lib_path = get_config.get_config_var('main', 'lib_path')
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-03-03 07:11:48 +00:00
|
|
|
for sshs in cred_sql.select_ssh(id=ssh_id):
|
2024-02-04 07:28:17 +00:00
|
|
|
ssh_enable = sshs.enable
|
|
|
|
ssh_key_name = f'{lib_path}/keys/{sshs.name}.pem'
|
|
|
|
new_ssh_key_name = f'{lib_path}/keys/{name}.pem'
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-02-04 07:28:17 +00:00
|
|
|
if ssh_enable == 1:
|
|
|
|
os.rename(ssh_key_name, new_ssh_key_name)
|
|
|
|
os.chmod(new_ssh_key_name, 0o600)
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2024-03-03 07:11:48 +00:00
|
|
|
cred_sql.update_ssh(ssh_id, name, enable, group, username, password)
|
2024-02-04 07:28:17 +00:00
|
|
|
roxywi_common.logging('Roxy-WI server', f'The SSH credentials {name} has been updated ', roxywi=1, login=1)
|
|
|
|
|
2022-12-07 07:47:47 +00:00
|
|
|
|
2023-09-17 09:42:39 +00:00
|
|
|
def delete_ssh_key(ssh_id) -> str:
|
2022-12-07 07:47:47 +00:00
|
|
|
lib_path = get_config.get_config_var('main', 'lib_path')
|
|
|
|
name = ''
|
|
|
|
ssh_enable = 0
|
|
|
|
ssh_key_name = ''
|
|
|
|
|
2024-03-03 07:11:48 +00:00
|
|
|
for sshs in cred_sql.select_ssh(id=ssh_id):
|
2022-12-07 07:47:47 +00:00
|
|
|
ssh_enable = sshs.enable
|
|
|
|
name = sshs.name
|
|
|
|
ssh_key_name = f'{lib_path}/keys/{sshs.name}.pem'
|
|
|
|
|
|
|
|
if ssh_enable == 1:
|
2022-12-07 13:49:42 +00:00
|
|
|
try:
|
|
|
|
os.remove(ssh_key_name)
|
|
|
|
except Exception:
|
|
|
|
pass
|
2024-03-03 07:11:48 +00:00
|
|
|
try:
|
|
|
|
cred_sql.delete_ssh(ssh_id)
|
2022-12-07 07:55:21 +00:00
|
|
|
roxywi_common.logging('Roxy-WI server', f'The SSH credentials {name} has deleted', roxywi=1, login=1)
|
2023-09-17 09:42:39 +00:00
|
|
|
return 'ok'
|
2024-03-03 07:11:48 +00:00
|
|
|
except Exception as e:
|
|
|
|
roxywi_common.handle_exceptions(e, 'Roxy-WI server', f'Cannot delete SSH credentials {name}', roxywi=1, login=1)
|
2024-02-04 07:28:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
def crypt_password(password: str) -> bytes:
|
|
|
|
"""
|
|
|
|
Crypt password
|
|
|
|
:param password: plain password
|
|
|
|
:return: crypted text
|
|
|
|
"""
|
|
|
|
salt = get_config.get_config_var('main', 'secret_phrase')
|
|
|
|
fernet = Fernet(salt.encode())
|
|
|
|
try:
|
|
|
|
crypted_pass = fernet.encrypt(password.encode())
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot crypt password: {e}')
|
|
|
|
return crypted_pass
|
|
|
|
|
|
|
|
|
|
|
|
def decrypt_password(password: str) -> str:
|
|
|
|
"""
|
|
|
|
Decrypt password
|
|
|
|
:param password: crypted password
|
|
|
|
:return: plain text
|
|
|
|
"""
|
|
|
|
salt = get_config.get_config_var('main', 'secret_phrase')
|
|
|
|
fernet = Fernet(salt.encode())
|
|
|
|
try:
|
|
|
|
decryp_pass = fernet.decrypt(password.encode()).decode()
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot decrypt password: {e}')
|
|
|
|
return decryp_pass
|