Pavel Loginov 2021-09-15 11:40:51 +06:00
parent 20ba4eff7a
commit bb4bec949d
15 changed files with 496 additions and 206 deletions

View File

@ -55,9 +55,6 @@ def default_values():
'desc': 'Socket port for HAProxy', 'group': '1'},
{'param': 'haproxy_sock_port', 'value': '1999', 'section': 'haproxy', 'desc': 'HAProxy sock port',
'group': '1'},
{'param': 'haproxy_enterprise', 'value': '0', 'section': 'haproxy',
'desc': 'If you use enterprise HAProxy, set the value of this parameter to 1. The name of the service will be changed as it is required for the commercial version',
'group': '1'},
{'param': 'apache_log_path', 'value': '/var/log/'+apache_dir+'/', 'section': 'logs', 'desc': 'Path to Apache logs',
'group': '1'},
{'param': 'nginx_path_error_logs', 'value': '/var/log/nginx/error.log', 'section': 'nginx',
@ -215,40 +212,6 @@ def update_db_v_4_4_2_1(**kwargs):
print("DB has been updated to 4.4.2")
def update_db_v_4_3_2_1(**kwargs):
groups = ''
query = Groups.select()
try:
query_res = query.execute()
except Exception as e:
out_error(e)
else:
groups = query_res
for g in groups:
try:
Setting.insert(param='haproxy_enterprise',
value=0,
section='haproxy',
desc='Use this option, if your HAProxy is enterprise. It changes service name for rebooting/reloading',
group=g.group_id).execute()
except Exception as e:
if kwargs.get('silent') != 1:
if (
str(e) == 'columns param, group are not unique' or
str(e) == '(1062, "Duplicate entry \'haproxy_enterprise-1\' for key \'param\'")' or
str(e) == 'UNIQUE constraint failed: settings.param, settings.group'
):
pass
else:
print("An error occurred:", e)
else:
print("Updating... groups")
def update_db_v_4_5_1(**kwargs):
cursor = conn.cursor()
sql = """ select name from role where name = 'superAdmin';"""
@ -789,8 +752,19 @@ def update_db_v_5_2_5_3(**kwargs):
print('Updating... DB has been updated to version 5.2.5-3')
def update_db_v_5_2_6(**kwargs):
query = Setting.delete().where(Setting.param == 'haproxy_enterprise')
try:
query.execute()
except Exception as e:
print("An error occurred:", e)
else:
if kwargs.get('silent') != 1:
print("Updating... DB has been updated to version 5.2.6")
def update_ver():
query = Version.update(version='5.2.5.0')
query = Version.update(version='5.2.6.0')
try:
query.execute()
except:
@ -805,7 +779,6 @@ def update_all():
update_db_v_4_3_0()
update_db_v_4_3_1()
update_db_v_4_4_2_1()
update_db_v_4_3_2_1()
update_db_v_4_5_1()
update_db_v_4_5_4()
update_db_v_4_5_7()
@ -833,7 +806,6 @@ def update_all_silent():
update_db_v_4_3_0(silent=1)
update_db_v_4_3_1(silent=1)
update_db_v_4_4_2_1(silent=1)
update_db_v_4_3_2_1(silent=1)
update_db_v_4_5_1(silent=1)
update_db_v_4_5_4(silent=1)
update_db_v_4_5_7(silent=1)

View File

@ -412,9 +412,35 @@ class GeoipCodes(BaseModel):
primary_key = False
constraints = [SQL('UNIQUE (code, name)')]
class ServiceSetting(BaseModel):
server_id = IntegerField()
service = CharField()
setting = CharField()
value = CharField()
class Meta:
table_name = 'service_settings'
primary_key = False
constraints = [SQL('UNIQUE (server_id, service, setting)')]
class ActionHistory(BaseModel):
service = CharField()
server_id = IntegerField()
user_id = IntegerField()
action = CharField()
ip = CharField()
date = DateTimeField(default=datetime.now)
class Meta:
table_name = 'action_history'
primary_key = False
def create_tables():
with conn:
conn.create_tables([User, Server, Role, Telegram, Slack, UUID, Token, ApiToken, Groups, UserGroups,
Setting, Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf,
PortScannerSettings, PortScannerPorts, PortScannerHistory, ProvidersCreds,
Setting, Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory,
PortScannerSettings, PortScannerPorts, PortScannerHistory, ProvidersCreds, ServiceSetting,
ProvisionedServers, MetricsHttpStatus, SMON, WafRules, Alerts, GeoipCodes, NginxMetrics])

View File

@ -7,7 +7,7 @@ import sys
def is_ip_or_dns(server_from_request: str) -> str:
import re
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]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
dns_regex = "^(?!-)[A-Za-z0-9-]+([\\-\\.]{1}[a-z0-9]+)*\\.[A-Za-z]{2,6}$"
try:
if server_from_request == 'roxy-wi-keep_alive':
return 'roxy-wi-keep_alive'
@ -161,6 +161,8 @@ def logging(server_ip, action, **kwargs):
if kwargs.get('login'):
mess = get_data('date_in_log') + " from " + ip + " user: " + login + ", group: " + user_group + ", " + \
action + " for: " + server_ip + "\n"
if kwargs.get('keep_history'):
keep_action_history(kwargs.get('service'), action, server_ip, login, ip)
else:
mess = get_data('date_in_log') + " " + action + " from " + ip + "\n"
log = open(log_path + "/roxy-wi-"+get_data('logs')+".log", "a")
@ -173,6 +175,9 @@ def logging(server_ip, action, **kwargs):
action + " for: " + server_ip + "\n"
log = open(log_path + "/config_edit-"+get_data('logs')+".log", "a")
if kwargs.get('keep_history'):
keep_action_history(kwargs.get('service'), action, server_ip, login, ip)
try:
log.write(mess)
log.close()
@ -180,6 +185,14 @@ def logging(server_ip, action, **kwargs):
print('<center><div class="alert alert-danger">Can\'t write log. Please check log_path in config %e</div></center>' % e)
def keep_action_history(service: str, action: str, server_ip: str, login: str, user_ip: str):
import sql
server_id = sql.select_server_id_by_ip(server_ip=server_ip)
user_id = sql.get_user_id_by_username(login)
sql.insert_action_history(service, action, server_id, user_id, user_ip)
def telegram_send_mess(mess, **kwargs):
import telebot
from telebot import apihelper
@ -351,10 +364,6 @@ def ssh_connect(server_ip):
try:
if ssh_enable == 1:
# cloud = sql.is_cloud()
# if cloud != '':
# k = paramiko.pkey.load_private_key_file(ssh_key_name, password=cloud)
# else:
k = paramiko.pkey.load_private_key_file(ssh_key_name)
ssh.connect(hostname=server_ip, port=ssh_port, username=ssh_user_name, pkey=k, timeout=11, banner_timeout=200)
else:
@ -623,6 +632,7 @@ def show_installation_output(error, output, service):
break
else:
print('success: ' + service + ' has been installed')
logging('localhost', error, haproxywi=1, keep_history=1, service=service)
return True
@ -828,6 +838,22 @@ def upload_and_restart(server_ip, cfg, **kwargs):
error = ""
if kwargs.get("nginx"):
service = 'nginx'
elif kwargs.get("keepalived"):
service = 'keepalived'
else:
service = 'haproxy'
if kwargs.get("just_save") == 'save':
action = 'save'
elif kwargs.get("just_save") == 'reload':
action = 'reload'
elif kwargs.get("just_save") == 'test':
action = 'test'
else:
action = 'restart'
if service == "nginx":
config_path = sql.get_setting('nginx_config_path')
tmp_file = sql.get_setting('tmp_config_path') + "/" + get_data('config') + ".conf"
else:
@ -839,26 +865,29 @@ def upload_and_restart(server_ip, cfg, **kwargs):
except OSError:
return 'Please install dos2unix'
if kwargs.get("keepalived") == 1:
if kwargs.get("just_save") == "save":
if service == "keepalived":
if action == "save":
commands = ["sudo mv -f " + tmp_file + " /etc/keepalived/keepalived.conf"]
elif kwargs.get("just_save") == "reload":
elif action == "reload":
commands = [
"sudo mv -f " + tmp_file + " /etc/keepalived/keepalived.conf && sudo systemctl reload keepalived"]
else:
commands = ["sudo mv -f " + tmp_file + " /etc/keepalived/keepalived.conf && sudo systemctl restart keepalived"]
elif kwargs.get("nginx"):
elif service == "nginx":
check_and_move = "sudo mv -f " + tmp_file + " " + config_path + " && sudo nginx -t -q"
if kwargs.get("just_save") == "save":
if action == "test":
commands = [check_config + " && sudo rm -f " + tmp_file]
elif action == "save":
commands = [check_and_move]
elif kwargs.get("just_save") == "reload":
elif action == "reload":
commands = [check_and_move + " && sudo systemctl reload nginx"]
else:
commands = [check_and_move + " && sudo systemctl restart nginx"]
if sql.return_firewall(server_ip):
commands[0] += open_port_firewalld(cfg, server_ip=server_ip, service='nginx')
else:
haproxy_enterprise = sql.get_setting('haproxy_enterprise')
server_id = sql.select_server_id_by_ip(server_ip=server_ip)
haproxy_enterprise = sql.select_service_setting(server_id, 'haproxy', 'haproxy_enterprise')
if haproxy_enterprise == '1':
haproxy_service_name = "hapee-2.0-lb"
@ -868,11 +897,11 @@ def upload_and_restart(server_ip, cfg, **kwargs):
check_config = "sudo " + haproxy_service_name + " -q -c -f " + tmp_file
move_config = " && sudo mv -f " + tmp_file + " " + config_path
if kwargs.get("just_save") == "test":
if action == "test":
commands = [check_config + " && sudo rm -f " + tmp_file]
elif kwargs.get("just_save") == "save":
elif action == "save":
commands = [check_config + move_config]
elif kwargs.get("just_save") == "reload":
elif action == "reload":
commands = [check_config + move_config + " && sudo systemctl reload "+haproxy_service_name+""]
else:
commands = [check_config + move_config + " && sudo systemctl restart "+haproxy_service_name+""]
@ -882,6 +911,12 @@ def upload_and_restart(server_ip, cfg, **kwargs):
try:
error += ssh_command(server_ip, commands)
if action != 'test':
logging(server_ip, 'A new config file has been uploaded', login=1, keep_history=1,
service=service)
if action == 'reload' or action == 'restart':
logging(server_ip, 'Service has been ' + action + 'ed', login=1, keep_history=1,
service=service)
except Exception as e:
error += e
if error:

View File

@ -148,8 +148,12 @@ if form.getvalue('backend_ip') is not None:
cmd = 'echo "set server %s/%s addr %s port %s check-port %s" |nc %s %s' % (backend_backend, backend_server, backend_ip, backend_port, backend_port, master[0], haproxy_sock_port)
output, stderr = funct.subprocess_execute(cmd)
print(output[0])
funct.logging(master[0], 'IP address and port have been changed. On: {}/{} to {}:{}'.format(backend_backend, backend_server, backend_ip, backend_port),
login=1, keep_history=1, service='haproxy')
cmd = 'echo "set server %s/%s addr %s port %s check-port %s" |nc %s %s' % (backend_backend, backend_server, backend_ip, backend_port, backend_port, serv, haproxy_sock_port)
funct.logging(serv, 'IP address and port have been changed. On: {}/{} to {}:{}'.format(backend_backend, backend_server, backend_ip, backend_port),
login=1, keep_history=1, service='haproxy')
output, stderr = funct.subprocess_execute(cmd)
if stderr != '':
@ -185,11 +189,15 @@ if form.getvalue('maxconn_frontend') is not None:
else:
cmd = 'echo "set maxconn frontend %s %s" |nc %s %s' % (frontend, maxconn, master[0], haproxy_sock_port)
output, stderr = funct.subprocess_execute(cmd)
funct.logging(master[0], 'Maxconn has been changed. On: {} to {}'.format(frontend, maxconn), login=1, keep_history=1,
service='haproxy')
if frontend == 'global':
cmd = 'echo "set maxconn %s %s" |nc %s %s' % (frontend, maxconn, serv, haproxy_sock_port)
else:
cmd = 'echo "set maxconn frontend %s %s" |nc %s %s' % (frontend, maxconn, serv, haproxy_sock_port)
funct.logging(serv, 'Maxconn has been changed. On: {} to {}'.format(frontend, maxconn), login=1, keep_history=1,
service='haproxy')
output, stderr = funct.subprocess_execute(cmd)
if stderr != '':
@ -308,22 +316,20 @@ if form.getvalue('list_id_for_delete') is not None:
if stderr[0] != '':
print('error: ' + stderr[0])
funct.logging(serv, '{} has been delete from list {}'.format(ip_id, list_id), login=1, keep_history=1,
service='haproxy')
if form.getvalue('list_ip_for_add') is not None:
haproxy_sock_port = sql.get_setting('haproxy_sock_port')
lists_path = sql.get_setting('lists_path')
fullpath = funct.get_config_var('main', 'fullpath')
full_path = funct.get_config_var('main', 'fullpath')
ip = form.getvalue('list_ip_for_add')
ip = ip.strip()
ip = funct.is_ip_or_dns(ip)
list_id = form.getvalue('list_id_for_add')
list_name = form.getvalue('list_name')
user_group = funct.get_user_group(id=1)
cmd = 'echo "%s" >> %s/%s/%s/%s' % (ip, fullpath, lists_path, user_group, list_name)
output, stderr = funct.subprocess_execute(cmd)
if output:
print('error: ' + str(output))
if stderr:
print('error: ' + str(stderr))
cmd = 'echo "add acl #%s %s" |nc %s %s' % (list_id, ip, serv, haproxy_sock_port)
output, stderr = funct.subprocess_execute(cmd)
if output[0]:
@ -331,6 +337,17 @@ if form.getvalue('list_ip_for_add') is not None:
if stderr:
print('error: ' + stderr[0])
if 'is not a valid IPv4 or IPv6 address' not in output[0]:
cmd = 'echo "%s" >> %s/%s/%s/%s' % (ip, full_path, lists_path, user_group, list_name)
output, stderr = funct.subprocess_execute(cmd)
if output:
print('error: ' + str(output))
if stderr:
print('error: ' + str(stderr))
funct.logging(serv, '{} has been added to list {}'.format(ip, list_id), login=1, keep_history=1,
service='haproxy')
if form.getvalue('sessions_select') is not None:
from jinja2 import Environment, FileSystemLoader
@ -390,7 +407,10 @@ if form.getvalue('action_hap') is not None and serv is not None:
action = form.getvalue('action_hap')
if funct.check_haproxy_config(serv):
haproxy_enterprise = sql.get_setting('haproxy_enterprise')
servers = sql.select_servers(server=serv)
for server in servers:
server_id = server[0]
haproxy_enterprise = sql.select_service_setting(serv, 'haproxy', 'haproxy_enterprise')
if haproxy_enterprise == '1':
haproxy_service_name = "hapee-2.0-lb"
else:
@ -398,7 +418,7 @@ if form.getvalue('action_hap') is not None and serv is not None:
commands = ["sudo systemctl %s %s" % (action, haproxy_service_name)]
funct.ssh_command(serv, commands)
funct.logging(serv, 'HAProxy has been ' + action + 'ed', haproxywi=1, login=1)
funct.logging(serv, 'Service has been ' + action + 'ed', haproxywi=1, login=1, keep_history=1, service='haproxy')
print("success: HAProxy has been %s" % action)
else:
print("error: Bad config, check please")
@ -408,7 +428,7 @@ if form.getvalue('action_nginx') is not None and serv is not None:
commands = ["sudo systemctl %s nginx" % action]
funct.ssh_command(serv, commands)
funct.logging(serv, 'Nginx has been ' + action + 'ed', haproxywi=1, login=1)
funct.logging(serv, 'Service has been ' + action + 'ed', haproxywi=1, login=1, keep_history=1, service='nginx')
print("success: Nginx has been %s" % action)
if form.getvalue('action_keepalived') is not None and serv is not None:
@ -416,13 +436,13 @@ if form.getvalue('action_keepalived') is not None and serv is not None:
commands = ["sudo systemctl %s keepalived" % action]
funct.ssh_command(serv, commands)
funct.logging(serv, 'Keepalived has been ' + action + 'ed', haproxywi=1, login=1)
funct.logging(serv, 'Service has been ' + action + 'ed', haproxywi=1, login=1, keep_history=1, service='keepalived')
print("success: Keepalived has been %s" % action)
if form.getvalue('action_waf') is not None and serv is not None:
serv = form.getvalue('serv')
action = form.getvalue('action_waf')
funct.logging(serv, 'WAF service has been ' + action + 'ed', haproxywi=1, login=1)
funct.logging(serv, 'WAF service has been ' + action + 'ed', haproxywi=1, login=1, keep_history=1, service='haproxy')
commands = ["sudo systemctl %s waf" % action]
funct.ssh_command(serv, commands)
@ -1025,6 +1045,7 @@ if form.getvalue('servaction') is not None:
command = [cmd]
if enable != "show":
funct.logging(serv, 'Has been ' + enable + 'ed ' + backend, login=1, keep_history=1, service='haproxy')
print(
'<center><h3>You %s %s on HAProxy %s. <a href="viewsttats.py?serv=%s" title="View stat" target="_blank">Look it</a> or <a href="runtimeapi.py" title="Runtime API">Edit something else</a></h3><br />' % (enable, backend, serv, serv))
@ -1769,7 +1790,8 @@ if form.getvalue('bwlists_save'):
except Exception:
pass
haproxy_enterprise = sql.get_setting('haproxy_enterprise')
server_id = sql.select_server_id_by_ip(server=serv)
haproxy_enterprise = sql.select_service_setting(server_id, 'haproxy', 'haproxy_enterprise')
if haproxy_enterprise == '1':
haproxy_service_name = "hapee-2.0-lb"
else:
@ -1940,6 +1962,7 @@ if form.getvalue('updatepassowrd') is not None:
if form.getvalue('newserver') is not None:
hostname = form.getvalue('servername')
ip = form.getvalue('newip')
ip = funct.is_ip_or_dns(ip)
group = form.getvalue('newservergroup')
scan_server = form.getvalue('scan_server')
typeip = form.getvalue('typeip')
@ -1954,6 +1977,10 @@ if form.getvalue('newserver') is not None:
port = form.getvalue('newport')
desc = form.getvalue('desc')
if ip == '':
print('error: IP or DNS name is not valid')
sys.exit()
if sql.add_server(hostname, ip, group, typeip, enable, master, cred, port, desc, haproxy, nginx, firewall):
try:
@ -2027,18 +2054,19 @@ if form.getvalue('updateserver') is not None:
funct.logging('the server ' + name, ' has been updated ', haproxywi=1, login=1)
if form.getvalue('serverdel') is not None:
serverdel = form.getvalue('serverdel')
server = sql.select_servers(id=serverdel)
server_id = form.getvalue('serverdel')
server = sql.select_servers(id=server_id)
for s in server:
hostname = s[1]
ip = s[2]
if sql.check_exists_backup(ip):
print('warning: Delete the backup first ')
sys.exit()
if sql.delete_server(serverdel):
sql.delete_waf_server(serverdel)
sql.delete_port_scanner_settings(serverdel)
if sql.delete_server(server_id):
sql.delete_waf_server(server_id)
sql.delete_port_scanner_settings(server_id)
sql.delete_waf_rules(ip)
sql.delete_action_history(server_id)
print("Ok")
funct.logging(hostname, ' has been deleted server with ', haproxywi=1, login=1)
@ -3705,3 +3733,43 @@ if form.getvalue('updatesavedserver') is not None:
if form.getvalue('savedserverdel') is not None:
if sql.delete_savedserver(form.getvalue('savedserverdel')):
print("Ok")
if form.getvalue('show_users_ovw') is not None:
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/ajax'), autoescape=True)
template = env.get_template('/show_users_ovw.html')
user, user_id, role, token, servers, user_services = funct.get_users_params()
users_groups = sql.select_user_groups_with_names(1, all=1)
user_group = funct.get_user_group(id=1)
if (role == 2 or role == 3) and int(user_group) != 1:
users = sql.select_users(group=user_group)
else:
users = sql.select_users()
template = template.render(users=users, users_groups=users_groups)
print(template)
if form.getvalue('serverSettings') is not None:
server_id = form.getvalue('serverSettings')
service = form.getvalue('serverSettingsService')
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/'), autoescape=True)
template = env.get_template('ajax/show_service_settings.html')
template = template.render(settings=sql.select_service_settings(server_id, service), service=service)
print(template)
if form.getvalue('serverSettingsSave') is not None:
server_id = form.getvalue('serverSettingsSave')
service = form.getvalue('serverSettingsService')
haproxy_enterprise = form.getvalue('serverSettingsEnterprise')
if service == 'haproxy':
if sql.insert_or_update_service_setting(server_id, service, 'haproxy_enterprise', haproxy_enterprise):
print('Ok')

View File

@ -19,7 +19,6 @@ try:
user_group = funct.get_user_group(id=1)
if (role == 2 or role == 3) and int(user_group) != 1:
users = sql.select_users(group=user_group)
servers_for_grep = ''
i = 1
servers_len = len(servers)
@ -49,7 +48,6 @@ try:
prometheus = ''
host = ''
else:
users = sql.select_users()
cmd = "ps ax |grep 'metrics_worker\|metrics_waf_worker.py\|metrics_nginx_worker.py' |grep -v grep |wc -l"
metrics_worker, stderr = funct.subprocess_execute(cmd)
cmd = "ps ax |grep 'checker_worker\|checker_nginx' |grep -v grep |wc -l"
@ -109,9 +107,7 @@ template = template.render(h2=1,
title="Overview",
role=role,
user=user,
users=users,
groups=groups,
users_groups=sql.select_user_groups_with_names(1, all=1),
roles=sql.select_roles(),
metrics_master=''.join(metrics_master),
metrics_worker=''.join(metrics_worker),

View File

@ -9,13 +9,14 @@ mysql_enable = funct.get_config_var('mysql', 'enable')
def out_error(error):
error = str(error)
print('error: ' + error)
try:
funct.logging('localhost', error, haproxywi=1, login=1)
except Exception:
if 'database is locked' not in error:
try:
funct.logging('localhost', error, haproxywi=1)
funct.logging('localhost', error, haproxywi=1, login=1)
except Exception:
pass
try:
funct.logging('localhost', error, haproxywi=1)
except Exception:
pass
def add_user(user, email, password, role, activeuser, group):
@ -62,8 +63,8 @@ def update_user_groups(groups, user_group_id):
def delete_user_groups(user_id):
group_for_delete = UserGroups.delete().where(UserGroups.user_id == user_id)
try:
group_for_delete = UserGroups.delete().where(UserGroups.user_id == user_id)
group_for_delete.execute()
except Exception as e:
out_error(e)
@ -158,9 +159,6 @@ def add_setting_for_new_group(group_id):
'desc': 'Path to the HAProxy sock file', 'group': group_id},
{'param': 'haproxy_sock_port', 'value': '1999', 'section': 'haproxy', 'desc': 'Socket port for HAProxy',
'group': group_id},
{'param': 'haproxy_enterprise', 'value': '0', 'section': 'haproxy',
'desc': 'If you use enterprise HAProxy, set the value of this parameter to 1. The name of the service will be changed as it is required for the commercial version',
'group': group_id},
{'param': 'nginx_path_error_logs', 'value': '/var/log/nginx/error.log', 'section': 'nginx',
'desc': 'Nginx error log', 'group': group_id},
{'param': 'nginx_stats_user', 'value': 'admin', 'section': 'nginx', 'desc': 'Username for accessing Nginx stats page',
@ -453,12 +451,21 @@ def select_server_by_name(name):
return ip.ip
def select_server_id_by_ip(server_ip):
try:
server_id = Server.get(Server.ip == server_ip).server_id
except Exception as e:
return out_error(e)
else:
return server_id
def select_servers(**kwargs):
cursor = conn.cursor()
sql = """select * from servers where enable = '1' ORDER BY groups """
if kwargs.get("server") is not None:
sql = """select * from servers where ip='{}' """.format(kwargs.get("server"))
sql = """select * from servers where ip = '{}' """.format(kwargs.get("server"))
if kwargs.get("full") is not None:
sql = """select * from servers ORDER BY hostname """
if kwargs.get("get_master_servers") is not None:
@ -488,25 +495,17 @@ def select_servers(**kwargs):
def write_user_uuid(login, user_uuid):
session_ttl = get_setting('session_ttl')
session_ttl = int(session_ttl)
user_id = get_user_id_by_username(login)
try:
user_id = User.get(User.username == login)
except Exception as e:
out_error(e)
try:
UUID.insert(user_id=user_id, uuid=user_uuid, exp=funct.get_data('regular', timedelta=session_ttl)).execute()
except Exception as e:
out_error(e)
def write_user_token(login, user_token):
token_ttl = int(get_setting('token_ttl'))
try:
user_id = User.get(User.username == login)
except Exception as e:
out_error(e)
user_id = get_user_id_by_username(login)
try:
Token.insert(user_id=user_id, token=user_token, exp=funct.get_data('regular', timedelta=token_ttl)).execute()
@ -549,6 +548,7 @@ def get_user_id_by_api_token(token):
for i in query_res:
return i.user_id
def get_username_groupid_from_api_token(token):
try:
user_name = ApiToken.get(ApiToken.token == token)
@ -635,6 +635,15 @@ def get_user_id_by_uuid(uuid):
return user.user_id
def get_user_id_by_username(username: str):
try:
query = User.get(User.username == username).user_id
except Exception as e:
out_error(e)
else:
return query
def get_user_role_by_uuid(uuid):
query = (Role.select(Role.role_id)
.join(User, on=(Role.name == User.role))
@ -1747,7 +1756,7 @@ def get_setting(param, **kwargs):
param == 'syslog_server_enable' or param == 'smon_check_interval' or
param == 'checker_check_interval' or param == 'port_scan_interval' or
param == 'smon_keep_history_range' or param == 'checker_keep_history_range' or
param == 'portscanner_keep_history_range' or param == 'haproxy_enterprise'
param == 'portscanner_keep_history_range'
):
return int(setting.value)
else:
@ -1942,18 +1951,18 @@ def check_token_exists(token):
if get_token(user_id.value) == token:
return True
else:
try:
funct.logging('localhost', ' Tried do action with wrong token', haproxywi=1, login=1)
except:
funct.logging('localhost', ' An action with wrong token', haproxywi=1)
return False
except:
try:
funct.logging('localhost', ' Cannot check token', haproxywi=1, login=1)
except:
funct.logging('localhost', ' Cannot check token', haproxywi=1)
finally:
# try:
# funct.logging('localhost', ' Tried do action with wrong token', haproxywi=1, login=1)
# except:
# funct.logging('localhost', ' An action with wrong token', haproxywi=1)
return False
except:
# try:
# funct.logging('localhost', ' Cannot check token', haproxywi=1, login=1)
# except:
# funct.logging('localhost', ' Cannot check token', haproxywi=1)
# finally:
return False
def insert_smon(server, port, enable, proto, uri, body, group, desc, telegram, user_group):
@ -2765,3 +2774,57 @@ def update_user_services(services, user_id):
out_error(e)
return False
def insert_or_update_service_setting(server_id, service, setting, value):
try:
ServiceSetting.insert(server_id=server_id, service=service, setting=setting, value=value).on_conflict('replace').execute()
except Exception as e:
out_error(e)
return False
else:
return True
def select_service_settings(server_id: int, service: str) -> str:
query = ServiceSetting.select().where((ServiceSetting.server_id == server_id) & (ServiceSetting.service == service))
try:
query_res = query.execute()
except Exception as e:
out_error(e)
else:
return query_res
def select_service_setting(server_id: int, service: str, setting: str) -> str:
try:
result = ServiceSetting.get(
(ServiceSetting.server_id == server_id) &
(ServiceSetting.service == service) &
(ServiceSetting.setting == setting)).value
except Exception:
pass
else:
return result
def insert_action_history(service: str, action: str, server_id: int, user_id: int, user_ip: str):
try:
ActionHistory.insert(service=service,
action=action,
server_id=server_id,
user_id=user_id,
ip=user_ip,
date=funct.get_data('regular')).execute()
except Exception as e:
out_error(e)
def delete_action_history(server_id: int):
query = ActionHistory.delete().where(ActionHistory.server_id == server_id)
try:
query.execute()
except Exception as e:
out_error(e)
return False
else:
return True

View File

@ -22,7 +22,7 @@
</select>
{{ input('serv', type='hidden', value=serv) }}
{{ input('open', type='hidden', value='open') }}
<a class="ui-button ui-widget ui-corner-all" id="show" title="Compare" onclick="showCompare()">Show</a>
<a class="ui-button ui-widget ui-corner-all" id="show" title="Compare" onclick="showCompare()">Compare</a>
</p>
</div>
</form>

View File

@ -0,0 +1,30 @@
{% from 'include/input_macros.html' import checkbox %}
<table class="overview">
{% if service == 'haproxy' %}
{% if settings %}
{% for s in settings %}
{% if s.haproxy_enterprise != '' %}
<tr>
<td class="padding20 help_cursor" style="width: 70%" title="If you use enterprise HAProxy, check this. The name of the service will be changed as it is required for the commercial version
">HAProxy Enterprise</td>
<td>
{% if s.value == '1' and s.setting == 'haproxy_enterprise' %}
{{ checkbox('haproxy_enterprise', checked='checked', title='This server uses HAProxy enterprise') }}
{% else %}
{{ checkbox('haproxy_enterprise', title='This server uses HAProxy community') }}
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
{% else %}
<tr>
<td class="padding20 help_cursor" style="width: 70%" title="If you use enterprise HAProxy, check this. The name of the service will be changed as it is required for the commercial version
">HAProxy Enterprise</td>
<td>
{{ checkbox('haproxy_enterprise', title='This server uses HAProxy community') }}
</td>
</tr>
{% endif %}
{% endif %}
</table>

View File

@ -0,0 +1,57 @@
{% set counter = 0 %}
{% for USER in users %}
{% set counter = counter + loop.index0 %}
{% if counter <= 2 %}
<tr class="{{ loop.cycle('odd', 'even') }}">
<td class="padding10 first-collumn-wi">
{% if USER.last_login %}
<span class="serverUp" style="margin-right: 5px;" title="{{USER.username}} is online"></span>
{% else %}
<span class="serverNone" style="margin-right: 5px;" title="{{USER.username}} is offline"></span>
{% endif %}
{% if USER.last_login_date == '0000-00-00 00:00:00' %}
{% set last_login_date = 'Never' %}
{% else %}
{% set last_login_date = USER.last_login_date %}
{% endif %}
<span title="Last activity: {{last_login_date}}, IP: {{USER.last_login_ip}}">{{ USER.username }}</span>
</td>
<td class="third-collumn-wi">
{% for group in users_groups %}
{% if USER.user_id|string() == group.user_id|string() %}
{{ group.groups.name }}
{% endif %}
{% endfor %}
</td>
<td>{{ USER.role }}</td>
<td></td>
<td></td>
</tr>
{% else %}
<tr style="display: none;" class="show-users {{ loop.cycle('odd', 'even') }}">
<td class="padding10 first-collumn-wi">
{% if USER.last_login %}
<span class="serverUp" style="margin-right: 5px;" title="{{USER.username}} is online"></span>
{% else %}
<span class="serverNone" style="margin-right: 5px;" title="{{USER.username}} is offline"></span>
{% endif %}
{% if USER.last_login_date == '0000-00-00 00:00:00' %}
{% set last_login_date = 'Never' %}
{% else %}
{% set last_login_date = USER.last_login_date %}
{% endif %}
<span title="Last activity: {{last_login_date}}, IP: {{USER.last_login_ip}}">{{ USER.username }}</span>
</td>
<td class="third-collumn-wi">
{% for group in users_groups %}
{% if group.user_id|string() == USER.user_id|string() %}
{{ group.groups.name }}{{ "," if not loop.last }}
{% endif %}
{% endfor %}
</td>
<td>{{ USER.role }}</td>
<td></td>
<td></td>
</tr>
{% endif %}
{% endfor %}

View File

@ -2,24 +2,11 @@
{% block content %}
{% from 'include/input_macros.html' import input, checkbox, select, copy_to_clipboard %}
<script src="/inc/overview.js"></script>
{% if serv %}
<link href="/inc/chart.min.css" rel="stylesheet">
<script src="/inc/metrics.js"></script>
<script src="/inc/chart.min.js"></script>
{% if servers|length == 0 %} {% include 'include/getstarted.html' %} {% endif %}
<style>
@media (max-width: 1280px) {
.div-pannel {
height: 430px !important;
}
}
</style>
{% endif %}
<style>
.alert-danger {
width: 250px;
display: inline-block;
height: 15px;
padding-top: 0px;
padding-bottom: 8px;
margin-bottom: -20px !important;
}
.ui-checkboxradio-label {
padding-bottom: 5px !important;
padding-top: 5px !important;
@ -64,19 +51,9 @@
{% endfor %}
});
</script>
{% if serv %}
<div id="up-pannel">
{% else %}
<div id="up-pannel" class="sortable">
{% endif %}
{% if servers|length == 0 %}
{% include 'include/getstarted.html' %}
{% endif %}
<div id="up-pannel" {%if not serv%} class="sortable"{%endif%}>
{% for s in servers %}
{% if serv %}
<link href="/inc/chart.min.css" rel="stylesheet">
<script src="/inc/metrics.js"></script>
<script src="/inc/chart.min.js"></script>
<script>
var server_ip = '{{s.2}}'
function showMetrics() {
@ -113,26 +90,29 @@
</script>
{% endif %}
{% if service == 'nginx' %}
{% set checker_desc = 'Checker monitors Nginx services. If Nginx service is down, Checker will alert via Telegram' %}
{% set checker_desc = 'Checker monitors Nginx services. If Nginx service is down, Checker will alert via Telegram and/or Slack' %}
{% set is_auto_start_enabled = s.8.0.17 %}
{% set is_checker_enabled = s.8.0.19 %}
{% set is_metrics_enabled = s.8.0.21 %}
{% set action_service = 'nginx' %}
{% if s.5.0.1 == 'active' %}
{% set additional_status_class = 'div-server-head-up' %}
{% else %}
{% set additional_status_class = 'div-server-head-down' %}
{% endif %}
{% elif service == 'keepalived' %}
{% set action_service = 'keepalived' %}
{% if s.5.0.1 == 'active' %}
{% set additional_status_class = 'div-server-head-up' %}
{% else %}
{% set additional_status_class = 'div-server-head-down' %}
{% endif %}
{% elif service == 'haproxy' %}
{% set checker_desc = 'Checker monitors HAProxy services and its backends. If some backend or HAProxy service is down, Checker will alert via Telegram' %}
{% set checker_desc = 'Checker monitors HAProxy services, its backends and maxconn. If some backend or HAProxy service is down, Checker will alert via Telegram and/or Slack' %}
{% set is_auto_start_enabled = s.8.0.12 %}
{% set is_checker_enabled = s.8.0.8 %}
{% set is_metrics_enabled = s.8.0.9 %}
{% set action_service = 'hap' %}
{% if s.5 != False %}
{% set additional_status_class = 'div-server-head-up' %}
{% else %}
@ -147,7 +127,7 @@
{% if s.5.0.1 == 'active' %}
<span class="serverUp server-status" title="Started: {{s.5.0.4}}"></span>
{% else %}
<span class="serverDown server-status" title="Stopped: : {{s.5.0.4}}"></span>
<span class="serverDown server-status" title="Stopped: {{s.5.0.4}}"></span>
{% endif %}
{% else %}
{% if s.5 != False %}
@ -157,16 +137,16 @@
{% endif %}
{% endif %}
{% if not serv %}
<a href="/app/hapservers.py?service={{service}}&serv={{s.2}}" title="More about {{s.1}}" style="color: #5d9ceb">{{s.1}}</a>
{% else %}
{{s.1}}
{% endif %}
<a href="/app/hapservers.py?service={{service}}&serv={{s.2}}" title="More about {{s.1}}" style="color: #5d9ceb">{{s.1}}</a>
{% else %}
{{s.1}}
{% endif %}
{% if s.6|int() >= 1 and service != 'keepalived' %}
<span
{% if keep_alive|int() >= 1 %}
class="shield green" title="Auto start is enabled">
class="shield green" title="Autostart is enabled">
{% else %}
class="shield red" title="Auto start is enabled, but Keep alive service does not work">
class="shield red" title="Autostart is enabled, but Keep alive service is not running">
{% endif %}
</span>
{% endif %}
@ -175,13 +155,6 @@
{% endif %}
{% if role <= 2 %}
<span class="server-action">
{% if service == 'nginx' %}
{% set action_service = 'nginx' %}
{% elif service == 'keepalived' %}
{% set action_service = 'keepalived' %}
{% else %}
{% set action_service = 'hap' %}
{% endif %}
<a id="start-{{ s.2 }}" class="start" title="Start {{service}} service">
<span class="service-start" onclick="confirmAjaxAction('start', '{{action_service}}', '{{s.2}}')"></span>
</a>
@ -194,6 +167,9 @@
<a id="stop-{{ s.2 }}" class="stop" title="Stop {{service}} service">
<span class="service-stop" onclick="confirmAjaxAction('stop', '{{action_service}}', '{{s.2}}')"></span>
</a>
{% if service != 'nginx' and service != 'keepalived' %}
<span class="menu-bar" onclick="serverSettings('{{s.0}}', '{{s.1}}')" title="Edit settings for {{s.1}} service" style="margin: 0 0 0 10px;"></span>
{% endif %}
</span>
{% endif %}
</div>
@ -229,7 +205,7 @@
<br />
IP: {{ copy_to_clipboard(value=s.2, style='font-weight: bold') }}
{% if s.7.0.0 != None %}
Master for: <b>{{ s.7.0.1 }}</b>
Master for: <b>{{ copy_to_clipboard(value=s.7.0.1, style='font-weight: bold') }}</b>
{% endif %}
{% if s.9.0 == '1' %}
VRRP status: <b>
@ -332,6 +308,7 @@
<div id="dialog-confirm" style="display: none;">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>Are you sure?</p>
</div>
<div id="dialog-settings-service" style="display: none;"></div>
<script>
{% if serv %}
overviewHapserverBackends(ip, hostnamea, '{{service}}');

View File

@ -59,7 +59,7 @@
{% endfor %}
</table>
<table class="overview-wi">
<tr class="overviewHead" style="height: 40px;">
<tr class="overviewHead" style="height: 30px;">
<td class="padding10 first-collumn-wi" colspan="2">
{% if role <= 1 %}
<a href="/app/viewlogs.py?viewlogs={{haproxy_wi_log_id}}&rows=10&grep=&hour=00&minut=00&hour1=24&minut1=00" title="View Roxy-WI logs" class="logs_link">
@ -292,7 +292,7 @@
{% set admin_uri = 'users.py' %}
{% endif %}
<table class="overview-wi">
<tr class="overviewHead">
<tr class="overviewHead" style="height: 30px;">
<td class="padding10 first-collumn-wi">
<a href="{{admin_uri}}#users" title="Manage users" class="logs_link">Login</a>
</td>
@ -305,50 +305,13 @@
</span>
</span>
</td>
<td style="padding-right: 10px;">
<a onclick="showUsersOverview()" title="Refresh" style="float: right;">
<span class="service-reload"></span>
</a>
</td>
</tr>
{% set counter = 0 %}
{% for USER in users %}
{% set counter = counter + loop.index0 %}
{% if counter <= 2 %}
<tr class="{{ loop.cycle('odd', 'even') }}">
<td class="padding10 first-collumn-wi">
{% if USER.last_login %}
<span class="serverUp" style="margin-right: 5px;" title="{{USER.username}} is online"></span>
{% else %}
<span class="serverNone" style="margin-right: 5px;" title="{{USER.username}} is offline"></span>
{% endif %}
{{ USER.username }}
</td>
<td class="third-collumn-wi">
{% for group in users_groups %}
{% if USER.user_id|string() == group.user_id|string() %}
{{ group.groups.name }}
{% endif %}
{% endfor %}
</td>
<td colspan="2">{{ USER.role }}</td>
</tr>
{% else %}
<tr style="display: none;" class="show-users {{ loop.cycle('odd', 'even') }}">
<td class="padding10 first-collumn-wi">
{% if USER.last_login %}
<span class="serverUp" style="margin-right: 5px;" title="{{USER.username}} is online"></span>
{% else %}
<span class="serverNone" style="margin-right: 5px;" title="{{USER.username}} is offline"></span>
{% endif %}
{{ USER.username }}
</td>
<td class="third-collumn-wi">
{% for group in users_groups %}
{% if group.user_id|string() == USER.user_id|string() %}
{{ group.groups.name }}{{ "," if not loop.last }}
{% endif %}
{% endfor %}
</td>
<td colspan="2">{{ USER.role }}</td>
</tr>
{% endif %}
{% endfor %}
<tbody id="users-table"></tbody>
</table>
{% endif %}
{% if role <= 1 %}
@ -359,7 +322,7 @@
</td>
<td class="second-collumn" style="width: 40%">Description</td>
<td>
<span class="add-button-wi">
<span class="add-button-wi">
<span title="Show all groups" id="show-all-groups" style="color: #fff">
Show all
</span>

View File

@ -268,6 +268,10 @@
font-family: "Font Awesome 5 Solid";
content: "\f0c9";
}
.menu-bar > .fa-bars {
cursor: pointer;
margin-bottom: 3px;
}
.minus::before {
display: none;
font-family: "Font Awesome 5 Solid";

View File

@ -61,7 +61,7 @@ $( function() {
type: frm.attr('method'),
success: function( data ) {
data = data.replace('\n', '<br>');
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error(s)') != '-1' || data.indexOf('failed ') != '-1') {
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error(s)') != '-1' || data.indexOf('failed ') != '-1' || data.indexOf('emerg] ') != '-1') {
toastr.clear();
toastr.error(data);
} else {

View File

@ -58,7 +58,8 @@ function overviewHapserverBackends(serv, hostnamea, service) {
} );
}
function showOverview(serv, hostnamea) {
showOverviewHapWI()
showOverviewHapWI();
showUsersOverview();
var i;
for (i = 0; i < serv.length; i++) {
showOverviewCallBack(serv[i], hostnamea[i])
@ -237,6 +238,19 @@ $( function() {
} catch (e) {
console.log(e);
}
try {
if (cur_url[0] == 'overview.py') {
UsersShowIntervalId = setInterval(showUsersOverview, 600000);
$(window).focus(function () {
UsersShowIntervalId = setInterval(showUsersOverview, 600000);
});
$(window).blur(function () {
clearInterval(UsersShowIntervalId);
});
}
} catch (e) {
console.log(e);
}
$( "#show-all-users" ).click( function() {
$( ".show-users" ).show("fast");
$( "#show-all-users" ).text("Hide");
@ -428,3 +442,85 @@ function showNginxConnections(serv) {
}
} );
}
function showUsersOverview() {
$.ajax( {
url: "options.py",
data: {
show_users_ovw: 1,
token: $('#token').val()
},
type: "POST",
beforeSend: function() {
$("#users-table").html('<img class="loading_small_bin_bout" style="padding-left: 100%;padding-top: 40px;padding-bottom: 40px;" src="/inc/images/loading.gif" />');
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1') {
toastr.error(data);
} else {
$("#users-table").html(data);
}
}
} );
}
function serverSettings(id, name) {
var service = $('#service').val();
$.ajax({
url: "options.py",
data: {
serverSettings: id,
serverSettingsService: service,
token: $('#token').val()
},
type: "POST",
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1') {
toastr.error(data);
} else {
$("#dialog-settings-service").html(data)
$( "input[type=checkbox]" ).checkboxradio();
$("#dialog-settings-service").dialog({
resizable: false,
height: "auto",
width: 400,
modal: true,
title: "Settings for " + name,
buttons: {
"Save": function () {
$(this).dialog("close");
serverSettingsSave(id, name, service, $(this));
},
Cancel: function () {
$(this).dialog("close");
}
}
});
}
}
});
}
function serverSettingsSave(id, name, service, dialog_id) {
var haproxy_enterprise = 0;
if ($('#haproxy_enterprise').is(':checked')) {
haproxy_enterprise = '1';
}
$.ajax({
url: "options.py",
data: {
serverSettingsSave: id,
serverSettingsService: service,
serverSettingsEnterprise: haproxy_enterprise,
token: $('#token').val()
},
type: "POST",
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1') {
toastr.error(data);
} else {
dialog_id.dialog('close');
}
}
});
}

View File

@ -1016,6 +1016,9 @@ label {
}
}
@media (max-width: 1280px) {
.div-pannel {
height: 430px !important;
}
.div-server {
margin-bottom: 30px !important;
height: 100px;