More security!
Redesigned authorization system
Small change and bugs
pull/19/head
Aidaho12 2018-05-02 17:11:22 +06:00
parent d26d949105
commit 4a121235b8
14 changed files with 262 additions and 89 deletions

View File

@ -24,7 +24,7 @@ ssh_user_name = config.get('ssh', 'ssh_user_name')
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
haproxy_config_path = config.get('haproxy', 'haproxy_config_path')
funct.chooseServer("configshow.py", "Show HAproxy config", "n", onclick="showConfig()")
funct.chooseServer("configshow.py", "Get Running Config", "n", onclick="showConfig()")
print('<div id="ajax">')
if serv is not None and form.getvalue('open') is not None :

View File

@ -108,20 +108,24 @@ def create_table():
('guest','Read only access');
CREATE TABLE IF NOT EXISTS `groups` (
`id` INTEGER NOT NULL,
`name` VARCHAR ( 80 ) UNIQUE,
`description` VARCHAR ( 255 ),
PRIMARY KEY(`id`)
`id` INTEGER NOT NULL,
`name` VARCHAR ( 80 ) UNIQUE,
`description` VARCHAR ( 255 ),
PRIMARY KEY(`id`)
);
INSERT INTO `groups` (name, description) VALUES ('All','All servers enter in this group');
CREATE TABLE IF NOT EXISTS `servers` (
`id` INTEGER NOT NULL,
`hostname` VARCHAR ( 64 ) UNIQUE,
`ip` VARCHAR ( 64 ) UNIQUE,
`groups` VARCHAR ( 64 ),
PRIMARY KEY(`id`)
`id` INTEGER NOT NULL,
`hostname` VARCHAR ( 64 ) UNIQUE,
`ip` VARCHAR ( 64 ) UNIQUE,
`groups` VARCHAR ( 64 ),
PRIMARY KEY(`id`)
);
CREATE TABLE IF NOT EXISTS `uuid` (
`user_id` INTEGER NOT NULL,
`uuid` varchar ( 64 )
);
"""
try:
cur.executescript(sql)
@ -144,7 +148,7 @@ def create_table():
cur.close()
con.close()
def update_db_v_2_0_1():
def update_db_v_2_0_1(**kwargs):
con, cur = get_cur()
sql = """
ALTER TABLE `servers` ADD COLUMN type_ip INTEGER NOT NULL DEFAULT 0;
@ -152,19 +156,19 @@ def update_db_v_2_0_1():
try:
cur.execute(sql)
except sqltool.Error as e:
if e.args[0] == 'duplicate column name: type_ip':
print('Updating... go to version 2.0.1.1<br />')
return False
else:
print("An error occurred:", e)
return False
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: type_ip':
print('Updating... go to version 2.0.1.1<br />')
else:
print("An error occurred:", e)
return False
else:
print("DB was update to 2.0.1<br />")
return True
cur.close()
con.close()
def update_db_v_2_0_1_1():
def update_db_v_2_0_1_1(**kwargs):
con, cur = get_cur()
sql = """
ALTER TABLE `servers` ADD COLUMN enable INTEGER NOT NULL DEFAULT 1;
@ -172,19 +176,19 @@ def update_db_v_2_0_1_1():
try:
cur.execute(sql)
except sqltool.Error as e:
if e.args[0] == 'duplicate column name: enable' or e == "1060 (42S21): Duplicate column name 'enable' ":
print('Updating... go to version 2.0.5<br />')
return False
else:
print("An error occurred:", e)
return False
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: enable' or e == "1060 (42S21): Duplicate column name 'enable' ":
print('Updating... go to version 2.0.5<br />')
else:
print("An error occurred:", e)
return False
else:
print("DB was update to 2.0.1.1<br />")
return True
cur.close()
con.close()
def update_db_v_2_0_5():
def update_db_v_2_0_5(**kwargs):
con, cur = get_cur()
sql = """
ALTER TABLE `servers` ADD COLUMN master INTEGER NOT NULL DEFAULT 0;
@ -192,22 +196,51 @@ def update_db_v_2_0_5():
try:
cur.execute(sql)
except sqltool.Error as e:
if e.args[0] == 'duplicate column name: master':
print('Already updated. No run more. Thx =^.^=')
return False
else:
print("An error occurred:", e)
return False
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: master':
print('Already updated. No run more. Thx =^.^=')
else:
print("An error occurred:", e)
return False
else:
print("DB was update to 2.0.5<br />")
return True
cur.close()
con.close()
def update_db_v_2_4(**kwargs):
con, cur = get_cur()
sql = """
CREATE TABLE IF NOT EXISTS `uuid` (`user_id` INTEGER NOT NULL, `uuid` varchar ( 64 ) );
"""
try:
cur.execute(sql)
except sqltool.Error as e:
print(kwargs.get('silent'))
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: user_id':
print('Already updated. No run more. Thx =^.^=')
else:
print("An error occurred:", e)
return False
else:
if kwargs.get('silent') != 1:
print("DB was update to 2.4 <br />")
return True
cur.close()
con.close()
def update_all():
update_db_v_2_0_1()
update_db_v_2_0_1_1()
update_db_v_2_0_5()
update_db_v_2_4()
def update_all_silent():
update_db_v_2_0_1(silent=1)
update_db_v_2_0_1_1(silent=1)
update_db_v_2_0_5(silent=1)
update_db_v_2_4(silent=1)
#if check_db():
# create_table()

View File

@ -68,23 +68,27 @@ def telegram_send_mess(mess):
bot.send_message(chat_id=channel_name, text=mess)
def check_login(**kwargs):
import sql
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
login = cookie.get('login')
role = cookie.get('role')
user_uuid = cookie.get('uuid')
ref = os.environ.get("SCRIPT_NAME")
if login is None:
if user_uuid is not None:
if sql.get_user_name_by_uuid(user_uuid.value) is None:
print('<meta http-equiv="refresh" content="0; url=login.py?ref=%s">' % ref)
else:
print('<meta http-equiv="refresh" content="0; url=login.py?ref=%s">' % ref)
def is_admin(**kwargs):
import sql
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
role = cookie.get('role')
level = kwargs.get("level")
if role is None:
user_id = cookie.get('uuid')
try:
role = sql.get_user_role_by_uuid(user_id.value)
except:
role = 3
else:
role = int(role.value)
pass
level = kwargs.get("level")
if level is None:
level = 1
@ -206,17 +210,18 @@ def links():
'</li>')
print('</ul>'
'</nav>'
'<div class="copyright-menu">HAproxy-WI v2.3.1</div>'
'<div class="copyright-menu">HAproxy-WI v2.4</div>'
'</div>')
def show_login_links():
import sql
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
login = cookie.get('login')
user_id = cookie.get('uuid')
if login is None:
if user_id is None:
print('<li><a href=/app/login.py? title="Login" class="login">Login</a></li>')
else:
print('<li><a href=/app/login.py?logout=logout title="Logout, user name: %s" class="login">Logout</a></li>' % login.value)
print('<li><a href=/app/login.py?logout=logout title="Logout, user name: %s" class="login">Logout</a></li>' % sql.get_user_name_by_uuid(user_id.value))
def footer():
print('</center></div>'
@ -573,7 +578,7 @@ def ssh_command(serv, commands, **kwargs):
else:
print('<div style="margin: -10px;">'+stdout.read().decode(encoding='UTF-8')+'</div>')
print(stderr.read().decode(encoding='UTF-8')+"<br/>")
print(stderr.read().decode(encoding='UTF-8'))
ssh.close()

View File

@ -23,7 +23,7 @@ print('<script src="/inc/users.js"></script>'
'<td>Slave</td>'
'<td>VRRP interface</td>'
'<td>VRRP IP</td>'
'<td><span title="Will be installed the latest version that you have in the repository">Install HAProxy(?)</span></td>'
'<td><span title="Haproxy-WI will try install haproxy-1.18.5, if it does not work then haproxy-1.15">Install HAProxy(?)</span></td>'
'<td></td>'
'</tr>'
'<tr>'

View File

@ -6,6 +6,8 @@ log_path = ${fullpath}/log/
cert_local_dir = ${cgi_path}/certs/
time_zone = UTC
proxy =
#Time to live users sessions. In days
session_ttl = 5
[configs]
#Server for save configs from HAproxy servers
@ -37,6 +39,8 @@ local_path_logs = /var/log/haproxy.log
#If exist syslog server for HAproxy logs
syslog_server_enable = 0
syslog_server =
#Time of storage of logs of user activity, in days
log_time_storage = 14
[telegram]
#Send log message to telegram channel

View File

@ -29,7 +29,7 @@ print('<script src="/inc/users.js"></script>'
'</td>'
'<td class="padding10 first-collumn">'
'<select id="haproxyaddserv">'
'<option disable selected>Choose master</option>')
'<option disable selected>Choose server</option>')
funct.choose_only_select(serv)
print('</select>'
'</td>'

View File

@ -7,6 +7,9 @@ import funct
import http.cookies
import sql
import create_db
import datetime
import uuid
from configparser import ConfigParser, ExtendedInterpolation
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
form = cgi.FieldStorage()
@ -14,17 +17,23 @@ ref = form.getvalue('ref')
login = form.getvalue('login')
password = form.getvalue('pass')
path_config = "haproxy-webintarface.config"
config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config)
def login_page(error):
if error == "error":
funct.head("Login page")
printError = "<h2>Login page. Enter please</h2><br /><br /><b style='color: red'>Somthing wrong :( I'm sad about this, but try again!</b><br /><br />"
else:
printError = "<h2>Login page. Enter please</h2><br /><br />"
if create_db.check_db():
if create_db.create_table():
print('<div class="alert alert-success">DB was created<br />')
create_db.update_all()
print('<br />Now you can login, default: admin/admin</div>')
create_db.update_all_silent()
ref = form.getvalue('ref')
if ref is None:
@ -38,40 +47,46 @@ def login_page(error):
print('<button type="submit" name="Login" value="Enter">Sign Up</button>')
print('</form></center>')
try:
if config.get('main', 'session_ttl'):
session_ttl = config.getint('main', 'session_ttl')
except:
print('<center><div class="alert alert-danger">Can not find "session_ttl" parametr. Check into config, "main" section</div>')
if form.getvalue('logout') is not None:
print("Set-cookie: login=; expires=Wed May 18 03:33:20 2003; path=/app/; httponly")
print("Set-cookie: role=; expires=Wed May 18 03:33:20 2003; path=/app/; httponly")
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
user_id = cookie.get('uuid')
try:
sql.delete_uuid(user_id.value)
except:
pass
print("Set-cookie: uuid=; expires=Wed May 18 03:33:20 2003; path=/app/; httponly")
print("Content-type: text/html\n")
print('<meta http-equiv="refresh" content="0; url=/overview.py">')
print('<meta http-equiv="refresh" content="0; url=/app/login.py">')
if login is None:
funct.head("Login page")
login_page("n")
if login is not None and password is not None:
if form.getvalue('ref') is None:
ref = "/index.html"
USERS = sql.select_users()
session_ttl = config.getint('main', 'session_ttl')
expires = datetime.datetime.utcnow() + datetime.timedelta(days=session_ttl)
user_uuid = str(uuid.uuid4())
for users in USERS:
if login in users[1] and password == users[3]:
if users[4] == "admin":
role = 1
elif users[4] == "editor":
role = 2
else:
role = 3
c = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
c["login"] = login
c["login"]["path"] = "/app/"
c["login"]["expires"] = "Wed May 18 03:33:20 2033"
c["role"] = role
c["role"]["path"] = "/app/"
c["role"]["expires"] = "Wed May 18 03:33:20 2033"
c["group"] = users[4]
c["group"]["path"] = "/app/"
c["group"]["expires"] = "Wed May 18 03:33:20 2033"
c["uuid"] = user_uuid
c["uuid"]["path"] = "/app/"
c["uuid"]["expires"] = expires.strftime("%a, %d %b %Y %H:%M:%S GMT")
print(c)
if form.getvalue('ref') is None:
ref = "/index.html"
print("Content-type: text/html\n")
sql.write_user_uuid(login, user_uuid)
print("Content-type: text/html\n")
print('<html><head><title>Redirecting</title><meta charset="UTF-8">')
print('<link href="/style.css" rel="stylesheet">')
print('<meta http-equiv="refresh" content="0; url=%s">' % ref)

View File

@ -89,6 +89,10 @@ if form.getvalue('ip') is not None and serv is not None:
commands = [ "ip a |grep inet |egrep -v '::1' |awk '{ print $2 }' |awk -F'/' '{ print $1 }'" ]
funct.ssh_command(serv, commands, ip="1")
if form.getvalue('showif'):
commands = ["ip link|grep 'UP' | awk '{print $2}' |awk -F':' '{print $1}'"]
funct.ssh_command(serv, commands, ip="1")
if form.getvalue('action') is not None and serv is not None:
serv = form.getvalue('serv')
action = form.getvalue('action')

View File

@ -81,10 +81,11 @@ def get_overview():
print('<a id="%s" class="start" title="Start HAproxy service" onclick = "if (! confirm(\'Start service?\')) return false;"><img src=/image/pic/start.png alt="start" class="icon"></a>' % server[2])
print('<a id="%s" class="stop" title="Stop HAproxy service" onclick = "return confirm(\'Stop service?\')"><img src=/image/pic/stop.png alt="start" class="icon"></a>' % server[2])
print('<a id="%s" class="restart" title="Restart HAproxy service" onclick = "if (! confirm(\'Restart service?\')) return false;"><img src=/image/pic/update.png alt="restart" class="icon"></a>' % server[2])
print('<a href="/app/configshow.py?serv=%s&open=open#conf" title="Show config"><img src=/image/pic/show.png alt="show" class="icon"></a>' % server[2])
print('<a href="/app/config.py?serv=%s&open=open#conf" title="Edit config"><img src=/image/pic/edit.png alt="edit" class="icon"></a>' % server[2])
print('<a href="/app/diff.py?serv=%s&open=open#diff" title="Compare config"><img src=/image/pic/compare.png alt="compare" class="icon"></a>' % server[2])
print('<a href="/app/map.py?serv=%s&open=open#map" title="Map listen/frontend/backend"><img src=/image/pic/map.png alt="map" class="icon"></a>' % server[2])
if funct.is_admin(level = 2):
print('<a href="/app/configshow.py?serv=%s&open=open#conf" title="Show config"><img src=/image/pic/show.png alt="show" class="icon"></a>' % server[2])
print('<a href="/app/config.py?serv=%s&open=open#conf" title="Edit config"><img src=/image/pic/edit.png alt="edit" class="icon"></a>' % server[2])
print('<a href="/app/diff.py?serv=%s&open=open#diff" title="Compare config"><img src=/image/pic/compare.png alt="compare" class="icon"></a>' % server[2])
print('<a href="/app/map.py?serv=%s&open=open#map" title="Map listen/frontend/backend"><img src=/image/pic/map.png alt="map" class="icon"></a>' % server[2])
print('</td><td>')
funct.ssh_command(server[2], commands1)
print('</td><td></td></tr>')

View File

@ -168,14 +168,14 @@ def update_server_master(master, slave):
try:
cur.execute(sql)
except sqltool.Error as e:
print('<span class="alert alert-danger" id="error">An error occurred: ' + e.args[0] + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
print('<span class="alert alert-danger" id="error">An error occurred: ' + e + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
for id in cur.fetchall():
sql = """ update servers set master = '%s' where ip = '%s' """ % (id[0], slave)
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
print('<span class="alert alert-danger" id="error">An error occurred: ' + e.args[0] + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
print('<span class="alert alert-danger" id="error">An error occurred: ' + e + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
con.rollback()
cur.close()
con.close()
@ -289,13 +289,69 @@ def get_enable_checkbox(id, **kwargs):
cur.close()
con.close()
def write_user_uuid(login, user_uuid):
con, cur = create_db.get_cur()
sql = """ select id from user where username = '%s' """ % login
try:
cur.execute(sql)
except sqltool.Error as e:
print('<span class="alert alert-danger" id="error">An error occurred: ' + e.args[0] + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
for id in cur.fetchall():
sql = """ insert into uuid (user_id, uuid) values('%s', '%s') """ % (id[0], user_uuid)
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
print('<span class="alert alert-danger" id="error">An error occurred: ' + e + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
con.rollback()
cur.close()
con.close()
def delete_uuid(uuid):
con, cur = create_db.get_cur()
sql = """ delete from uuid where uuid = '%s' """ % uuid
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
pass
cur.close()
con.close()
def get_user_name_by_uuid(uuid):
con, cur = create_db.get_cur()
sql = """ select user.username from user left join uuid as uuid on user.id = uuid.user_id where uuid.uuid = '%s' """ % uuid
try:
cur.execute(sql)
except sqltool.Error as e:
print("An error occurred:", e)
else:
for user_id in cur.fetchall():
return user_id[0]
cur.close()
con.close()
def get_user_role_by_uuid(uuid):
con, cur = create_db.get_cur()
sql = """ select role.id from user left join uuid as uuid on user.id = uuid.user_id left join role on role.name = user.role where uuid.uuid = '%s' """ % uuid
try:
cur.execute(sql)
except sqltool.Error as e:
print("An error occurred:", e)
else:
for user_id in cur.fetchall():
return user_id[0]
cur.close()
con.close()
def get_dick_permit(**kwargs):
import http.cookies
import os
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
login = cookie.get('login')
user_id = cookie.get('uuid')
con, cur = create_db.get_cur()
sql = """ select * from user where username = '%s' """ % login.value
sql = """ select * from user where username = '%s' """ % get_user_name_by_uuid(user_id.value)
if kwargs.get('virt'):
type_ip = ""
else:
@ -303,7 +359,7 @@ def get_dick_permit(**kwargs):
try:
cur.execute(sql)
except sqltool.Error as e:
print("An error occurred:", e.args[0])
print("An error occurred:", e)
else:
for group in cur:
if group[5] == '1':

View File

@ -5,6 +5,7 @@ import os, sys
import funct
from configparser import ConfigParser, ExtendedInterpolation
import glob
import datetime
form = cgi.FieldStorage()
viewlog = form.getvalue('viewlogs')
@ -21,18 +22,30 @@ config.read(path_config)
try:
if config.get('main', 'log_path'):
log_path = config.get('main', 'log_path')
time_storage = config.getint('logs', 'log_time_storage')
except:
print('<center><div class="alert alert-danger">Can not find "log_path" parametr. Check into config</div>')
print('<center><div class="alert alert-danger">Can not find "log_path" and "log_time_storage" parametrs. Check into config</div>')
try:
os.chdir(log_path)
except IOError:
print('<center><div class="alert alert-danger">No such file or directory: "%s". Please check log_path in config and exist directory</div>' % log_path)
print('<center><div class="alert alert-danger">No such file or directory: "%s". Please check "log_path" in config and exist directory</div>' % log_path)
sys.exit()
print('<script src="/inc/users.js"></script>'
'<a name="top"></a>'
'<center><h3>Choose log file</h3><br />')
try:
time_storage_hours = time_storage * 24
for dirpath, dirnames, filenames in os.walk(log_path):
for file in filenames:
curpath = os.path.join(dirpath, file)
file_modified = datetime.datetime.fromtimestamp(os.path.getmtime(curpath))
if datetime.datetime.now() - file_modified > datetime.timedelta(hours=time_storage_hours):
os.remove(curpath)
except:
print('<center><div class="alert alert-danger" style="margin: 0; margin-bottom: 10px;">Can\'t delete old logs file. <br> Please check "log_time_storage" in config and <br>exist directory </div>')
pass
print('<select id="viewlogs">'
'<option disabled selected>Choose log</option>')

View File

@ -27,7 +27,7 @@ print('<br />'
'<select autofocus required name="serv" id="serv">'
'<option disabled>Choose server</option>')
funct.choose_only_select(serv, master_slave=1)
funct.choose_only_select(serv, virt=1)
print('</select>'
'<a class="ui-button ui-widget ui-corner-all" id="show" title="Show stats" onclick="showStats()">Show</a>'

View File

@ -1,5 +1,15 @@
var url = "/inc/script.js";
var cur_url = window.location.href.split('/').pop();
cur_url = cur_url.split('?');
var intervalId;
function autoRefreshStyle(autoRefresh) {
var margin;
if (cur_url[0] == "overview.py") {
if(autoRefresh < 60000) {
autoRefresh = 60000;
}
}
autoRefresh = autoRefresh / 1000;
if ( autoRefresh == 60) {
timeRange = " minute"
@ -44,10 +54,6 @@ function setRefreshInterval(interval) {
}
}
var url = "/inc/script.js";
var cur_url = window.location.href.split('/').pop();
cur_url = cur_url.split('?');
var intervalId;
function startSetInterval(interval) {
if (cur_url[0] == "logs.py") {
intervalId = setInterval('showLog()', interval);
@ -56,6 +62,9 @@ function startSetInterval(interval) {
intervalId = setInterval('showStats()', interval);
showStats()
} else if (cur_url[0] == "overview.py") {
if(interval < 60000) {
interval = 60000;
}
intervalId = setInterval('showOverview()', interval);
showOverview();
} else if (cur_url[0] == "viewlogs.py") {
@ -97,7 +106,6 @@ function showOverview() {
type: "GET",
success: function( data ) {
$("#ajax").html(data);
$.getScript(url);
}
} );
}
@ -308,7 +316,7 @@ $( function() {
});
var location = window.location.href;
var cur_url = '/cgi-bin/' + location.split('/').pop();
var cur_url = '/app/' + location.split('/').pop();
cur_url = cur_url.split('?');
$('.menu li').each(function () {
@ -656,6 +664,40 @@ $( function() {
autoFocus: true,
minLength: -1
});
$( "#interface" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "options.py",
data: {
showif:1,
serv: $("#master").val()
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
response(data.split(" "));
}
} );
},
autoFocus: true,
minLength: -1
});
$( "#interface-add" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "options.py",
data: {
showif:1,
serv: $("#master").val()
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
response(data.split(" "));
}
} );
},
autoFocus: true,
minLength: -1
});
$( "#ssl_key_upload" ).click(function() {
$('.alert-danger').remove();
$.ajax( {

View File

@ -107,7 +107,7 @@ $( function() {
}
} );
});
$('.alert-danger').remove();
//$('.alert-danger').remove();
$('#add-user').click(function() {
$('#error').remove();