Now ssh credentials keep in DB, it's more user-frendly and and safer
pull/19/head
Aidaho12 2018-05-07 19:24:22 +06:00
parent ff069069b5
commit 02d5f9ab6b
11 changed files with 239 additions and 44 deletions

View File

@ -126,6 +126,12 @@ def create_table():
`user_id` INTEGER NOT NULL,
`uuid` varchar ( 64 )
);
CREATE TABLE IF NOT EXISTS `cred` (
`enable` INTEGER NOT NULL DEFAULT 1,
`username` VARCHAR ( 64 ) NOT NULL,
`password` VARCHAR ( 64 ) NOT NULL
);
insert into cred('enable','username','password') values ('1', 'root','password');
"""
try:
cur.executescript(sql)
@ -155,6 +161,7 @@ def update_db_v_2_0_1(**kwargs):
"""
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: type_ip':
@ -175,6 +182,7 @@ def update_db_v_2_0_1_1(**kwargs):
"""
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: enable' or e == "1060 (42S21): Duplicate column name 'enable' ":
@ -195,6 +203,7 @@ def update_db_v_2_0_5(**kwargs):
"""
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: master' or e == "1060 (42S21): Duplicate column name 'master' ":
@ -215,11 +224,12 @@ def update_db_v_2_4(**kwargs):
"""
try:
cur.execute(sql)
con.commit()
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 =^.^=')
print('Updating... go to version 2.5.3')
else:
print("An error occurred:", e)
return False
@ -230,17 +240,47 @@ def update_db_v_2_4(**kwargs):
cur.close()
con.close()
def update_db_v_2_5_3(**kwargs):
con, cur = get_cur()
sql = """
CREATE TABLE IF NOT EXISTS `cred` (`enable` INTEGER NOT NULL DEFAULT 1, `username` VARCHAR ( 64 ) NOT NULL, `password` VARCHAR ( 64 ) NOT NULL );
"""
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
print(kwargs.get('silent'))
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: enable':
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.5.3<br />")
sql2 = """
insert into `cred` (`enable`,`username`,`password`) values ('1', 'root','password');
"""
cur.execute(sql2)
con.commit()
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()
update_db_v_2_5_3()
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)
update_db_v_2_5_3(silent=1)
#if check_db():
# create_table()

View File

@ -18,7 +18,6 @@ fullpath = config.get('main', 'fullpath')
time_zone = config.get('main', 'time_zone')
proxy = config.get('main', 'proxy')
ssh_keys = config.get('ssh', 'ssh_keys')
ssh_user_name = config.get('ssh', 'ssh_user_name')
haproxy_configs_server = config.get('configs', 'haproxy_configs_server')
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
haproxy_config_path = config.get('haproxy', 'haproxy_config_path')
@ -123,44 +122,63 @@ def get_button(button, **kwargs):
print('<button type="submit" value="%s" name="%s" class="btn btn-default">%s</button>' % (value, value, button))
def ssh_connect(serv, **kwargs):
import sql
ssh_enable = sql.ssh_enable()
ssh_user_name = sql.select_ssh_username()
ssh = SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
if config.get('ssh', 'ssh_keys_enable') == "1":
if ssh_enable == 1:
k = paramiko.RSAKey.from_private_key_file(ssh_keys)
ssh.connect(hostname = serv, username = ssh_user_name, pkey = k )
else:
ssh.connect(hostname = serv, username = ssh_user_name, password = config.get('ssh', 'ssh_pass'))
ssh.connect(hostname = serv, username = ssh_user_name, password = sql.select_ssh_password())
if kwargs.get('check'):
return True
else:
return ssh
except paramiko.AuthenticationException:
print('<div class="alert alert-danger">Authentication failed, please verify your credentials</div>')
error = 'Authentication failed, please verify your credentials'
return False
if kwargs.get('check'):
print('<div class="alert alert-danger">Authentication failed, please verify your credentials</div>')
return False
else:
return 'Authentication failed, please verify your credentials'
except paramiko.SSHException as sshException:
print('<div class="alert alert-danger">Unable to establish SSH connection: %s </div>' % sshException)
error = 'Unable to establish SSH connection: %s ' % sshException
return False
if kwargs.get('check'):
print('<div class="alert alert-danger">Unable to establish SSH connection: %s </div>' % sshException)
return False
else:
return 'Unable to establish SSH connection: %s ' % sshException
except paramiko.BadHostKeyException as badHostKeyException:
print('<div class="alert alert-danger">Unable to verify server\'s host key: %s </div>' % badHostKeyException)
error = 'Unable to verify server\'s host key: %s ' % badHostKeyException
return False
if kwargs.get('check'):
print('<div class="alert alert-danger">Unable to verify server\'s host key: %s </div>' % badHostKeyException)
return False
else:
return 'Unable to verify server\'s host key: %s ' % badHostKeyException
except Exception as e:
if e.args[1] == "No such file or directory":
print('<div class="alert alert-danger">{}. Check ssh key</div>'.format(e.args[1]))
error = '{}. Check ssh key'.format(e.args[1])
if kwargs.get('check'):
print('<div class="alert alert-danger">{}. Check ssh key</div>'.format(e.args[1]))
else:
return '{}. Check ssh key'.format(e.args[1])
elif e.args[1] == "Invalid argument":
print('<div class="alert alert-danger">Check the IP of the new server</div>')
error = 'Check the IP of the new server'
if kwargs.get('check'):
print('<div class="alert alert-danger">Check the IP of the new server</div>')
else:
error = 'Check the IP of the new server'
else:
print('<div class="alert alert-danger">{}</div>'.format(e.args[1]))
error = e.args[1]
return False
if kwargs.get('check'):
print('<div class="alert alert-danger">{}</div>'.format(e.args[1]))
else:
error = e.args[1]
if kwargs.get('check'):
return False
else:
return error
def get_config(serv, cfg, **kwargs):
error = ""
if kwargs.get("keepalived"):
config_path = "/etc/keepalived/keepalived.conf"
else:
@ -173,7 +191,8 @@ def get_config(serv, cfg, **kwargs):
sftp.close()
ssh.close()
except Exception as e:
return str(e)
ssh += str(e)
return ssh
def show_config(cfg):
print('<div style="margin-left: 16%" class="configShow">')

View File

@ -25,13 +25,8 @@ mysql_db = haproxywi
mysql_host = 127.0.0.1
[ssh]
#If ssh connect disable entare password for ssh connect. Default enable
ssh_keys_enable = 1
#SSH keys to connect without password to HAproxy servers
ssh_keys = ${main:fullpath}/app/id_rsa.pem
#Username for connect ssh
ssh_user_name = root
ssh_pass =
[logs]
#Logs save locally, disable by default

View File

@ -44,15 +44,14 @@ if form.getvalue('serv') is not None and form.getvalue('open') is not None :
funct.logging(serv, "keepalivedconfig.py open config")
except:
pass
funct.get_config(serv, cfg, keepalived=1)
error = funct.get_config(serv, cfg, keepalived=1)
try:
conf = open(cfg, "r",encoding='utf-8', errors='ignore')
config_read = conf.read()
conf.close
except IOError:
print('<div class="alert alert-danger">Can\'t read import config file</div>')
conf.close
error += "<br>Can't read import config file"
os.system("/bin/mv %s %s.old" % (cfg, cfg))
@ -70,7 +69,7 @@ if form.getvalue('serv') is not None and form.getvalue('config') is not None:
with open(cfg, "a") as conf:
conf.write(config)
except IOError:
print("Can't read import config file")
error += "Can't read import config file"
stderr = funct.upload_and_restart(serv, cfg, just_save=save, keepalived=1)

View File

@ -49,12 +49,6 @@ except:
user = ""
pass
if create_db.check_db():
if create_db.create_table():
create_db.update_all()
db_create = '<div class="alert alert-success">DB was created<br /><br />Now you can login, default: admin/admin</div>'
create_db.update_all_silent()
if form.getvalue('logout'):
try:
sql.delete_uuid(user_id.value)
@ -91,6 +85,11 @@ if login is not None and password is not None:
if login is None:
print("Content-type: text/html\n")
if create_db.check_db():
if create_db.create_table():
create_db.update_all()
db_create = '<div class="alert alert-success">DB was created<br /><br />Now you can login, default: admin/admin</div>'
output_from_parsed_template = template.render(h2 = 1, title = "Login page. Enter please",
role = role,
user = user,

View File

@ -1,5 +1,6 @@
#!/usr/bin/env python3
import funct, sql
import create_db
import os, http
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/'))
@ -7,6 +8,7 @@ template = env.get_template('ovw.html')
print('Content-type: text/html\n')
funct.check_login()
create_db.update_all_silent()
try:
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))

View File

@ -214,7 +214,7 @@ def select_user_name_group(id):
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>')
else:
for group in cur.fetchone():
return group
@ -389,7 +389,62 @@ def is_master(ip, **kwargs):
return cur.fetchall()
cur.close()
con.close()
def ssh_enable():
con, cur = create_db.get_cur()
sql = """select enable from cred """
try:
cur.execute(sql)
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>')
else:
for enable in cur.fetchone():
return enable
cur.close()
con.close()
def select_ssh_username():
con, cur = create_db.get_cur()
sql = """select username from cred """
try:
cur.execute(sql)
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>')
else:
for username in cur.fetchone():
return username
cur.close()
con.close()
def select_ssh_password():
con, cur = create_db.get_cur()
sql = """select password from cred """
try:
cur.execute(sql)
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>')
else:
for password in cur.fetchone():
return password
cur.close()
con.close()
def update_ssh(enable, username, password):
con, cur = create_db.get_cur()
sql = """
update cred set
enable = '%s',
username = '%s',
password = '%s' """ % (enable, username, password)
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 show_update_servers():
SERVERS = select_servers()
print('<tr class="overviewHead">'
@ -612,4 +667,15 @@ if form.getvalue('updateserver') is not None:
if funct.ssh_connect(ip, check=1):
update_server(name, ip, group, typeip, enable, master, id)
else:
print('<span class="alert alert-danger" id="error"><a title="Close" id="errorMess"><b>X</b></a></span>')
print('<span class="alert alert-danger" id="error"><a title="Close" id="errorMess"><b>X</b></a></span>')
if form.getvalue('updatessh'):
enable = form.getvalue('ssh_enable')
username = form.getvalue('ssh_user')
password = form.getvalue('ssh_pass')
if username is None:
print('Content-type: text/html\n')
print(error_mess)
else:
print('Content-type: text/html\n')
update_ssh(enable, username, password)

View File

@ -7,7 +7,7 @@
<li><a href="#groups">Groups</a></li>
<li><a href="#servers">Servers</a></li>
<li><a href="#roles">Roles</a></li>
<li><a href="#cert">SSH key</a></li>
<li><a href="#ssh">SSH credentials</a></li>
</ul>
<div id="users">
<table class="overview" id="ajax-users">
@ -277,8 +277,34 @@
{% endfor %}
</table>
</div>
<div id="cert">
<table id="ssh">
<div id="ssh">
<table id="ssh_enable_table">
<tr class="overviewHead" style="width: 50%;">
<td class="padding10 first-collumn">SSH key</td>
<td>
<span title="Enter SSH user name. If SSH key disabled, enter password for ssh user">Credentials(?)</span>
</td>
<td></td>
</tr>
<tr style="width: 50%;">
<td class="first-collumn" valign="top" style="padding-top: 15px;">
{% if ssh_enable == 1 %}
<label for="ssh_enable">Enable SSH<input type="checkbox" id="ssh_enable" checked>
{% else %}
<label for="ssh_enable">Enable SSH<input type="checkbox" id="ssh_enable">
{% endif %}
</td>
<td style="padding-top: 15px;">
<p>
<input type="text" id="ssh_user" class="form-control" value="{{ssh_user}}">
</p>
<input type="password" id="ssh_pass" class="form-control" value="{{ssh_pass}}" style="display: none;">
<br>
</td>
<td></td>
</tr>
</table>
<table id="ssh_key">
<tr class="overviewHead" style="width: 50%;">
<td class="padding10 first-collumn">Upload SSH Key</td>
<td>

View File

@ -87,6 +87,7 @@
<li><a href=/app/users.py#groups title="Actions with groups" class="group head-submenu">Groups</a></li>
<li><a href=/app/users.py#servers title="Actions with servers" class="runtime head-submenu">Servers</a></li>
<li><a href=/app/users.py#roles title="Users roles" class="role head-submenu">Roles</a></li>
<li><a href=/app/users.py#ssh title="Users roles" class="admin head-submenu">SSH credentials</a></li>
<li><a href=/app/settings.py title="View settings" class="settings head-submenu">View settings</a></li>
<li><a href=/app/viewlogs.py title="View users actions logs" class="logs head-submenu">View logs</a></li>
</li>
@ -94,7 +95,7 @@
{% endif %}
</ul>
</nav>
<div class="copyright-menu">HAproxy-WI v2.5.2</div>
<div class="copyright-menu">HAproxy-WI v2.5.3</div>
</div>
</div>
<div class="container">

View File

@ -28,5 +28,8 @@ output_from_parsed_template = template.render(title = "Admin area: users manage"
groups = sql.select_groups(),
servers = sql.select_servers(full=1),
roles = sql.select_roles(),
masters = sql.select_servers(get_master_servers=1))
masters = sql.select_servers(get_master_servers=1),
ssh_enable = sql.ssh_enable(),
ssh_user = sql.select_ssh_username(),
ssh_pass = sql.select_ssh_password())
print(output_from_parsed_template)

View File

@ -252,6 +252,21 @@ $( function() {
var id = $(this).attr('id').split('-');
updateServer(id[1])
});
$( "#ssh_enable_table input" ).change(function() {
updateSSH()
});
$('#ssh_enable').click(function() {
if ($('#ssh_enable').is(':checked')) {
$('#ssh_pass').css('display', 'none');
} else {
$('#ssh_pass').css('display', 'block');
}
});
if ($('#ssh_enable').is(':checked')) {
$('#ssh_pass').css('display', 'none');
} else {
$('#ssh_pass').css('display', 'block');
}
} );
function removeUser(id) {
$("#user-"+id).css("background-color", "#f2dede");
@ -419,4 +434,34 @@ function uploadSsh() {
}
}
} );
}
function updateSSH() {
$('#error').remove();
var ssh_enable = 0;
if ($('#ssh_enable').is(':checked')) {
ssh_enable = '1';
}
$.ajax( {
url: "sql.py",
data: {
updatessh: 1,
ssh_enable: ssh_enable,
ssh_user: $('#ssh_user').val(),
ssh_pass: $('#ssh_pass').val(),
},
type: "GET",
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error') != '-1') {
$("#ajax-ssh").append(data);
$.getScript(users);
} else {
$('.alert-danger').remove();
$("#ssh_enable_table").addClass( "update", 1000 );
setTimeout(function() {
$( "#ssh_enable_table" ).removeClass( "update" );
}, 2500 );
}
}
} );
}