Merge pull request #364 from FirmlyReality/master

Web Security Upgrade
This commit is contained in:
Yujian Zhu 2018-12-22 15:55:29 +08:00 committed by GitHub
commit 5b27d625c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 166 additions and 81 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
apt-get install -y gdebi-core apt-get install -y gdebi-core
gdebi ossfs_1.80.5_ubuntu16.04_amd64.deb gdebi ossfs_1.80.5_ubuntu16.04_amd64.deb
pip3 install grpcio grpcio-tools googleapis-common-protos pip3 install grpcio grpcio-tools googleapis-common-protos

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

@ -6,6 +6,7 @@ from utils import env, imagemgr
from utils.lvmtool import sys_run, check_volume from utils.lvmtool import sys_run, check_volume
from worker.monitor import Container_Collector, History_Manager from worker.monitor import Container_Collector, History_Manager
import lxc import lxc
from utils import model
class Container(object): class Container(object):
def __init__(self, addr, etcdclient): def __init__(self, addr, etcdclient):
@ -320,17 +321,11 @@ IP=%s
# list containers in FS_PREFIX/global/... on this host as global # list containers in FS_PREFIX/global/... on this host as global
def diff_containers(self): def diff_containers(self):
[status, localcontainers] = self.list_containers() [status, localcontainers] = self.list_containers()
globalpath = self.fspath+"/global/users/" containers = model.Container.query.all()
users = os.listdir(globalpath)
globalcontainers = [] globalcontainers = []
for user in users: for con in containers:
clusters = os.listdir(globalpath+user+"/clusters") if con.host == self.addr:
for cluster in clusters: globalcontainers.append(con.containername)
clusterfile = open(globalpath+user+"/clusters/"+cluster, 'r')
clusterinfo = json.loads(clusterfile.read())
for container in clusterinfo['containers']:
if container['host'] == self.addr:
globalcontainers.append(container['containername'])
both = [] both = []
onlylocal = [] onlylocal = []
onlyglobal = [] onlyglobal = []

View File

@ -23,7 +23,7 @@ sed -i "s/%NGINX_PORT/${NGINX_PORT}/g" ${NGINX_CONF}/nginx_docklet.conf
sed -i "s/%PROXY_PORT/${PROXY_PORT}/g" ${NGINX_CONF}/nginx_docklet.conf sed -i "s/%PROXY_PORT/${PROXY_PORT}/g" ${NGINX_CONF}/nginx_docklet.conf
sed -i "s/%WEB_PORT/${WEB_PORT}/g" ${NGINX_CONF}/nginx_docklet.conf sed -i "s/%WEB_PORT/${WEB_PORT}/g" ${NGINX_CONF}/nginx_docklet.conf
if [ "${NGINX_PORT}" != "80" ] if [ "${NGINX_PORT}" != "80" ] && [ "${NGINX_PORT}" != "443" ]
then then
sed -i "s/\$host/\$host:\$server_port/g" ${NGINX_CONF}/nginx_docklet.conf sed -i "s/\$host/\$host:\$server_port/g" ${NGINX_CONF}/nginx_docklet.conf
fi fi

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']})

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)
{ {
@ -277,7 +277,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

@ -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>
@ -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">
@ -293,6 +294,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 %}

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, \
@ -62,7 +63,7 @@ if (external_login == 'True'):
app = Flask(__name__) app = Flask(__name__)
CsrfProtect(app)
@app.route("/", methods=['GET']) @app.route("/", methods=['GET'])
@ -776,4 +777,4 @@ if __name__ == '__main__':
elif opt in ("-p", "--port"): elif opt in ("-p", "--port"):
webport = int(arg) webport = int(arg)
app.run(host = webip, port = webport, debug = True, threaded=True) app.run(host = webip, port = webport, threaded=True)

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/')