Merge pull request #361 from FirmlyReality/master

FIx Sercurity bug
This commit is contained in:
Yujian Zhu 2018-12-12 20:07:14 +08:00 committed by GitHub
commit 23c5823bf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 159 additions and 69 deletions

View File

@ -1,10 +1,19 @@
server server
{ {
listen %NGINX_PORT; listen %NGINX_PORT;
#ssl on;
#ssl_certificate /etc/nginx/ssl/1604242_iwork.pku.edu.cn.pem;
#ssl_certificate_key /etc/nginx/ssl/1604242_iwork.pku.edu.cn.key;
server_name nginx_docklet.conf; server_name nginx_docklet.conf;
charset UTF-8; charset UTF-8;
add_header X-Frame-Options SAMEORIGIN;
merge_slashes off;
rewrite (.*)//+(.*) $1/$2 permanent;
index index.html index.htm; index index.html index.htm;
client_max_body_size 20m; client_max_body_size 20m;
if ($request_method !~* GET|POST){
return 403;
}
location ~ ^/NginxStatus/ { location ~ ^/NginxStatus/ {
stub_status on; stub_status on;
access_log off; access_log off;

View File

@ -23,6 +23,7 @@ apt-get install -y nodejs nodejs-legacy npm
apt-get install -y etcd apt-get install -y etcd
apt-get install -y glusterfs-client attr apt-get install -y glusterfs-client attr
apt-get install -y nginx apt-get install -y nginx
pip3 install Flask-WTF
#add ip forward #add ip forward
echo "net.ipv4.ip_forward=1" >>/etc/sysctl.conf echo "net.ipv4.ip_forward=1" >>/etc/sysctl.conf

View File

@ -7,7 +7,7 @@ Warning: in some early versions, "token" stand for the instance of class model.U
Original author: Liu Peidong Original author: Liu Peidong
''' '''
from utils.model import db, User, UserGroup, Notification, UserUsage, LoginMsg from utils.model import db, User, UserGroup, Notification, UserUsage, LoginMsg, LoginFailMsg
from functools import wraps from functools import wraps
import os, subprocess, math import os, subprocess, math
import hashlib import hashlib
@ -19,7 +19,7 @@ import smtplib
from email.mime.text import MIMEText from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.header import Header from email.header import Header
from datetime import datetime from datetime import datetime, timedelta
import json import json
from utils.log import logger from utils.log import logger
from utils.lvmtool import * from utils.lvmtool import *
@ -144,7 +144,6 @@ class userManager:
''' '''
try: try:
User.query.all() User.query.all()
LoginMsg.query.all()
except: except:
db.create_all() db.create_all()
if password == None: if password == None:
@ -202,6 +201,8 @@ class userManager:
try: try:
UserUsage.query.all() UserUsage.query.all()
LoginMsg.query.all()
LoginFailMsg.query.all()
except: except:
db.create_all() db.create_all()
@ -209,9 +210,9 @@ class userManager:
password = hashlib.sha512(password.encode('utf-8')).hexdigest() password = hashlib.sha512(password.encode('utf-8')).hexdigest()
user = User.query.filter_by(username = username).first() user = User.query.filter_by(username = username).first()
if (user == None): if (user == None):
return {"success":'false', "reason": "User did not exist"} return {"success":'false', "reason": "User does not exist!"}
if (user.password != password): if (user.password != password):
return {"success":'false', "reason": "Wrong password"} return {"success":'false', "reason": "Wrong password!"}
result = { result = {
"success": 'true', "success": 'true',
"data":{ "data":{
@ -230,7 +231,7 @@ class userManager:
user = User.query.filter_by(username = username).first() user = User.query.filter_by(username = username).first()
pamresult = PAM.authenticate(username, password) pamresult = PAM.authenticate(username, password)
if (pamresult == False or (user != None and user.auth_method != 'pam')): if (pamresult == False or (user != None and user.auth_method != 'pam')):
return {"success":'false', "reason": "Wrong password or wrong login method"} return {"success":'false', "reason": "Wrong password or wrong login method!"}
if (user == None): if (user == None):
newuser = self.newuser(); newuser = self.newuser();
newuser.username = username newuser.username = username
@ -327,21 +328,45 @@ class userManager:
return a token as well as some user information return a token as well as some user information
''' '''
user = User.query.filter_by(username = username).first() user = User.query.filter_by(username = username).first()
failmsg = LoginFailMsg.query.filter_by(username = username).first()
result = {} result = {}
if (user == None or user.auth_method =='pam'): if failmsg == None:
result = self.auth_pam(username, password) newfailmsg = LoginFailMsg(username)
elif (user.auth_method == 'local'): db.session.add(newfailmsg)
db.session.commit()
failmsg = newfailmsg
elif failmsg.failcnt > 40:
reason = "You have been input wrong password over 40 times. You account will be locked. Please contact administrators for help."
logger.info("Login failed: userip=%s reason:%s" % (userip,reason))
return {'success':'false', 'reason':reason}
elif datetime.now() < failmsg.bantime:
reason = "You have been input wrong password %d times. Please try after %s." % (failmsg.failcnt, failmsg.bantime.strftime("%Y-%m-%d %H:%M:%S"))
logger.info("Login failed: userip=%s reason:%s" % (userip,reason))
return {'success':'false', 'reason':reason}
if (user == None or user.auth_method =='local'):
result = self.auth_local(username, password) result = self.auth_local(username, password)
elif (user.auth_method == 'pam'):
result = self.auth_pam(username, password)
else: else:
result = {'success':'false', 'reason':'auth_method error'} result = {'success':'false', 'reason':'auth_method error!'}
if result['success'] == 'true': if result['success'] == 'true':
loginmsg = LoginMsg(result['data']['username'],userip) loginmsg = LoginMsg(result['data']['username'],userip)
failmsg.failcnt = 0
db.session.add(loginmsg) db.session.add(loginmsg)
db.session.commit() db.session.commit()
logger.info("Login success: username=%s, userip=%s" % (result['data']['username'], userip)) logger.info("Login success: username=%s, userip=%s" % (result['data']['username'], userip))
else: else:
logger.info("Login failed: userip=%s" % (userip)) logger.info("Login failed: userip=%s" % (userip))
failmsg.failcnt += 1
if failmsg.failcnt == 10:
failmsg.bantime = datetime.now() + timedelta(minutes=10)
elif failmsg.failcnt == 20:
failmsg.bantime = datetime.now() + timedelta(minutes=100)
elif failmsg.failcnt == 30:
failmsg.bantime = datetime.now() + timedelta(days=1)
db.session.commit()
return result return result
def auth_token(self, token): def auth_token(self, token):

View File

@ -221,6 +221,20 @@ class LoginMsg(db.Model):
def __repr__(self): def __repr__(self):
return '<id=%d, username=%s, userip=%s, time=%s>' % (self.id,self.username,self.userip,self.time.strftime("%Y-%m-%d %H:%M:%S")) return '<id=%d, username=%s, userip=%s, time=%s>' % (self.id,self.username,self.userip,self.time.strftime("%Y-%m-%d %H:%M:%S"))
class LoginFailMsg(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(10), unique=True)
failcnt = db.Column(db.Integer)
bantime = db.Column(db.DateTime)
def __init__(self, username):
self.username = username
self.failcnt = 0
self.bantime = datetime.now()
def __repr__(self):
return '<id=%d, username=%s, failcnt=%d, bantime=%s>' % (self.id,self.username,self.failcnt,self.bantime.strftime("%Y-%m-%d %H:%M:%S"))
class VNode(db.Model): class VNode(db.Model):
__bind_key__ = 'history' __bind_key__ = 'history'
name = db.Column(db.String(100), primary_key=True) name = db.Column(db.String(100), primary_key=True)

View File

@ -94,7 +94,7 @@ def login():
auth_result = G_usermgr.auth(user,key,userip) auth_result = G_usermgr.auth(user,key,userip)
if auth_result['success'] == 'false': if auth_result['success'] == 'false':
logger.info("%s login failed" % user) logger.info("%s login failed" % user)
return json.dumps({'success':'false', 'message':'auth failed'}) return json.dumps({'success':'false', 'message':auth_result['reason']})
logger.info("%s login success" % user) logger.info("%s login success" % user)
return json.dumps({'success':'true', 'action':'login', 'data': auth_result['data']}) return json.dumps({'success':'true', 'action':'login', 'data': auth_result['data']})
@ -473,7 +473,7 @@ def query_self_notifications_infos(cur_user, user, form):
result = G_notificationmgr.query_self_notifications_infos(cur_user=cur_user, form=form) result = G_notificationmgr.query_self_notifications_infos(cur_user=cur_user, form=form)
return json.dumps(result) return json.dumps(result)
@app.route("/bug/report/", methods=['POST']) @app.route("/bug/report/", methods=['POST'])
@login_required @login_required
def report_bug(cur_user, user, form): def report_bug(cur_user, user, form):
logger.info("handle request: bug/report") logger.info("handle request: bug/report")

View File

@ -159,7 +159,7 @@ var host = window.location.host;
var node_name = $("#node_name").html(); var node_name = $("#node_name").html();
var masterip = $("#masterip").html(); var masterip = $("#masterip").html();
var url = "http://" + host + "/monitor/" + masterip + "/vnodes/" + node_name; var url = "//" + host + "/monitor/" + masterip + "/vnodes/" + node_name;
function num2human(data) function num2human(data)
{ {
@ -260,7 +260,7 @@ function processInfo()
function plot_net(host,monitorurl) function plot_net(host,monitorurl)
{ {
var url = "http://" + host + "/user/selfQuery/"; var url = "//" + host + "/user/selfQuery/";
$.post(url,{},function(data){ $.post(url,{},function(data){
ingress_rate_limit = parseInt(data.groupinfo.input_rate_limit); ingress_rate_limit = parseInt(data.groupinfo.input_rate_limit);

View File

@ -4,7 +4,7 @@ var total = 0;
var idle = 0; var idle = 0;
var disk_usedp = 0; var disk_usedp = 0;
var count = 0; var count = 0;
var Ki = 1024; var Ki = 1024;
var is_running = true; var is_running = true;
function processMemData(data) function processMemData(data)
@ -15,7 +15,7 @@ function processMemData(data)
total = data.monitor.meminfo.total; total = data.monitor.meminfo.total;
var used2 = ((data.monitor.meminfo.used)/Ki).toFixed(2); var used2 = ((data.monitor.meminfo.used)/Ki).toFixed(2);
var total2 = ((data.monitor.meminfo.total)/Ki).toFixed(2); var total2 = ((data.monitor.meminfo.total)/Ki).toFixed(2);
var free2 = ((data.monitor.meminfo.free)/Ki).toFixed(2); var free2 = ((data.monitor.meminfo.free)/Ki).toFixed(2);
$("#mem_used").html(used2); $("#mem_used").html(used2);
$("#mem_total").html(total2); $("#mem_total").html(total2);
$("#mem_free").html(free2); $("#mem_free").html(free2);
@ -32,7 +32,7 @@ function getMemY()
{ {
if(total == 0) if(total == 0)
return 0; return 0;
else else
return (used/total)*100; return (used/total)*100;
} }
function processCpuData(data) function processCpuData(data)
@ -101,8 +101,8 @@ function plot_graph(container,url,processData,getY) {
// //
var data = []; var data = [];
function getBaseData() { function getBaseData() {
@ -211,7 +211,7 @@ var host = window.location.host;
var com_ip = $("#com_ip").html(); var com_ip = $("#com_ip").html();
var masterip = $("#masterip").html(); var masterip = $("#masterip").html();
var url = "http://" + host + "/monitor/" + masterip + "/hosts/"+com_ip; var url = "//" + host + "/monitor/" + masterip + "/hosts/"+com_ip;
function processStatus() function processStatus()
{ {
@ -229,4 +229,3 @@ plot_graph($("#mem-chart"), url + "/meminfo/" ,processMemData,getMemY);
plot_graph($("#cpu-chart"), url + "/cpuinfo/",processCpuData,getCpuY); plot_graph($("#cpu-chart"), url + "/cpuinfo/",processCpuData,getCpuY);
//plot_graph($("#disk-chart"), url + "/diskinfo",processDiskData,getDiskY); //plot_graph($("#disk-chart"), url + "/diskinfo",processDiskData,getDiskY);
$.post(url+"/diskinfo/",{},processDiskData,"json"); $.post(url+"/diskinfo/",{},processDiskData,"json");

View File

@ -38,7 +38,7 @@
</div> </div>
<div class="box-body"> <div class="box-body">
<form id="form" class="form-horizontal" action="/workspace/{{masterips[0].split("@")[0]}}/add/" method="POST"> <form id="form" class="form-horizontal" action="/workspace/{{masterips[0].split("@")[0]}}/add/" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"><label class="col-sm-2 control-label">Workspace Name</label> <div class="form-group"><label class="col-sm-2 control-label">Workspace Name</label>
<div class="col-sm-10"><input type="text" class="form-control" name="clusterName" id="clusterName"></div> <div class="col-sm-10"><input type="text" class="form-control" name="clusterName" id="clusterName"></div>
</div> </div>
@ -94,7 +94,7 @@
<td>{{image['name']}}</td> <td>{{image['name']}}</td>
<td>public</td> <td>public</td>
<td>{{p_user}}</td> <td>{{p_user}}</td>
<td>{{image['size_format']}}</td> <td>{{image['size_format']}}</td>
<td><a href="/image/{{masterips[0].split("@")[0]}}/description/{{image['name']}}_{{p_user}}_public/" target="_blank">{{image['description']}}</a></td> <td><a href="/image/{{masterips[0].split("@")[0]}}/description/{{image['name']}}_{{p_user}}_public/" target="_blank">{{image['description']}}</a></td>
<td><div class="i-checks"><label><input type="radio" name="image" value="{{image['name']}}_{{p_user}}_public" onchange="setMinDiskSize({{image['size_in_mb']}})"></label></div></td> <td><div class="i-checks"><label><input type="radio" name="image" value="{{image['name']}}_{{p_user}}_public" onchange="setMinDiskSize({{image['size_in_mb']}})"></label></div></td>
</tr> </tr>
@ -156,20 +156,18 @@
{% block script_src %} {% block script_src %}
<!-- Custom and plugin javascript --> <!-- Custom and plugin javascript -->
<script src="/static/js/inspinia.js"></script> <script src="https://cdn.bootcss.com/pace/1.0.2/pace.min.js"></script>
<script src="http://cdn.bootcss.com/pace/1.0.2/pace.min.js"></script>
<!-- Steps --> <!-- Steps -->
<script src="http://cdn.bootcss.com/jquery-steps/1.1.0/jquery.steps.min.js"></script> <script src="https://cdn.bootcss.com/jquery-steps/1.1.0/jquery.steps.min.js"></script>
<!-- Jquery Validate --> <!-- Jquery Validate -->
<script src="http://cdn.bootcss.com/jquery-validate/1.15.0/jquery.validate.min.js"></script> <script src="https://cdn.bootcss.com/jquery-validate/1.15.0/jquery.validate.min.js"></script>
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script> <script src="https://cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script>
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script> <script src="https://cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script>
<script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script> <script src="https://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
function setMinDiskSize(minSize) { function setMinDiskSize(minSize) {
@ -185,10 +183,10 @@
console.log(masterip); console.log(masterip);
document.getElementById("form").action="/workspace/"+masterip+"/add/"; document.getElementById("form").action="/workspace/"+masterip+"/add/";
var host = window.location.host; var host = window.location.host;
$.post("http://"+host+"/getmasterdesc/"+mastername+"/", {}, function(data) { $.post("//"+host+"/getmasterdesc/"+mastername+"/", {}, function(data) {
$("#masterdesc").html(data); $("#masterdesc").html(data);
}); });
$.post("http://"+host+"/image/"+masterip+"/list/",{},function(data){ $.post("//"+host+"/image/"+masterip+"/list/",{},function(data){
var images = data.images; var images = data.images;
var imagehtml = var imagehtml =
"<thread>" "<thread>"

View File

@ -117,6 +117,7 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<!-- The user image in the menu --> <!-- The user image in the menu -->
<form action="/bug/report/" method="POST"> <form action="/bug/report/" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<textarea id="bugmessage" name="bugmessage" style="width:250px; height:200px"></textarea> <textarea id="bugmessage" name="bugmessage" style="width:250px; height:200px"></textarea>
<li class="user-footer" style="background-color:#e6e6e6"> <li class="user-footer" style="background-color:#e6e6e6">
<div class="pull-right"> <div class="pull-right">
@ -290,6 +291,9 @@
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
$.ajaxSetup({
headers: {'X-CSRFToken':'{{ csrf_token() }}'},
});
var ajaxCfg = { var ajaxCfg = {
type : "post", type : "post",
url : '/notification/query_self/', url : '/notification/query_self/',

View File

@ -48,6 +48,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="/beans/apply/" method="POST" id="beansapplyForm"> <form action="/beans/apply/" method="POST" id="beansapplyForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>Number</label><small class="font-bold"> How many beans do you need?</small> <label>Number</label><small class="font-bold"> How many beans do you need?</small>
<input type="number" class="form-control" placeholder="100-5000" name="number" id="number" min="100" max="5000" required /> <input type="number" class="form-control" placeholder="100-5000" name="number" id="number" min="100" max="5000" required />
@ -101,9 +102,9 @@
{% block script_src %} {% block script_src %}
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script>
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script>
<script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script> <script src="//cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script>
<script src="https://cdn.bootcss.com/jquery-validate/1.17.0/jquery.validate.js"></script> <script src="https://cdn.bootcss.com/jquery-validate/1.17.0/jquery.validate.js"></script>
<script> <script>

View File

@ -55,6 +55,7 @@
</div> </div>
<div class="box-body table-responsive"> <div class="box-body table-responsive">
<form action="/cloud/{{master.split("@")[0]}}/setting/modify/" method="POST"> <form action="/cloud/{{master.split("@")[0]}}/setting/modify/" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<textarea id="setting" name="setting" class="form-control" rows="20">{{ info['result'] }}</textarea> <textarea id="setting" name="setting" class="form-control" rows="20">{{ info['result'] }}</textarea>
<button type="submit" class="btn btn-primary">Save</button> <button type="submit" class="btn btn-primary">Save</button>
</form> </form>
@ -69,5 +70,5 @@
{% block script_src %} {% block script_src %}
<script src="//cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.min.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.min.js"></script>
<script src="//cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.min.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.min.js"></script>
<script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script> <script src="https://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script>
{% endblock %} {% endblock %}

View File

@ -74,6 +74,7 @@
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<form action="/workspace/{{master.split("@")[0]}}/scaleout/{{ clustername }}/" method="POST" > <form action="/workspace/{{master.split("@")[0]}}/scaleout/{{ clustername }}/" method="POST" >
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<table class="table table-striped table-bordered table-hover table-image"> <table class="table table-striped table-bordered table-hover table-image">
<thead> <thead>
<tr> <tr>
@ -199,6 +200,7 @@
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<form action="/workspace/{{master.split("@")[0]}}/save/{{ clustername }}/{{ container['containername'] }}/" method="POST" id="saveImage"> <form action="/workspace/{{master.split("@")[0]}}/save/{{ clustername }}/{{ container['containername'] }}/" method="POST" id="saveImage">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<label>Image Name</label> <label>Image Name</label>
<input type="text" placeholder="Enter Image Name" class="form-control" name="ImageName" id="ImageName"/> <input type="text" placeholder="Enter Image Name" class="form-control" name="ImageName" id="ImageName"/>
<br/> <br/>
@ -249,6 +251,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="/port_mapping/add/{{master.split("@")[0]}}/" method="POST" id="AddportsmappingForm"> <form action="/port_mapping/add/{{master.split("@")[0]}}/" method="POST" id="AddportsmappingForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>Cluster Name</label> <label>Cluster Name</label>
<input type = "text" value="{{ clustername }}" class="form-control" name="clustername" readonly="readonly"> <input type = "text" value="{{ clustername }}" class="form-control" name="clustername" readonly="readonly">
@ -376,6 +379,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="/image/{{master.split("@")[0]}}/copy/{{image['name']}}/" method="POST" id="CopyImageForm"> <form action="/image/{{master.split("@")[0]}}/copy/{{image['name']}}/" method="POST" id="CopyImageForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<table class="table table-striped table-bordered table-hover table-image"> <table class="table table-striped table-bordered table-hover table-image">
<thead> <thead>
<tr> <tr>
@ -445,9 +449,9 @@
{% block script_src %} {% block script_src %}
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script>
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script>
<script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script> <script src="//cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {

View File

@ -37,6 +37,7 @@
<div class="box-body"> <div class="box-body">
<form id="notificationForm" class="form-horizontal" action="/notification/create/" method="post"> <form id="notificationForm" class="form-horizontal" action="/notification/create/" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label">Title</label> <label class="col-sm-2 control-label">Title</label>
<div class="col-sm-10"> <div class="col-sm-10">

8
web/templates/home.template Executable file → Normal file
View File

@ -7,8 +7,8 @@
<title>Docklet | Home</title> <title>Docklet | Home</title>
<link rel="shortcut icon" href="/static/img/favicon.ico"> <link rel="shortcut icon" href="/static/img/favicon.ico">
<link href="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<link href="http://cdn.bootcss.com/font-awesome/4.5.0/css/font-awesome.css" rel="stylesheet"> <link href="https://cdn.bootcss.com/font-awesome/4.5.0/css/font-awesome.css" rel="stylesheet">
<style type="text/css"> <style type="text/css">
a.linkbtn, a.linkbtn:visited, a.linkbtn:active{ a.linkbtn, a.linkbtn:visited, a.linkbtn:active{
@ -133,7 +133,7 @@
</div> </div>
<script src="http://cdn.bootcss.com/jquery/2.2.1/jquery.js"></script> <script src="https://cdn.bootcss.com/jquery/2.2.1/jquery.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <script src="https://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body> </body>
</html> </html>

View File

@ -76,6 +76,7 @@
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<form action="/cluster/save/{{ clustername }}/{{ container['containername'] }}/" method="GET" id="saveImage"> <form action="/cluster/save/{{ clustername }}/{{ container['containername'] }}/" method="GET" id="saveImage">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<label>Image Name</label> <label>Image Name</label>
<input type="text" placeholder="Enter image name" class="form-control" name="ImageName" id="ImageName"/> <input type="text" placeholder="Enter image name" class="form-control" name="ImageName" id="ImageName"/>
<div class="modal-footer"> <div class="modal-footer">

View File

@ -31,14 +31,20 @@
<div class="login-box-body"> <div class="login-box-body">
<p class="login-box-msg">An easy and quick way to launch your DISTRIBUTED applications!</p> <p class="login-box-msg">An easy and quick way to launch your DISTRIBUTED applications!</p>
<form action="" method="POST"> <form action="" method="POST" id="loginForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<input type="text" class="form-control" placeholder="Username" name="username">
<span class="glyphicon glyphicon-user form-control-feedback"></span> <span class="glyphicon glyphicon-user form-control-feedback"></span>
<input type="text" class="form-control" placeholder="Username" name="username" required>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<input type="password" class="form-control" placeholder="Password" name="password">
<span class="glyphicon glyphicon-lock form-control-feedback"></span> <span class="glyphicon glyphicon-lock form-control-feedback"></span>
<input type="password" class="form-control" placeholder="Password" name="password" required>
</div>
<div class="row">
<div class="col-xs-12">
<p style="text-align:center;font-weight:800;color:red;">{{ loginMsg }}</p>
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
@ -73,6 +79,12 @@
<script src="//cdn.bootcss.com/jquery/2.2.1/jquery.min.js"></script> <script src="//cdn.bootcss.com/jquery/2.2.1/jquery.min.js"></script>
<!-- Bootstrap 3.3.5 --> <!-- Bootstrap 3.3.5 -->
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="//cdn.bootcss.com/jquery-validate/1.17.0/jquery.validate.js"></script>
<script>
$().ready(function() {
$("#loginForm").validate();
});
</script>
</body> </body>
</html> </html>

View File

@ -69,9 +69,9 @@
{% block script_src %} {% block script_src %}
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script>
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script>
<script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script> <script src="//cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
@ -81,4 +81,3 @@
</script> </script>
{% endblock %} {% endblock %}

View File

@ -156,10 +156,9 @@
function updateAll() function updateAll()
{ {
var host = window.location.host; var host = window.location.host;
// var url0 = "http://" + host + "/monitor/hosts/";
{% for master in allmachines %} {% for master in allmachines %}
{% for phym in allmachines[master] %} {% for phym in allmachines[master] %}
url = "http://" + host + "/monitor/" + '{{master.split("@")[0]}}' + "/hosts/" + '{{phym["ip"]}}'; url = "//" + host + "/monitor/" + '{{master.split("@")[0]}}' + "/hosts/" + '{{phym["ip"]}}';
// url = url0 + '{{ phym['ip'] }}'; // url = url0 + '{{ phym['ip'] }}';
update(url,'{{master.split("@")[1]}}_{{ loop.index }}'); update(url,'{{master.split("@")[1]}}_{{ loop.index }}');
{% endfor %} {% endfor %}

View File

@ -133,10 +133,8 @@
function updateAll() function updateAll()
{ {
var host = window.location.host; var host = window.location.host;
// var url0 = "http://" + host + "/monitor/vnodes/";
{% for container in containerslist %} {% for container in containerslist %}
url = "http://" + host + "/monitor/" + '{{masterip}}' + "/vnodes/" + '{{container["Name"]}}'; url = "//" + host + "/monitor/" + '{{masterip}}' + "/vnodes/" + '{{container["Name"]}}';
//url = url0 + '{{ container['Name'] }}'; //url = url0 + '{{ container['Name'] }}';
update(url,'{{ container['Name'] }}'); update(url,'{{ container['Name'] }}');
{% endfor %} {% endfor %}
@ -144,7 +142,7 @@
var info = data.monitor.concpuinfo; var info = data.monitor.concpuinfo;
for(container in info) for(container in info)
{ {
$("#"+container+"_cpupercent").html(info[container]); $("#"+container+"_cpupercent").html(info[container]);
} }
},"json");*/ },"json");*/
} }

View File

@ -273,9 +273,9 @@
{% block script_src %} {% block script_src %}
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script>
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script>
<script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script> <script src="//cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script>
<script type='text/javascript'> <script type='text/javascript'>
function num2human(data) function num2human(data)
@ -408,15 +408,13 @@ function num2human(data)
function updateAll() function updateAll()
{ {
var host = window.location.host; var host = window.location.host;
//var url0 = "http://" + host + "/monitor/vnodes/";
{% for master in allcontainers %} {% for master in allcontainers %}
url = "http://" + host + "/monitor/" + '{{master.split("@")[0]}}' + "/user/net_stats/"; url = "//" + host + "/monitor/" + '{{master.split("@")[0]}}' + "/user/net_stats/";
update_net_stats(url,'{{master.split("@")[1]}}') update_net_stats(url,'{{master.split("@")[1]}}')
{% for clustername, clusterinfo in allcontainers[master].items() %} {% for clustername, clusterinfo in allcontainers[master].items() %}
{% for container in clusterinfo['containers'] %} {% for container in clusterinfo['containers'] %}
//url = url0 + '{{ container['containername'] }}'; //url = url0 + '{{ container['containername'] }}';
url = "http://" + host + "/monitor/" + '{{master.split("@")[0]}}' + "/vnodes/" + '{{container["containername"]}}' ; url = "//" + host + "/monitor/" + '{{master.split("@")[0]}}' + "/vnodes/" + '{{container["containername"]}}' ;
update(url,'{{master.split("@")[1]}}_{{ container['containername'] }}'); update(url,'{{master.split("@")[1]}}_{{ container['containername'] }}');
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}

View File

@ -111,6 +111,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form id="modifyNotificationForm_{{ notify['id'] }}" action="/notification/modify/" method="post"> <form id="modifyNotificationForm_{{ notify['id'] }}" action="/notification/modify/" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>Title</label> <label>Title</label>
<input type="text" class="form-control" name="title" value="{{ notify['title'] }}"> <input type="text" class="form-control" name="title" value="{{ notify['title'] }}">
@ -184,6 +185,7 @@
<div class="modal-body"> <div class="modal-body">
<strong class="text-center">Are you sure to do this?</strong> <strong class="text-center">Are you sure to do this?</strong>
<form id="deleteNotificationForm_{{ notify['id'] }}" style="display: none" action="/notification/delete/" method="post"> <form id="deleteNotificationForm_{{ notify['id'] }}" style="display: none" action="/notification/delete/" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="text" class="form-control" name="notify_id" style="display: none" value="{{ notify['id'] }}"> <input type="text" class="form-control" name="notify_id" style="display: none" value="{{ notify['id'] }}">
</form> </form>
</div> </div>

View File

@ -29,6 +29,7 @@
<div class="login-box-body"> <div class="login-box-body">
<p class="login-box-msg">An easy and quick way to launch your DISTRIBUTED applications!</p> <p class="login-box-msg">An easy and quick way to launch your DISTRIBUTED applications!</p>
<form class="m-t" role="form" action="" id="activateForm" method="POST"> <form class="m-t" role="form" action="" id="activateForm" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<input type="text" class="form-control" placeholder="username" required="" name="username"> <input type="text" class="form-control" placeholder="username" required="" name="username">
</div> </div>

View File

@ -23,6 +23,7 @@
{% block content %} {% block content %}
<div class="box-body text-center p-md"> <div class="box-body text-center p-md">
<form action="/workspace/{{masterip}}/save/{{ clustername }}/{{ containername }}/force/" method="POST"> <form action="/workspace/{{masterip}}/save/{{ clustername }}/{{ containername }}/force/" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<label>Image:</label> <label>Image:</label>
<input type="text" name="ImageName" id="ImageName" readonly="true" value="{{ image }}"/> <input type="text" name="ImageName" id="ImageName" readonly="true" value="{{ image }}"/>
<label> exists, are you sure to overwrite it?</label> <label> exists, are you sure to overwrite it?</label>

View File

@ -51,6 +51,7 @@
<div class="modal-body"> <div class="modal-body">
<form action="/group/add/" method="POST" id="addGroupForm"> <form action="/group/add/" method="POST" id="addGroupForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>Name</label> <label>Name</label>
<input type="text" placeholder="Enter Name" class="form-control" name="groupname"/> <input type="text" placeholder="Enter Name" class="form-control" name="groupname"/>
@ -87,6 +88,7 @@
<div class="modal-body"> <div class="modal-body">
<form action="/quota/add/" method="POST" id="addQuotaForm"> <form action="/quota/add/" method="POST" id="addQuotaForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>Name</label> <label>Name</label>
<input type="text" placeholder="Enter Name" class="form-control" name="quotaname"/> <input type="text" placeholder="Enter Name" class="form-control" name="quotaname"/>
@ -121,6 +123,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="/quota/chdefault/" method="POST" id="chDefaultForm"> <form action="/quota/chdefault/" method="POST" id="chDefaultForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>Default Group</label> <label>Default Group</label>
<select class="form-control" name="defaultgroup" value={{ defaultgroup }} /> <select class="form-control" name="defaultgroup" value={{ defaultgroup }} />
@ -176,6 +179,7 @@
<small class="font-bold">Modify a group in Docklet</small> <small class="font-bold">Modify a group in Docklet</small>
</div> </div>
<form action="/group/modify/{{group['name']}}/" method="POST" > <form action="/group/modify/{{group['name']}}/" method="POST" >
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label>Name</label> <label>Name</label>
@ -276,6 +280,7 @@
</div> </div>
<div class="box-body"> <div class="box-body">
<form id="chlxcsetting" class="form-horizontal" action="/quota/chlxcsetting/" method="POST"> <form id="chlxcsetting" class="form-horizontal" action="/quota/chlxcsetting/" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2">CPU</label> <label class="control-label col-sm-2">CPU</label>
<div class="col-sm-8"><input type="number" class="form-control" name="lxcCpu" id="lxcCpu" value={{lxcsetting['cpu']}} />CORE</div> <div class="col-sm-8"><input type="number" class="form-control" name="lxcCpu" id="lxcCpu" value={{lxcsetting['cpu']}} />CORE</div>
@ -305,6 +310,7 @@
</div> </div>
<div class="box-body"> <div class="box-body">
<form role="form" action="/settings/update/" method="POST" > <form role="form" action="/settings/update/" method="POST" >
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="box-body"> <div class="box-body">
<div class="form-group"> <div class="form-group">
<label for="ADMIN_EMAIL_ADDRESS">Admin Email Address</label> <label for="ADMIN_EMAIL_ADDRESS">Admin Email Address</label>
@ -415,6 +421,7 @@
<h4>Sure to set <strong> {{ parm["parm"] }} </strong>to <strong>{{ history }} </strong>?</h4> <h4>Sure to set <strong> {{ parm["parm"] }} </strong>to <strong>{{ history }} </strong>?</h4>
</div> </div>
<form action="/system/modify/" method="POST"> <form action="/system/modify/" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div style="display:none"> <div style="display:none">
<input type="text" placeholder="" class="" name="field" value={{field}} /> <input type="text" placeholder="" class="" name="field" value={{field}} />
</div> </div>
@ -473,6 +480,7 @@
<small class="font-bold">Modify a parameter in Docklet</small> <small class="font-bold">Modify a parameter in Docklet</small>
</div> </div>
<form action="/system/modify/" method="POST" > <form action="/system/modify/" method="POST" >
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div style="display:none"> <div style="display:none">
<input type="text" placeholder="" class="" name="field" value={{field}} /> <input type="text" placeholder="" class="" name="field" value={{field}} />
</div> </div>
@ -515,6 +523,7 @@
<h4>Sure to set <strong> {{ parm["parm"] }} </strong> to <strong> {{ parm["default"] }} </strong> ?</h4> <h4>Sure to set <strong> {{ parm["parm"] }} </strong> to <strong> {{ parm["default"] }} </strong> ?</h4>
</div> </div>
<form action="/system/modify/" method="POST"> <form action="/system/modify/" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div style="display:none"> <div style="display:none">
<input type="text" placeholder="" class="" name="field" value={{field}} /> <input type="text" placeholder="" class="" name="field" value={{field}} />
</div> </div>
@ -574,7 +583,7 @@
{% block script_src %} {% block script_src %}
<script src="//cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.min.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.min.js"></script>
<script src="//cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.min.js"></script> <script src="//cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.min.js"></script>
<script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script> <script src="//cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {

View File

@ -29,6 +29,7 @@
<div class="login-box-body"> <div class="login-box-body">
<p class="login-box-msg">An easy and quick way to launch your DISTRIBUTED applications!</p> <p class="login-box-msg">An easy and quick way to launch your DISTRIBUTED applications!</p>
<form class="m-t" role="form" action="" id="activateForm" method="POST"> <form class="m-t" role="form" action="" id="activateForm" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<input type="email" class="form-control" placeholder="E-mail" required="" name="email" value="{{ info['e_mail'] }}"> <input type="email" class="form-control" placeholder="E-mail" required="" name="email" value="{{ info['e_mail'] }}">
</div> </div>

View File

@ -91,6 +91,7 @@
<div class="modal-body"> <div class="modal-body">
<form action="/user/info/" method="POST" id="ChpasswordForm"> <form action="/user/info/" method="POST" id="ChpasswordForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>Old password</label> <label>Old password</label>
<input type = "password" placeholder="Enter old password" class="form-control" name="o_password" id="o_password"> <input type = "password" placeholder="Enter old password" class="form-control" name="o_password" id="o_password">

View File

@ -50,6 +50,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="/user/add/" method="POST" id="addUserForm"> <form action="/user/add/" method="POST" id="addUserForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>User Name</label> <label>User Name</label>
<input type = "text" placeholder="Enter Username" class="form-control" name="username"> <input type = "text" placeholder="Enter Username" class="form-control" name="username">
@ -100,6 +101,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="/user/modify/" method="POST" id="modifyUserForm"> <form action="/user/modify/" method="POST" id="modifyUserForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>User Name</label> <label>User Name</label>
<input type = "text" placeholder="Enter Username" class="form-control" name="username" id="mUsername" readonly="readonly"> <input type = "text" placeholder="Enter Username" class="form-control" name="username" id="mUsername" readonly="readonly">
@ -182,6 +184,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="/user/change/" method="POST" id="chpasswordForm"> <form action="/user/change/" method="POST" id="chpasswordForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-group"> <div class="form-group">
<label>User Name</label> <label>User Name</label>
<input type = "text" placeholder="Enter Username" class="form-control" name="username" id="mpUsername" readonly="readonly"> <input type = "text" placeholder="Enter Username" class="form-control" name="username" id="mpUsername" readonly="readonly">

View File

@ -21,6 +21,7 @@ initlogging("docklet-web")
from webViews.log import logger from webViews.log import logger
from flask import Flask, request, session, render_template, redirect, send_from_directory, make_response, url_for, abort from flask import Flask, request, session, render_template, redirect, send_from_directory, make_response, url_for, abort
from flask_wtf.csrf import CsrfProtect
from webViews.dashboard import dashboardView from webViews.dashboard import dashboardView
from webViews.user.userlist import userlistView, useraddView, usermodifyView, userdataView, userqueryView from webViews.user.userlist import userlistView, useraddView, usermodifyView, userdataView, userqueryView
from webViews.notification.notification import CreateNotificationView, NotificationView, QuerySelfNotificationsView, \ from webViews.notification.notification import CreateNotificationView, NotificationView, QuerySelfNotificationsView, \
@ -61,7 +62,7 @@ if (external_login == 'True'):
app = Flask(__name__) app = Flask(__name__)
CsrfProtect(app)
@app.route("/", methods=['GET']) @app.route("/", methods=['GET'])

View File

@ -47,7 +47,7 @@ class loginView(normalView):
else: else:
link = '' link = ''
url = '' url = ''
return render_template(self.template_path, link = link, url = url, open_registry=self.open_registry) return render_template(self.template_path, loginMsg="", link = link, url = url, open_registry=self.open_registry)
@classmethod @classmethod
def post(self): def post(self):
@ -70,7 +70,14 @@ class loginView(normalView):
session['token'] = result['data']['token'] session['token'] = result['data']['token']
return resp return resp
else: else:
return redirect('/login/') if (env.getenv('EXTERNAL_LOGIN') == 'True'):
url = external_generate.external_login_url
link = external_generate.external_login_link
else:
link = ''
url = ''
loginMsg = result.get('message', '')
return render_template(self.template_path, loginMsg=loginMsg, link = link, url = url, open_registry=self.open_registry)
else: else:
return redirect('/login/') return redirect('/login/')