diff --git a/app/create_db.py b/app/create_db.py index c5db894f..0bcb8f4b 100644 --- a/app/create_db.py +++ b/app/create_db.py @@ -204,6 +204,7 @@ def create_table(**kwargs): `create_date` DATETIME default '0000-00-00 00:00:00', `expire_date` DATETIME default '0000-00-00 00:00:00' ); + CREATE TABLE IF NOT EXISTS `slack` (`id` integer primary key autoincrement, `token` VARCHAR (64), `chanel_name` INTEGER NOT NULL DEFAULT 1, `groups` INTEGER NOT NULL DEFAULT 1); """ try: cur.executescript(sql) @@ -1219,6 +1220,29 @@ def update_db_v_5_1_0_1(**kwargs): con.close() +def update_db_v_5_1_1(**kwargs): + con, cur = get_cur() + sql = """CREATE TABLE IF NOT EXISTS `slack` ( + `id` integer primary key autoincrement, + `token` VARCHAR (64), + `chanel_name` INTEGER NOT NULL DEFAULT 1, + `groups` INTEGER NOT NULL DEFAULT 1 + ); + """ + try: + cur.execute(sql) + con.commit() + except sqltool.Error as e: + if kwargs.get('silent') != 1: + if e.args[0] == 'duplicate column name: version' or e == "1060 (42S21): Duplicate column name 'version' ": + print('Updating... DB has been updated to version 5.1.1') + else: + print("Updating... DB has been updated to version 5.1.1") + + cur.close() + con.close() + + def update_ver(): con, cur = get_cur() sql = """update version set version = '5.1.1.0'; """ @@ -1263,6 +1287,7 @@ def update_all(): update_db_v_5_0_1() update_db_v_5_1_0() update_db_v_5_1_0_1() + update_db_v_5_1_1() update_ver() @@ -1298,6 +1323,7 @@ def update_all_silent(): update_db_v_5_1_0_13(silent=1) update_db_v_5_1_0(silent=1) update_db_v_5_1_0_1(silent=1) + update_db_v_5_1_1(silent=1) update_ver() diff --git a/app/funct.py b/app/funct.py index caf6edd9..3fe63a9c 100644 --- a/app/funct.py +++ b/app/funct.py @@ -136,6 +136,8 @@ def telegram_send_mess(mess, **kwargs): telegrams = sql.get_telegram_by_id(kwargs.get('telegram_channel_id')) else: telegrams = sql.get_telegram_by_ip(kwargs.get('ip')) + slack_send_mess(mess, ip=kwargs.get('ip')) + proxy = sql.get_setting('proxy') for telegram in telegrams: @@ -157,7 +159,36 @@ def telegram_send_mess(mess, **kwargs): print(str(e)) logging('localhost', str(e), haproxywi=1) - + +def slack_send_mess(mess, **kwargs): + import sql + from slack_sdk import WebClient + from slack_sdk.errors import SlackApiError + + if kwargs.get('slack_channel_id'): + slacks = sql.get_slack_by_id(kwargs.get('slack_channel_id')) + else: + slacks = sql.get_slack_by_ip(kwargs.get('ip')) + + proxy = sql.get_setting('proxy') + + for slack in slacks: + slack_token = slack[1] + channel_name = slack[2] + + if proxy is not None and proxy != '' and proxy != 'None': + proxies = dict(https=proxy, http=proxy) + client = WebClient(token=slack_token, proxies=proxies) + else: + client = WebClient(token=slack_token) + + try: + client.chat_postMessage(channel='#'+channel_name, text=mess) + except SlackApiError as e: + print('error: ' + str(e)) + logging('localhost', str(e), haproxywi=1) + + def check_login(): import sql import http.cookies diff --git a/app/haproxy-wi.db.sql b/app/haproxy-wi.db.sql index c3ee1687..3b728b4b 100644 --- a/app/haproxy-wi.db.sql +++ b/app/haproxy-wi.db.sql @@ -27,4 +27,5 @@ CREATE TABLE IF NOT EXISTS port_scanner_ports (`serv` varchar(64), user_group_id CREATE TABLE IF NOT EXISTS port_scanner_history (`serv` varchar(64), port INTEGER NOT NULL, status varchar(64), service_name varchar(64), `date` DATETIME default '0000-00-00 00:00:00'); CREATE TABLE IF NOT EXISTS providers_creds (`id` INTEGER NOT NULL, `name` VARCHAR ( 64 ), `type` VARCHAR ( 64 ), `group` VARCHAR ( 64 ), `key` VARCHAR ( 64 ), `secret` VARCHAR ( 64 ), `create_date` DATETIME default '0000-00-00 00:00:00', `edit_date` DATETIME default '0000-00-00 00:00:00', PRIMARY KEY(`id`)); CREATE TABLE IF NOT EXISTS provisioned_servers (`id` INTEGER NOT NULL, `region` VARCHAR ( 64 ), `instance_type` VARCHAR ( 64 ), `public_ip` INTEGER, `floating_ip` INTEGER, `volume_size` INTEGER, `backup` INTEGER, `monitoring` INTEGER, `private_networking` INTEGER, `ssh_key_name` VARCHAR ( 64 ), `ssh_ids` VARCHAR ( 64 ), `name` VARCHAR ( 64 ), `os` VARCHAR ( 64 ), `firewall` INTEGER, `provider_id` INTEGER, `type` VARCHAR ( 64 ), `status` VARCHAR ( 64 ), `group_id` INTEGER NOT NULL, `date` DATETIME default '0000-00-00 00:00:00', `IP` VARCHAR ( 64 ), `last_error` VARCHAR ( 256 ), `delete_on_termination` INTEGER, PRIMARY KEY(`id`)); -CREATE TABLE IF NOT EXISTS api_tokens (`token` varchar(64), `user_name` varchar(64), `user_group_id` INTEGER NOT NULL, `user_role` INTEGER NOT NULL, `create_date` DATETIME default '0000-00-00 00:00:00', `expire_date` DATETIME default '0000-00-00 00:00:00'); \ No newline at end of file +CREATE TABLE IF NOT EXISTS api_tokens (`token` varchar(64), `user_name` varchar(64), `user_group_id` INTEGER NOT NULL, `user_role` INTEGER NOT NULL, `create_date` DATETIME default '0000-00-00 00:00:00', `expire_date` DATETIME default '0000-00-00 00:00:00'); +CREATE TABLE IF NOT EXISTS `slack` (`id` integer primary key autoincrement, `token` VARCHAR (64), `chanel_name` INTEGER NOT NULL DEFAULT 1, `groups` INTEGER NOT NULL DEFAULT 1); diff --git a/app/options.py b/app/options.py index 74506624..33a963dc 100644 --- a/app/options.py +++ b/app/options.py @@ -11,6 +11,7 @@ serv = form.getvalue("serv") act = form.getvalue("act") if (form.getvalue('new_metrics') or + form.getvalue('new_http_metrics') or form.getvalue('new_waf_metrics') or form.getvalue('metrics_hapwi_ram') or form.getvalue('metrics_hapwi_cpu')): @@ -458,6 +459,30 @@ if act == "overviewHapserverBackends": template = template.render(backends=sections, serv=serv, service=service) print(template) +if form.getvalue('show_userlists'): + configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir') + format_file = 'cfg' + + try: + sections = funct.get_userlists(configs_dir + funct.get_files(dir=configs_dir, format=format_file)[0]) + except Exception as e: + funct.logging('localhost', str(e), haproxywi=1) + try: + cfg = configs_dir + serv + "-" + funct.get_data('config') + '.' + format_file + except Exception as e: + funct.logging('localhost', ' Cannot generate cfg path ' + str(e), haproxywi=1) + try: + error = funct.get_config(serv, cfg) + except Exception as e: + funct.logging('localhost', ' Cannot download config ' + str(e), haproxywi=1) + try: + sections = funct.get_userlists(cfg) + except Exception as e: + funct.logging('localhost', ' Cannot get Userlists from config file ' + str(e), haproxywi=1) + sections = 'error: Cannot get Userlists' + + print(sections) + if act == "overviewHapservers": if form.getvalue('service') == 'nginx': config_path = sql.get_setting('nginx_config_path') @@ -881,7 +906,7 @@ if serv is not None and form.getvalue('right') is not None: configs_dir = funct.get_config_var('configs', 'nginx_save_configs_dir') else: configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir') - cmd = 'diff -ub %s%s %s%s' % (configs_dir, left, configs_dir, right) + cmd = 'diff -pub %s%s %s%s' % (configs_dir, left, configs_dir, right) env = Environment(loader=FileSystemLoader('templates/'), autoescape=True, extensions=["jinja2.ext.loopcontrols", "jinja2.ext.do"]) template = env.get_template('ajax/compare.html') @@ -1380,6 +1405,40 @@ if form.getvalue('new_metrics'): print(json.dumps(metrics)) +if form.getvalue('new_http_metrics'): + serv = form.getvalue('server') + time_range = form.getvalue('time_range') + metric = sql.select_metrics_http(serv, time_range=time_range) + metrics = {'chartData': {}} + metrics['chartData']['labels'] = {} + labels = '' + http_2xx = '' + http_3xx = '' + http_4xx = '' + http_5xx = '' + server = '' + + for i in metric: + label = str(i[5]) + label = label.split(' ')[1] + labels += label + ',' + http_2xx += str(i[1]) + ',' + http_3xx += str(i[2]) + ',' + http_4xx += str(i[3]) + ',' + http_5xx += str(i[4]) + ',' + server = str(i[0]) + + metrics['chartData']['labels'] = labels + metrics['chartData']['http_2xx'] = http_2xx + metrics['chartData']['http_3xx'] = http_3xx + metrics['chartData']['http_4xx'] = http_4xx + metrics['chartData']['http_5xx'] = http_5xx + metrics['chartData']['server'] = server + + import json + + print(json.dumps(metrics)) + if form.getvalue('new_waf_metrics'): serv = form.getvalue('server') time_range = form.getvalue('time_range') @@ -1892,6 +1951,26 @@ if form.getvalue('newtelegram'): print(output_from_parsed_template) funct.logging(channel, ' has created a new Telegram channel ', haproxywi=1, login=1) +if form.getvalue('newslack'): + token = form.getvalue('newslack') + channel = form.getvalue('chanel') + group = form.getvalue('slackgroup') + page = form.getvalue('page') + page = page.split("#")[0] + + if token is None or channel is None or group is None: + print(error_mess) + else: + if sql.insert_new_slack(token, channel, group): + from jinja2 import Environment, FileSystemLoader + + env = Environment(loader=FileSystemLoader('templates/ajax'), autoescape=True) + template = env.get_template('/new_slack.html') + output_from_parsed_template = template.render(groups=sql.select_groups(), + slacks=sql.select_slack(token=token), page=page) + print(output_from_parsed_template) + funct.logging(channel, ' has created a new Slack channel ', haproxywi=1, login=1) + if form.getvalue('telegramdel') is not None: telegramdel = form.getvalue('telegramdel') telegram = sql.select_telegram(id=telegramdel) @@ -1901,6 +1980,15 @@ if form.getvalue('telegramdel') is not None: print("Ok") funct.logging(telegram_name, ' has deleted the Telegram channel ', haproxywi=1, login=1) +if form.getvalue('slackdel') is not None: + slackdel = form.getvalue('slackdel') + slack = sql.select_slack(id=slackdel) + for t in slack: + slack_name = t[1] + if sql.delete_slack(slackdel): + print("Ok") + funct.logging(slack_name, ' has deleted the Slack channel ', haproxywi=1, login=1) + if form.getvalue('updatetoken') is not None: token = form.getvalue('updatetoken') channel = form.getvalue('updategchanel') @@ -1910,7 +1998,18 @@ if form.getvalue('updatetoken') is not None: print(error_mess) else: sql.update_telegram(token, channel, group, user_id) - funct.logging('group ' + group, ' telegram token has updated channel: ' + channel, haproxywi=1, login=1) + funct.logging('group ' + group, ' Telegram token has updated channel: ' + channel, haproxywi=1, login=1) + +if form.getvalue('update_slack_token') is not None: + token = form.getvalue('update_slack_token') + channel = form.getvalue('updategchanel') + group = form.getvalue('updateslackgroup') + user_id = form.getvalue('id') + if token is None or channel is None or group is None: + print(error_mess) + else: + sql.update_slack(token, channel, group, user_id) + funct.logging('group ' + group, ' Slack token has updated channel: ' + channel, haproxywi=1, login=1) if form.getvalue('updatesettings') is not None: settings = form.getvalue('updatesettings') @@ -3155,12 +3254,15 @@ if form.getvalue('loadchecker'): if page == 'servers.py': user_group = funct.get_user_group(id=1) telegrams = sql.get_user_telegram_by_group(user_group) + slacks = sql.get_user_slack_by_group(user_group) else: telegrams = sql.select_telegram() + slacks = sql.select_slack() template = template.render(services=services, telegrams=telegrams, groups=groups, + slacks=slacks, page=page) print(template) @@ -3174,6 +3276,7 @@ if form.getvalue('load_update_hapwi'): smon_ver = funct.check_new_version(service='smon') metrics_ver = funct.check_new_version(service='metrics') keep_ver = funct.check_new_version(service='keep') + portscanner_ver = funct.check_new_version(service='portscanner') services = funct.get_services_status() template = template.render(services=services, @@ -3181,6 +3284,7 @@ if form.getvalue('load_update_hapwi'): checker_ver=checker_ver, smon_ver=smon_ver, metrics_ver=metrics_ver, + portscanner_ver=portscanner_ver, keep_ver=keep_ver) print(template) @@ -3216,3 +3320,8 @@ if form.getvalue('check_telegram'): telegram_id = form.getvalue('check_telegram') mess = 'Test message from HAProxy-WI' funct.telegram_send_mess(mess, telegram_channel_id=telegram_id) + +if form.getvalue('check_slack'): + slack_id = form.getvalue('check_slack') + mess = 'Test message from HAProxy-WI' + funct.slack_send_mess(mess, slack_channel_id=slack_id) diff --git a/app/sql.py b/app/sql.py index d1a03819..e3135cd3 100644 --- a/app/sql.py +++ b/app/sql.py @@ -841,6 +841,45 @@ def get_telegram_by_id(id): con.close() +def get_user_slack_by_group(group): + con, cur = get_cur() + sql = """ select slack.* from slack where groups = '%s' """ % group + try: + cur.execute(sql) + except sqltool.Error as e: + funct.out_error(e) + else: + return cur.fetchall() + cur.close() + con.close() + + +def get_slack_by_ip(ip): + con, cur = get_cur() + sql = """ select slack.* from slack left join servers as serv on serv.groups = slack.groups where serv.ip = '%s' """ % ip + try: + cur.execute(sql) + except sqltool.Error as e: + funct.out_error(e) + else: + return cur.fetchall() + cur.close() + con.close() + + +def get_slack_by_id(id): + con, cur = get_cur() + sql = """ select * from slack where id = '%s' """ % id + try: + cur.execute(sql) + except sqltool.Error as e: + funct.out_error(e) + else: + return cur.fetchall() + cur.close() + con.close() + + def get_dick_permit(**kwargs): import http.cookies import os @@ -1071,21 +1110,6 @@ def check_exists_backup(server): con.close() -def insert_new_telegram(token, chanel, group): - con, cur = get_cur() - sql = """insert into telegram(`token`, `chanel_name`, `groups`) values ('%s', '%s', '%s') """ % (token, chanel, group) - try: - cur.execute(sql) - con.commit() - except sqltool.Error as e: - print('An error occurred: ' + e.args[0] + ' X') - con.rollback() - else: - return True - cur.close() - con.close() - - def delete_telegram(id): con, cur = get_cur() sql = """ delete from telegram where id = %s """ % (id) @@ -1127,7 +1151,7 @@ def insert_new_telegram(token, chanel, group): cur.execute(sql) con.commit() except sqltool.Error as e: - print('An error occurred: ' + e.args[0] + ' X') + funct.out_error(e) con.rollback() else: return True @@ -1152,6 +1176,72 @@ def update_telegram(token, chanel, group, id): con.close() +def delete_slack(id): + con, cur = get_cur() + sql = """ delete from slack where id = %s """ % (id) + try: + cur.execute(sql) + con.commit() + except sqltool.Error as e: + funct.out_error(e) + con.rollback() + else: + return True + cur.close() + con.close() + + +def select_slack(**kwargs): + con, cur = get_cur() + sql = """select * from slack """ + if kwargs.get('group'): + sql = """select * from slack where groups = '%s' """ % kwargs.get('group') + if kwargs.get('token'): + sql = """select * from slack where token = '%s' """ % kwargs.get('token') + if kwargs.get('id'): + sql = """select * from slack where id = '%s' """ % kwargs.get('id') + try: + cur.execute(sql) + except sqltool.Error as e: + funct.out_error(e) + else: + return cur.fetchall() + cur.close() + con.close() + + +def insert_new_slack(token, chanel, group): + con, cur = get_cur() + sql = """insert into slack(`token`, `chanel_name`, `groups`) values ('%s', '%s', '%s') """ % (token, chanel, group) + try: + cur.execute(sql) + con.commit() + except sqltool.Error as e: + funct.out_error(e) + con.rollback() + else: + return True + cur.close() + con.close() + + +def update_slack(token, chanel, group, id): + con, cur = get_cur() + sql = """ update slack set + `token` = '%s', + `chanel_name` = '%s', + `groups` = '%s' + where id = '%s' """ % (token, chanel, group, id) + try: + cur.execute(sql) + con.commit() + except sqltool.Error as e: + funct.out_error(e) + con.rollback() + cur.close() + con.close() + + def insert_new_option(option, group): con, cur = get_cur() sql = """insert into options(`options`, `groups`) values ('%s', '%s') """ % (option, group) @@ -1293,19 +1383,6 @@ def insert_mentrics(serv, curr_con, cur_ssl_con, sess_rate, max_sess_rate): con.close() -# def select_waf_metrics_enable(id): -# con, cur = get_cur() -# sql = """ select waf.metrics from waf left join servers as serv on waf.server_id = serv.id where server_id = '%s' """ % id -# try: -# cur.execute(sql) -# except sqltool.Error as e: -# funct.out_error(e) -# else: -# return cur.fetchall() -# cur.close() -# con.close() - - def select_waf_metrics_enable_server(ip): con, cur = get_cur() sql = """ select waf.metrics from waf left join servers as serv on waf.server_id = serv.id where ip = '%s' """ % ip @@ -1585,6 +1662,7 @@ def delete_mentrics(): con.close() + def select_metrics(serv, **kwargs): con, cur = get_cur() diff --git a/app/templates/ajax/compare.html b/app/templates/ajax/compare.html index 8980ffd8..a255ff15 100644 --- a/app/templates/ajax/compare.html +++ b/app/templates/ajax/compare.html @@ -1,30 +1,29 @@ -
- {% set plus = [] %} - {% set minus = [] %} - {% set total_change = 0 %} - {% for line in stdout %} + {% set plus = [] %} + {% set minus = [] %} + {% set total_change = 0 %} + {% for line in stdout -%} + {%- if loop.index0 == 0 -%} +
{{ line }}
+ {%- elif loop.index0 == 1 %} + {{ line }}
+ {% elif line.startswith('-') and loop.index0 > 1 %} +
{{ line }}
+ {% do minus.append(1) %} + {% elif line.startswith('+') and loop.index0 > 2 %} +
{{ line }}
+ {% do plus.append(1) %} + {% elif line.startswith('@') %} +
{{ line }}
+ {% else %} +
{{ line }}
+ {%- endif %} + {% endfor %} - {% if loop.index0 == 0 %} -
{{ line }}
- {% elif loop.index0 == 1 %} - {{ line }}
- {% elif line.startswith('-') and loop.index0 > 1 %} -
{{ line }}
- {% do minus.append(1) %} - {% elif line.startswith('+') and loop.index0 > 2 %} -
{{ line }}
- {% do plus.append(1) %} - {% elif line.startswith('@') %} -
{{ line }}
- {% else %} -
{{ line }}
- {% endif %} - {% endfor %} - - {% set total_change = minus + plus %} -
Total change: {{ total_change|length }}, additions: {{ plus|length }} & deletions: {{ minus|length }}
- + {% set total_change = minus + plus %} +
+ Total change: {{ total_change|length }}, additions: {{ plus|length }} & deletions: {{ minus|length }} +
\ No newline at end of file diff --git a/app/templates/ajax/load_telegram.html b/app/templates/ajax/load_telegram.html index c8c32b51..e54c4760 100644 --- a/app/templates/ajax/load_telegram.html +++ b/app/templates/ajax/load_telegram.html @@ -3,6 +3,7 @@ {% if s.0 == 'checker_haproxy' %} {% if s.3 != '* is not installed' and s.3 != '' %} +

Add Telegram channel

Token @@ -53,10 +54,63 @@

+ Add

+ + + + + + {% if page != "servers.py" %} + + {% endif %} + + + + + {% for slack in slacks %} + + + + {% if page != "servers.py" %} + + {% endif %} + + + + + {% endfor %} +

Add Slack channel

+ Token + Channel nameGroup
+ {% set id = 'slack-token-' + slack.0|string() %} + {{ input(id, value=slack.1, size='30') }} + + {% set id = 'slack-chanel-' + slack.0|string() %} + {{ input(id, value=slack.2, size='30') }} + + + + + + + + +
+
+ Add +

- You can read the description of all parameters here - and How to create and use Telegram bot in this article + You can read the description of all parameters here, + How to create and use Telegram bot in this article, + How to create and use Slack APP in this article
{% else %}
diff --git a/app/templates/ajax/new_slack.html b/app/templates/ajax/new_slack.html new file mode 100644 index 00000000..57fccf95 --- /dev/null +++ b/app/templates/ajax/new_slack.html @@ -0,0 +1,33 @@ +{% for slack in slacks %} + + + + + + + + + {% if page != "servers.py" %} + + + + {% endif %} + + + + + + + + + + +{% endfor %} \ No newline at end of file diff --git a/app/templates/ajax/new_telegram.html b/app/templates/ajax/new_telegram.html index 0a5fa31c..3a850087 100644 --- a/app/templates/ajax/new_telegram.html +++ b/app/templates/ajax/new_telegram.html @@ -20,6 +20,9 @@ {% endif %} + + + diff --git a/app/templates/ajax/show_compare_configs.html b/app/templates/ajax/show_compare_configs.html index 447b596c..dbfd3806 100644 --- a/app/templates/ajax/show_compare_configs.html +++ b/app/templates/ajax/show_compare_configs.html @@ -1,13 +1,10 @@ {% from 'include/input_macros.html' import input %} -
-
-

- Choose left - Choose right -

+ +
+

Comparing config files

+ + {% for group in groups %} + + {% endfor %} + + + + {% endif %} + +