diff --git a/.gitignore b/.gitignore
index 983fedd49..e300831e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,7 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject
+.settings
*.log
logs/*
keys/*
diff --git a/README.md b/README.md
index 448ce6711..947b4b5e9 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
+## 写在前面
+ - 目前本版本处于beta阶段,请不要用于生产环境,除非你知道你在做什么
+ - 本版本暂时没加入LDAP接口,稳定版会将LDAP和无Agent方式抽象成API,2.x版本支持LDAP,请移步release中下载
+
#欢迎使用Jumpserver
**Jumpserver** 是一款由python编写开源的跳板机(堡垒机)系统,实现了跳板机应有的功能。基于ssh协议来管理,客户端无需安装agent。
支持常见系统:
diff --git a/connect.py b/connect.py
index 37c9a126c..0be5abdfb 100755
--- a/connect.py
+++ b/connect.py
@@ -21,7 +21,7 @@ from io import open as copen
import uuid
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
-if django.get_version() != '1.6':
+if not django.get_version().startswith('1.6'):
setup = django.setup()
from django.contrib.sessions.models import Session
from jumpserver.api import ServerError, User, Asset, PermRole, AssetGroup, get_object, mkdir, get_asset_info
@@ -33,7 +33,10 @@ from jperm.ansible_api import MyRunner
from jlog.models import ExecLog, FileLog
login_user = get_object(User, username=getpass.getuser())
-remote_ip = os.popen("who -m | awk '{ print $NF }'").read().strip('()\n')
+try:
+ remote_ip = os.environ.get('SSH_CLIENT').split()[0]
+except (IndexError, AttributeError):
+ remote_ip = os.popen("who -m | awk '{ print $NF }'").read().strip('()\n')
try:
import termios
@@ -412,7 +415,10 @@ class SshTty(Tty):
pass
if sys.stdin in r:
- x = os.read(sys.stdin.fileno(), 4096)
+ try:
+ x = os.read(sys.stdin.fileno(), 4096)
+ except OSError:
+ pass
input_mode = True
if str(x) in ['\r', '\n', '\r\n']:
if self.vim_flag:
@@ -576,12 +582,15 @@ class Nav(object):
role = role_check[int(role_id)]
elif len(roles) == 1: # 授权角色数为1
role = roles[0]
+ else:
+ color_print('当前用户未被授予角色,无法执行任何操作,如有疑问请联系管理员。')
+ return
assets = list(self.user_perm.get('role', {}).get(role).get('asset')) # 获取该用户,角色授权主机
print "授权包含该系统用户的所有主机"
for asset in assets:
print ' %s' % asset.hostname
print
- print "请输入主机名或ansile支持的pattern, 多个主机:分隔, q退出"
+ print "请输入主机名或ansible支持的pattern, 多个主机:分隔, q退出"
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
if pattern == 'q':
break
@@ -623,7 +632,7 @@ class Nav(object):
self.user_perm = get_group_user_perm(self.user)
try:
print "进入批量上传模式"
- print "请输入主机名或ansile支持的pattern, 多个主机:分隔 q退出"
+ print "请输入主机名或ansible支持的pattern, 多个主机:分隔 q退出"
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
if pattern == 'q':
break
@@ -676,7 +685,7 @@ class Nav(object):
self.user_perm = get_group_user_perm(self.user)
try:
print "进入批量下载模式"
- print "请输入主机名或ansile支持的pattern, 多个主机:分隔,q退出"
+ print "请输入主机名或ansible支持的pattern, 多个主机:分隔,q退出"
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
if pattern == 'q':
break
@@ -800,7 +809,7 @@ def main():
color_print('请输入正确ID', 'red')
except ServerError, e:
color_print(e, 'red')
- except Exception, e:
+ except IndexError, e:
color_print(e)
time.sleep(5)
pass
diff --git a/install/install.py b/install/install.py
index 5552d3c20..c5765ff12 100755
--- a/install/install.py
+++ b/install/install.py
@@ -12,6 +12,8 @@ import socket
import fcntl
import struct
import readline
+import random
+import string
jms_dir = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
sys.path.append(jms_dir)
@@ -71,12 +73,15 @@ class PreSetup(object):
self.mail_addr = 'hello@jumpserver.org'
self.mail_pass = ''
self.ip = ''
+ self.key = ''.join(random.choice(string.ascii_lowercase + string.digits) \
+ for _ in range(16))
def write_conf(self, conf_file=os.path.join(jms_dir, 'jumpserver.conf')):
color_print('开始写入配置文件', 'green')
conf = ConfigParser.ConfigParser()
conf.read(conf_file)
conf.set('base', 'url', 'http://%s' % self.ip)
+ conf.set('base', 'key', self.key)
conf.set('db', 'host', self.db_host)
conf.set('db', 'port', self.db_port)
conf.set('db', 'user', self.db_user)
@@ -96,6 +101,7 @@ class PreSetup(object):
color_print('默认用户名: %s 默认密码: %s' % (self.db_user, self.db_pass), 'green')
bash('yum -y install mysql-server')
bash('service mysqld start')
+ bash('chkconfig mysqld on')
bash('mysql -e "create database %s default charset=utf8"' % self.db)
bash('mysql -e "grant all on %s.* to \'%s\'@\'%s\' identified by \'%s\'"' % (self.db,
self.db_user,
@@ -105,6 +111,7 @@ class PreSetup(object):
@staticmethod
def _set_env():
color_print('开始关闭防火墙和selinux', 'green')
+ os.system("export LANG='en_US.UTF-8' && sed -i 's/LANG=.*/LANG=en_US.UTF-8/g' /etc/sysconfig/i18n")
bash('service iptables stop && chkconfig iptables off && setenforce 0')
def _test_db_conn(self):
diff --git a/install/next.py b/install/next.py
index a68eb66bc..e3dc312fa 100755
--- a/install/next.py
+++ b/install/next.py
@@ -18,7 +18,7 @@ if django.get_version() != '1.6':
from juser.user_api import db_add_user, get_object, User
from install import color_print
-from jumpserver.api import get_mac_address
+from jumpserver.api import get_mac_address, bash
socket.setdefaulttimeout(2)
@@ -81,9 +81,10 @@ class Setup(object):
os.system('id %s &> /dev/null || useradd %s' % (self.admin_user, self.admin_user))
@staticmethod
- def _ensure_sh():
- jshell = os.path.join(jms_dir, 'connect.py')
- os.chmod(jshell, 0755)
+ def _cp_zzsh():
+ os.chdir(os.path.join(jms_dir, 'install'))
+ shutil.copy('zzjumpserver.sh', '/etc/profile.d/')
+ bash("sed -i 's#/opt/jumpserver#%s#g' /etc/profile.d/zzjumpserver.sh" % jms_dir)
@staticmethod
def _run_service():
@@ -97,7 +98,7 @@ class Setup(object):
self._sync_db()
self._input_admin()
self._create_admin()
- self._ensure_sh()
+ self._cp_zzsh()
self._run_service()
diff --git a/install/zzjumpserver.sh b/install/zzjumpserver.sh
new file mode 100644
index 000000000..516b0466e
--- /dev/null
+++ b/install/zzjumpserver.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+export LANG='zh_CN.UTF-8'
+
+if [ "$USER" != "admin" ] && [ "$USER" != "root" ];then
+ python /opt/jumpserver/connect.py
+ if [ $USER == 'guanghongwei' ];then
+ echo
+ else
+ exit 3
+ echo
+ fi
+fi
diff --git a/jasset/asset_api.py b/jasset/asset_api.py
index ca733cad0..7cc49fa66 100644
--- a/jasset/asset_api.py
+++ b/jasset/asset_api.py
@@ -311,13 +311,12 @@ def excel_to_db(excel_file):
def get_ansible_asset_info(asset_ip, setup_info):
- print asset_ip
+ print setup_info, '***'
disk_need = {}
disk_all = setup_info.get("ansible_devices")
if disk_all:
for disk_name, disk_info in disk_all.iteritems():
- print disk_name, disk_info
- if disk_name.startswith('sd') or disk_name.startswith('hd') or disk_name.startswith('vd'):
+ if disk_name.startswith('sd') or disk_name.startswith('hd') or disk_name.startswith('vd') or disk_name.startswith('xvd'):
disk_size = disk_info.get("size", '')
if 'M' in disk_size:
disk_format = round(float(disk_size[:-2]) / 1000, 0)
@@ -334,7 +333,7 @@ def get_ansible_asset_info(asset_ip, setup_info):
mac = setup_info.get("ansible_default_ipv4").get("macaddress")
brand = setup_info.get("ansible_product_name")
cpu_type = setup_info.get("ansible_processor")[1]
- cpu_cores = setup_info.get("ansible_processor_count")
+ cpu_cores = setup_info.get("ansible_processor_vcpus")
cpu = cpu_type + ' * ' + unicode(cpu_cores)
memory = setup_info.get("ansible_memtotal_mb")
try:
diff --git a/jasset/models.py b/jasset/models.py
index 2851b7d56..82c5f54a6 100644
--- a/jasset/models.py
+++ b/jasset/models.py
@@ -75,7 +75,7 @@ class Asset(models.Model):
brand = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'硬件厂商型号')
cpu = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'CPU')
memory = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'内存')
- disk = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'硬盘')
+ disk = models.CharField(max_length=1024, blank=True, null=True, verbose_name=u'硬盘')
system_type = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"系统类型")
system_version = models.CharField(max_length=8, blank=True, null=True, verbose_name=u"系统版本号")
system_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=u"系统平台")
diff --git a/jasset/views.py b/jasset/views.py
index aabe0665d..779306580 100644
--- a/jasset/views.py
+++ b/jasset/views.py
@@ -227,7 +227,7 @@ def asset_edit(request):
if use_default_auth:
af_save.username = ''
af_save.password = ''
- af_save.port = None
+ # af_save.port = None
else:
if password:
password_encode = CRYPTOR.encrypt(password)
diff --git a/jlog/log_api.py b/jlog/log_api.py
index b10325643..6f2d6edbe 100644
--- a/jlog/log_api.py
+++ b/jlog/log_api.py
@@ -6,7 +6,10 @@ from contextlib import closing
from io import open as copen
from json import dumps
from math import ceil
+import datetime
+import time
import re
+import os
from os.path import basename, dirname, exists, join
from struct import unpack
from subprocess import Popen
@@ -17,6 +20,7 @@ from jinja2 import FileSystemLoader, Template
from jinja2.environment import Environment
from jumpserver.api import BASE_DIR
+from jlog.models import Log
DEFAULT_TEMPLATE = join(BASE_DIR, 'templates', 'jlog', 'static.jinja2')
@@ -75,3 +79,28 @@ def renderTemplate(script_path, time_file_path, dimensions=(24, 80), templatenam
return rendered
+def kill_invalid_connection():
+ long_time_logs = []
+ unfinished_logs = Log.objects.filter(is_finished=False)
+ now = datetime.datetime.now()
+ now_timestamp = int(time.mktime(now.timetuple()))
+ for log in unfinished_logs:
+ if (now - log.start_time).days > 1:
+ long_time_logs.append(log)
+
+ for log in long_time_logs:
+ try:
+ log_file_mtime = int(os.stat(log.log_path).st_mtime)
+ except OSError:
+ log_file_mtime = 0
+
+ if (now_timestamp - log_file_mtime) > 3600:
+ try:
+ os.kill(int(log.pid), 9)
+ except OSError:
+ pass
+
+ log.is_finished = True
+ log.end_time = now
+ log.save()
+
diff --git a/jlog/views.py b/jlog/views.py
index ff0eaf1c0..e2565250e 100644
--- a/jlog/views.py
+++ b/jlog/views.py
@@ -66,7 +66,7 @@ def log_list(request, offset):
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
- web_monitor_uri = 'ws://%s/monitor' % WEB_SOCKET_HOST
+ web_monitor_uri = '%s/monitor' % WEB_SOCKET_HOST
web_kill_uri = 'http://%s/kill' % WEB_SOCKET_HOST
session_id = request.session.session_key
return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request))
diff --git a/jperm/ansible_api.py b/jperm/ansible_api.py
index 953271917..20725908c 100644
--- a/jperm/ansible_api.py
+++ b/jperm/ansible_api.py
@@ -365,6 +365,16 @@ class MyTask(MyRunner):
self.run("user", module_args, become=True)
return self.results
+ def del_user_sudo(self, username):
+ """
+ delete a role sudo item
+ :param username:
+ :return:
+ """
+ module_args = "sed -i 's/^%s.*//' /etc/sudoers" % username
+ self.run("command", module_args, become=True)
+ return self.results
+
@staticmethod
def gen_sudo_script(role_list, sudo_list):
# receive role_list = [role1, role2] sudo_list = [sudo1, sudo2]
diff --git a/jperm/views.py b/jperm/views.py
index db05783bd..a8a66128b 100644
--- a/jperm/views.py
+++ b/jperm/views.py
@@ -16,8 +16,8 @@ from jperm.perm_api import get_role_info, get_role_push_host
from jumpserver.api import my_render, get_object, CRYPTOR
# 设置PERM APP Log
-from jumpserver.settings import LOG_LEVEL
-logger = set_log(LOG_LEVEL, filename='jumpserver_perm.log')
+from jumpserver.api import logger
+#logger = set_log(LOG_LEVEL, filename='jumpserver_perm.log')
@require_role('admin')
@@ -277,7 +277,7 @@ def perm_role_add(request):
if request.method == "POST":
# 获取参数: name, comment
- name = request.POST.get("role_name", "")
+ name = request.POST.get("role_name", "").strip()
comment = request.POST.get("role_comment", "")
password = request.POST.get("role_password", "")
key_content = request.POST.get("role_key", "")
@@ -286,6 +286,8 @@ def perm_role_add(request):
try:
if get_object(PermRole, name=name):
raise ServerError(u'已经存在该用户 %s' % name)
+ if name == "root":
+ raise ServerError(u'禁止使用root用户作为系统用户,这样非常危险!')
default = get_object(Setting, name='default')
if password:
@@ -317,14 +319,37 @@ def perm_role_delete(request):
"""
delete role page
"""
+ if request.method == "GET":
+ try:
+ # 获取参数删除的role对象
+ role_id = request.GET.get("id")
+ role = get_object(PermRole, id=role_id)
+ if not role:
+ logger.warning(u"Delete Role: role_id %s not exist" % role_id)
+ raise ServerError(u"role_id %s 无数据记录" % role_id)
+ # 删除推送到主机上的role
+ filter_type = request.GET.get("filter_type")
+ print filter_type
+ if filter_type:
+ if filter_type == "recycle_assets":
+ recycle_assets = [push.asset for push in role.perm_push.all() if push.success]
+ print recycle_assets
+ recycle_assets_ip = ','.join([asset.ip for asset in recycle_assets])
+ return HttpResponse(recycle_assets_ip)
+ else:
+ return HttpResponse("no such filter_type: %s" % filter_type)
+ else:
+ return HttpResponse("filter_type: ?")
+ except ServerError, e:
+ return HttpResponse(e)
if request.method == "POST":
try:
# 获取参数删除的role对象
role_id = request.POST.get("id")
role = get_object(PermRole, id=role_id)
if not role:
- logger.warning(u"Delete Role: %s not exist" % role.name)
- raise ServerError(u"%s 无数据记录" % role.name)
+ logger.warning(u"Delete Role: role_id %s not exist" % role_id)
+ raise ServerError(u"role_id %s 无数据记录" % role_id)
role_key = role.key_path
# 删除推送到主机上的role
recycle_assets = [push.asset for push in role.perm_push.all() if push.success]
@@ -333,11 +358,13 @@ def perm_role_delete(request):
recycle_resource = gen_resource(recycle_assets)
task = MyTask(recycle_resource)
try:
- msg = task.del_user(get_object(PermRole, id=role_id).name)
+ msg_del_user = task.del_user(get_object(PermRole, id=role_id).name)
+ msg_del_sudo = task.del_user_sudo(get_object(PermRole, id=role_id).name)
except Exception, e:
logger.warning(u"Recycle Role failed: %s" % e)
raise ServerError(u"回收已推送的系统用户失败: %s" % e)
- logger.info(u"delete role %s - execute delete user: %s" % (role.name, msg))
+ logger.info(u"delete role %s - execute delete user: %s" % (role.name, msg_del_user))
+ logger.info(u"delete role %s - execute delete sudo: %s" % (role.name, msg_del_sudo))
# TODO: 判断返回结果,处理异常
# 删除存储的秘钥,以及目录
try:
@@ -423,6 +450,9 @@ def perm_role_edit(request):
if not role:
raise ServerError('该系统用户不能存在')
+ if role_name == "root":
+ raise ServerError(u'禁止使用root用户作为系统用户,这样非常危险!')
+
if role_password:
encrypt_pass = CRYPTOR.encrypt(role_password)
role.password = encrypt_pass
@@ -473,6 +503,7 @@ def perm_role_push(request):
for asset_group in asset_groups_obj:
group_assets_obj.extend(asset_group.asset_set.all())
calc_assets = list(set(assets_obj) | set(group_assets_obj))
+
push_resource = gen_resource(calc_assets)
# 调用Ansible API 进行推送
@@ -577,25 +608,28 @@ def perm_sudo_add(request):
"""
# 渲染数据
header_title, path1, path2 = "Sudo命令", "别名管理", "添加别名"
+ try:
+ if request.method == "POST":
+ # 获取参数: name, comment
+ name = request.POST.get("sudo_name").strip().upper()
+ comment = request.POST.get("sudo_comment").strip()
+ commands = request.POST.get("sudo_commands").strip()
- if request.method == "POST":
- # 获取参数: name, comment
- name = request.POST.get("sudo_name").strip().upper()
- comment = request.POST.get("sudo_comment").strip()
- commands = request.POST.get("sudo_commands").strip()
+ if not name or not commands:
+ raise ServerError(u"sudo name 和 commands是必填项!")
- pattern = re.compile(r'[ \n,\r]')
- commands = ', '.join(list_drop_str(pattern.split(commands), u''))
- logger.debug(u'添加sudo %s: %s' % (name, commands))
-
- if get_object(PermSudo, name=name):
- error = 'Sudo别名 %s已经存在' % name
- else:
- sudo = PermSudo(name=name.strip(), comment=comment, commands=commands)
- sudo.save()
- msg = u"添加Sudo命令别名: %s" % name
- # 渲染数据
+ pattern = re.compile(r'[\n,\r]')
+ commands = ', '.join(list_drop_str(pattern.split(commands), u''))
+ logger.debug(u'添加sudo %s: %s' % (name, commands))
+ if get_object(PermSudo, name=name):
+ error = 'Sudo别名 %s已经存在' % name
+ else:
+ sudo = PermSudo(name=name.strip(), comment=comment, commands=commands)
+ sudo.save()
+ msg = u"添加Sudo命令别名: %s" % name
+ except ServerError, e:
+ error = e
return my_render('jperm/perm_sudo_add.html', locals(), request)
@@ -612,22 +646,27 @@ def perm_sudo_edit(request):
sudo_id = request.GET.get("id")
sudo = PermSudo.objects.get(id=sudo_id)
- if request.method == "POST":
- name = request.POST.get("sudo_name").upper()
- commands = request.POST.get("sudo_commands")
- comment = request.POST.get("sudo_comment")
+ try:
+ if request.method == "POST":
+ name = request.POST.get("sudo_name").upper()
+ commands = request.POST.get("sudo_commands")
+ comment = request.POST.get("sudo_comment")
- pattern = re.compile(r'[ \n,\r]')
- commands = ', '.join(list_drop_str(pattern.split(commands), u'')).strip()
- logger.debug(u'添加sudo %s: %s' % (name, commands))
+ if not name or not commands:
+ raise ServerError(u"sudo name 和 commands是必填项!")
- sudo.name = name.strip()
- sudo.commands = commands
- sudo.comment = comment
- sudo.save()
+ pattern = re.compile(r'[\n,\r]')
+ commands = ', '.join(list_drop_str(pattern.split(commands), u'')).strip()
+ logger.debug(u'添加sudo %s: %s' % (name, commands))
- msg = u"更新命令别名: %s" % name
+ sudo.name = name.strip()
+ sudo.commands = commands
+ sudo.comment = comment
+ sudo.save()
+ msg = u"更新命令别名: %s" % name
+ except ServerError, e:
+ error = e
return my_render('jperm/perm_sudo_edit.html', locals(), request)
diff --git a/jumpserver/api.py b/jumpserver/api.py
index 68a013870..691aafb11 100644
--- a/jumpserver/api.py
+++ b/jumpserver/api.py
@@ -64,7 +64,6 @@ def get_asset_info(asset):
info = {'hostname': asset.hostname, 'ip': asset.ip}
if asset.use_default_auth:
if default:
- info['port'] = int(default.field2)
info['username'] = default.field1
try:
info['password'] = CRYPTOR.decrypt(default.field3)
@@ -73,9 +72,12 @@ def get_asset_info(asset):
if os.path.isfile(default.field4):
info['ssh_key'] = default.field4
else:
- info['port'] = int(asset.port)
info['username'] = asset.username
info['password'] = CRYPTOR.decrypt(asset.password)
+ try:
+ info['port'] = int(asset.port)
+ except TypeError:
+ info['port'] = int(default.field2)
return info
diff --git a/jumpserver/settings.py b/jumpserver/settings.py
index fa8431272..d1c8a8f40 100644
--- a/jumpserver/settings.py
+++ b/jumpserver/settings.py
@@ -152,5 +152,6 @@ STATIC_URL = '/static/'
BOOTSTRAP_COLUMN_COUNT = 10
CRONJOBS = [
- ('0 1 * * *', 'jasset.asset_api.asset_ansible_update_all')
+ ('0 1 * * *', 'jasset.asset_api.asset_ansible_update_all'),
+ ('1 * * * *', 'jlog.log_api.kill_invalid_connection'),
]
diff --git a/jumpserver/views.py b/jumpserver/views.py
index 766ae021f..afe5ddd38 100644
--- a/jumpserver/views.py
+++ b/jumpserver/views.py
@@ -344,7 +344,7 @@ def download(request):
def exec_cmd(request):
role = request.GET.get('role')
check_assets = request.GET.get('check_assets', '')
- web_terminal_uri = 'ws://%s/exec?role=%s' % (WEB_SOCKET_HOST, role)
+ web_terminal_uri = '%s/exec?role=%s' % (WEB_SOCKET_HOST, role)
return my_render('exec_cmd.html', locals(), request)
@@ -356,7 +356,7 @@ def web_terminal(request):
if asset:
print asset
hostname = asset.hostname
- web_terminal_uri = 'ws://%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name)
+ web_terminal_uri = '%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name)
return render_to_response('jlog/web_terminal.html', locals())
diff --git a/juser/user_api.py b/juser/user_api.py
index 2c16c3dc7..a6fc7648a 100644
--- a/juser/user_api.py
+++ b/juser/user_api.py
@@ -151,8 +151,8 @@ def server_add_user(username, password, ssh_key_pwd='', ssh_key_login_need=True)
add a system user in jumpserver
在jumpserver服务器上添加一个用户
"""
- bash("useradd -s %s/connect.py '%s'; echo '%s'; echo '%s' | passwd --stdin '%s'" %
- (BASE_DIR, username, password, password, username))
+ bash("useradd '%s'; echo '%s'; echo '%s:%s' | chpasswd " %
+ (username, password, username, password))
if ssh_key_login_need:
gen_ssh_key(username, ssh_key_pwd)
diff --git a/juser/views.py b/juser/views.py
index ed2c11f2a..41baa7536 100644
--- a/juser/views.py
+++ b/juser/views.py
@@ -6,7 +6,7 @@
# from Crypto.PublicKey import RSA
import uuid
from django.contrib.auth.decorators import login_required
-
+from django.shortcuts import get_object_or_404
from django.db.models import Q
from juser.user_api import *
from jperm.perm_api import get_group_user_perm
@@ -111,22 +111,18 @@ def group_edit(request):
if len(UserGroup.objects.filter(name=group_name)) > 1:
raise ServerError(u'%s 用户组已存在' % group_name)
# add user group
+ user_group = get_object_or_404(UserGroup, id=group_id)
+ user_group.user_set.clear()
+
for user in User.objects.filter(id__in=users_selected):
user.group.add(UserGroup.objects.get(id=group_id))
- # delete user group
- user_group = UserGroup.objects.get(id=group_id)
- for user in [user for user in User.objects.filter(group=user_group) if user not in User.objects.filter(id__in=users_selected)]:
- user_group_all = user.group.all()
- user.group.clear()
- for g in user_group_all:
- if g == user_group:
- continue
- user.group.add(g)
+
user_group.name = group_name
user_group.comment = comment
user_group.save()
except ServerError, e:
error = e
+
if not error:
return HttpResponseRedirect(reverse('user_group_list'))
else:
@@ -313,6 +309,12 @@ def reset_password(request):
hash_encode = request.GET.get('hash', '')
action = '/juser/password/reset/?uuid=%s×tamp=%s&hash=%s' % (uuid_r, timestamp, hash_encode)
+ if hash_encode == PyCrypt.md5_crypt(uuid_r + timestamp + KEY):
+ if int(time.time()) - int(timestamp) > 600:
+ return http_error(request, u'链接已超时')
+ else:
+ return HttpResponse('hash校验失败')
+
if request.method == 'POST':
password = request.POST.get('password')
password_confirm = request.POST.get('password_confirm')
@@ -328,11 +330,8 @@ def reset_password(request):
else:
return HttpResponse('用户不存在')
- if hash_encode == PyCrypt.md5_crypt(uuid_r + timestamp + KEY):
- if int(time.time()) - int(timestamp) > 600:
- return http_error(request, u'链接已超时')
- else:
- return render_to_response('juser/reset_password.html', locals())
+ else:
+ return render_to_response('juser/reset_password.html', locals())
return http_error(request, u'错误请求')
diff --git a/run_websocket.py b/run_websocket.py
index 4a1a185dc..ec6b2f73f 100755
--- a/run_websocket.py
+++ b/run_websocket.py
@@ -230,15 +230,14 @@ class ExecHandler(tornado.websocket.WebSocketHandler):
def on_message(self, message):
data = json.loads(message)
pattern = data.get('pattern', '')
- command = data.get('command', '')
- asset_name_str = ''
- if pattern and command:
+ self.command = data.get('command', '')
+ self.asset_name_str = ''
+ if pattern and self.command:
for inv in self.runner.inventory.get_hosts(pattern=pattern):
- asset_name_str += '%s ' % inv.name
- self.write_message('匹配主机: ' + asset_name_str)
- self.write_message('Ansible> %s\n\n' % command)
- self.__class__.tasks.append(MyThread(target=self.run_cmd, args=(command, pattern)))
- ExecLog(host=asset_name_str, cmd=command, user=self.user.username, remote_ip=self.remote_ip).save()
+ self.asset_name_str += '%s ' % inv.name
+ self.write_message('匹配主机: ' + self.asset_name_str)
+ self.write_message('Ansible> %s\n\n' % self.command)
+ self.__class__.tasks.append(MyThread(target=self.run_cmd, args=(self.command, pattern)))
for t in self.__class__.tasks:
if t.is_alive():
@@ -251,11 +250,12 @@ class ExecHandler(tornado.websocket.WebSocketHandler):
def run_cmd(self, command, pattern):
self.runner.run('shell', command, pattern=pattern)
+ ExecLog(host=self.asset_name_str, cmd=self.command, user=self.user.username,
+ remote_ip=self.remote_ip, result=self.runner.results).save()
newline_pattern = re.compile(r'\n')
for k, v in self.runner.results.items():
for host, output in v.items():
output = newline_pattern.sub('
', output)
- logger.debug(output)
if k == 'ok':
header = "[ %s => %s]\n" % (host, 'Ok')
else:
diff --git a/templates/exec_cmd.html b/templates/exec_cmd.html
index 754105cee..d1eda2fcb 100644
--- a/templates/exec_cmd.html
+++ b/templates/exec_cmd.html
@@ -23,7 +23,13 @@
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/templates/jasset/asset_list.html b/templates/jasset/asset_list.html
index 1da808c3c..b87b6e177 100644
--- a/templates/jasset/asset_list.html
+++ b/templates/jasset/asset_list.html
@@ -243,8 +243,9 @@
area: ['628px', '420px'],
content: new_url+data
});
+ window.open(new_url+data, '_blank', 'toolbar=yes, location=yes, scrollbars=yes, resizable=yes, copyhistory=yes, width=628, height=400')
*/
- window.open(new_url+data, '', 'width=628px, height=420px')
+ window.open(new_url+data, '', 'width=628px, height=380px');
} else if (dataArray.length == 1 && data != 'error'){
/*layer.open({
type: 2,
@@ -255,7 +256,7 @@
content: new_url+data
});
*/
- window.open(new_url+data, '', 'width=628px, height=440px')
+ window.open(new_url+data, '_blank', 'toolbar=yes, location=yes, copyhistory=yes, scrollbars=yes, width=628, height=410');
}
else {
@@ -292,7 +293,7 @@
content: new_url
});
*/
- window.open(new_url, '', 'height=628px, width=420px')
+ window.open(new_url, '_blank', 'toolbar=yes, location=yes, copyhistory=yes, scrollbars=yes, width=628, height=400')
} else {
/*
@@ -305,7 +306,7 @@
content: new_url
});
*/
- window.open(new_url, '', 'height=628px, width=452px')
+ window.open(new_url, '_blank', 'toolbar=yes, location=yes, copyhistory=yes, scrollbars=yes, width=628, height=410');
}
return false
@@ -429,4 +430,4 @@
});
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/templates/jlog/log_online.html b/templates/jlog/log_online.html
index 14e55f957..f82969156 100644
--- a/templates/jlog/log_online.html
+++ b/templates/jlog/log_online.html
@@ -136,14 +136,20 @@
{# })#}
{# });#}
function init(obj){
+ var protocol = "ws://";
+ if (window.location.protocol == 'https:') {
+ protocol = 'wss://';
+ }
+
var file_path = obj.attr('file_path');
- var wsUri = '{{ web_monitor_uri }}';
+ var wsUri = protocol + '{{ web_monitor_uri }}';
var socket = new WebSocket(wsUri + '?file_path=' + file_path);
var term = new Terminal({
- cols: 80,
- rows: 24,
- screenKeys: false
+ cols: 80,
+ rows: 24,
+ screenKeys: false,
+ handler: function(){return false}
});
var tag = $('