Merge branch 'dev' of https://git.coding.net/jumpserver/jumpserver into NormalUserPageLZ

pull/26/head
liuzheng712 2015-11-20 11:12:10 +08:00
commit 31807b674b
37 changed files with 446 additions and 324 deletions

1
.gitignore vendored
View File

@ -37,6 +37,7 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject
*.log
logs/*
keys/*
jumpserver.conf

View File

@ -19,8 +19,8 @@ import struct, fcntl, signal, socket, select
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
if django.get_version() != '1.6':
django.setup()
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object
from jumpserver.api import logger, mkdir, Log, TtyLog
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir
from jumpserver.api import logger, Log, TtyLog
from jumpserver.settings import LOG_DIR
@ -68,9 +68,6 @@ def check_vim_status(command, ssh):
return False
class Tty(object):
"""
A virtual tty class
@ -252,6 +249,7 @@ class Tty(object):
log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.asset_name, time_start))
try:
mkdir(os.path.dirname(today_connect_log_dir), mode=0777)
mkdir(today_connect_log_dir, mode=0777)
except OSError:
logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir))
@ -289,7 +287,7 @@ class Tty(object):
# 2. get 映射用户
# 3. get 映射用户的账号密码或者key
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''}
self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': '', 'role_key': '/root/.ssh/id_rsa.bak'}
self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': 'redhat', 'role_key': ''}
return self.connect_info
def get_connection(self):
@ -452,7 +450,7 @@ class SshTty(Tty):
#print 'ok'+tmp+'ok'
# SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
# SSH_TTY = ''
channel.send('clear\n')
# channel.send('clear\n')
# Make ssh interactive tunnel
self.posix_shell()
@ -468,20 +466,83 @@ class SshTty(Tty):
pass
def print_prompt():
"""
Print prompt
打印提示导航
"""
msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m
1) Type \033[32mIP or Part IP, Host Alias or Comments \033[0m To Login.
2) Type \033[32mP/p\033[0m To Print The Servers You Available.
3) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
4) Type \033[32mG/g(1-N)\033[0m To Print The Server Group Hosts You Available.
5) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
6) Type \033[32mQ/q\033[0m To Quit.
"""
print textwrap.dedent(msg)
def print_user_asset_group_info(user):
asset_groups = AssetGroup.objects.all()
for asset_group in asset_groups:
if asset_group.comment:
print '[%-2s] %-10s %s' % (asset_group.id, asset_group.name, asset_group.comment)
else:
print '[%-2s] %-10s' % (asset_group.id, asset_group.name)
print
class Nav(object):
def __init__(self, user):
self.user = user
self.search_result = {}
@staticmethod
def print_nav():
"""
Print prompt
打印提示导航
"""
msg = """\n\033[1;32m### Welcome To Use JumpServer, A Open Source System . ### \033[0m
1) Type \033[32mID\033[0m To Login.
2) Type \033[32m/\033[0m + \033[32mIP, Host Name, Host Alias or Comments \033[0mTo Search.
3) Type \033[32mP/p\033[0m To Print The Servers You Available.
4) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
5) Type \033[32mG/g\033[0m\033[0m + \033[32mGroup ID\033[0m To Print The Server Group You Available.
6) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
7) Type \033[32mQ/q\033[0m To Quit.
"""
msg = """\n\033[1;32m### 欢迎使用Jumpserver开源跳板机 ### \033[0m
1) 输入 \033[32mID\033[0m 直接登录.
2) 输入 \033[32m/\033[0m + \033[32mIP, 主机名, 主机别名 or 备注 \033[0m搜索.
3) 输入 \033[32mP/p\033[0m 显示您有权限的主机.
4) 输入 \033[32mG/g\033[0m 显示您有权限的主机组.
5) 输入 \033[32mG/g\033[0m\033[0m + \033[32m组ID\033[0m 显示该组下主机.
6) 输入 \033[32mE/e\033[0m 批量执行命令.
7) 输入 \033[32mQ/q\033[0m 退出.
"""
print textwrap.dedent(msg)
def search(self, str_r=''):
gid_pattern = re.compile(r'^g\d+$')
user_asset_all = list(Asset.objects.all())
user_asset_search = []
if str_r:
if gid_pattern.match(str_r):
user_asset_search = list(Asset.objects.all())
else:
for asset in user_asset_all:
if str_r in asset.ip or str_r in str(asset.comment):
user_asset_search.append(asset)
else:
user_asset_search = user_asset_all
self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search))
print '\033[32m[%-3s] %-15s %-15s %-5s %-5s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
for index, asset in self.search_result.items():
if asset.comment:
print '[%-3s] %-15s %-15s %-5s %-5s %s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role', asset.comment)
else:
print '[%-3s] %-15s %-15s %-5s %-5s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role')
print
@staticmethod
def print_asset_group():
user_asset_group_all = AssetGroup.objects.all()
print '\033[32m[%-3s] %-15s %s \033[0m' % ('ID', 'GroupName', 'Comment')
for asset_group in user_asset_group_all:
if asset_group.comment:
print '[%-3s] %-15s %s' % (asset_group.id, asset_group.name, asset_group.comment)
else:
print '[%-3s] %-15s' % (asset_group.id, asset_group.name)
print
def main():
@ -492,29 +553,26 @@ def main():
if not login_user: # 判断用户是否存在
color_print(u'没有该用户或许你是以root运行的 No that user.', exits=True)
print_prompt()
gid_pattern = re.compile(r'^g\d+$')
nav = Nav(login_user)
nav.print_nav()
try:
while True:
try:
option = raw_input("\033[1;32mOpt or IP>:\033[0m ")
option = raw_input("\033[1;32mOpt or ID>:\033[0m ").strip()
except EOFError:
print_prompt()
nav.print_nav()
continue
except KeyboardInterrupt:
sys.exit(0)
if option in ['P', 'p']:
login_user.get_asset_info(printable=True)
if option in ['P', 'p', '\n', '']:
nav.search()
continue
if option.startswith('/') or gid_pattern.match(option):
nav.search(option.lstrip('/'))
elif option in ['G', 'g']:
login_user.get_asset_group_info(printable=True)
continue
elif gid_pattern.match(option):
gid = option[1:].strip()
asset_group = get_object(AssetGroup, id=gid)
if asset_group and asset_group.is_permed(user=login_user):
asset_group.get_asset_info(printable=True)
nav.print_asset_group()
continue
elif option in ['E', 'e']:
# exec_cmd_servers(login_name)
@ -523,7 +581,11 @@ def main():
sys.exit()
else:
try:
verify_connect(login_user, option)
asset = nav.search_result[int(option)]
ssh_tty = SshTty('a', 'b')
ssh_tty.connect()
except (KeyError, ValueError):
color_print('请输入正确ID', 'red')
except ServerError, e:
color_print(e, 'red')
except IndexError:

View File

@ -1,6 +1,5 @@
sphinx-me==0.3
django==1.6
python-ldap==2.4.19
pycrypto==2.6.1
paramiko==1.15.2
ecdsa==0.13
@ -9,4 +8,9 @@ django-uuidfield==0.5.0
psutil==2.2.1
xlsxwriter==0.7.7
xlrd==0.9.4
django-bootstrap-form
django-bootstrap-form
tornado
ansible
pyinotify
passlib
argparse

View File

@ -311,8 +311,12 @@ def write_excel(asset_all):
group_all = '/'.join(group_list)
status = asset.get_status_display()
idc_name = asset.idc.name if asset.idc else u''
system_type = asset.system_type if asset.idc else u''
system_version = asset.system_version if asset.idc else u''
system_os = unicode(system_type) + unicode(system_version)
alter_dic = [asset.hostname, asset.ip, idc_name, asset.mac, asset.remote_ip, asset.cpu, asset.memory,
asset.disk, (asset.system_type + asset.system_version), asset.cabinet, group_all, status,
asset.disk, system_os, asset.cabinet, group_all, status,
asset.comment]
data.append(alter_dic)
format = workbook.add_format()
@ -381,13 +385,13 @@ def excel_to_db(excel_file):
row = table.row_values(row_num)
if row:
ip, port, hostname, use_default_auth, username, password, group = row
print ip
use_default_auth = 1 if use_default_auth == u'默认' else 0
if get_object(Asset, ip=ip):
continue
if ip and port:
asset = Asset(ip=ip,
port=port,
hostname=hostname,
use_default_auth=use_default_auth,
username=username,
password=password

View File

@ -37,8 +37,8 @@ class AssetGroup(models.Model):
class IDC(models.Model):
name = models.CharField(max_length=32, verbose_name=u'机房名称')
bandwidth = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机房带宽')
linkman = models.CharField(max_length=16, null=True, verbose_name=u'联系人')
phone = models.CharField(max_length=32, verbose_name=u'联系电话')
linkman = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'联系人')
phone = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'联系电话')
address = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"机房地址")
network = models.TextField(blank=True, null=True, verbose_name=u"IP地址段")
date_added = models.DateField(auto_now=True, null=True)

View File

@ -2,9 +2,9 @@
import ast
from django.db.models import Q
from django.shortcuts import get_object_or_404
from jasset.asset_api import *
from jumpserver.api import *
from jumpserver.models import Setting
from jasset.forms import AssetForm, IdcForm
from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS
from ansible_api import Tasks
@ -13,7 +13,7 @@ from ansible_api import Tasks
@require_role('admin')
def group_add(request):
"""
Add asset group
Group add view
添加资产组
"""
header_title, path1, path2 = u'添加资产组', u'资产管理', u'添加资产组'
@ -47,7 +47,7 @@ def group_add(request):
@require_role('admin')
def group_edit(request):
"""
Edit asset group
Group edit view
编辑资产组
"""
header_title, path1, path2 = u'编辑主机组', u'资产管理', u'编辑主机组'
@ -89,7 +89,10 @@ def group_edit(request):
@require_role('admin')
def group_detail(request):
""" 主机组详情 """
"""
Group detail view
主机组详情
"""
header_title, path1, path2 = u'主机组详情', u'资产管理', u'主机组详情'
group_id = request.GET.get('id', '')
group = get_object(AssetGroup, id=group_id)
@ -121,7 +124,7 @@ def group_list(request):
@require_role('admin')
def group_del(request):
"""
del asset group
Group delete view
删除主机组
"""
group_ids = request.GET.get('id', '')
@ -160,7 +163,7 @@ def asset_add(request):
asset_save = af_post.save(commit=False)
if not use_default_auth:
password = request.POST.get('password', '')
password_encode = CRYPTOR.encrypt(password)
password_encode = password
asset_save.password = password_encode
asset_save.is_active = True if is_active else False
asset_save.save()
@ -293,7 +296,7 @@ def asset_list(request):
s = write_excel(asset_find)
if s[0]:
file_name = s[1]
smg = 'excel文件已生成请点击下载!'
smg = u'excel文件已生成请点击下载!'
return my_render('jasset/asset_excel_download.html', locals(), request)
assets_list, p, assets, page_range, current_page, show_first, show_end = pages(asset_find, request)
return my_render('jasset/asset_list.html', locals(), request)
@ -330,13 +333,20 @@ def asset_update(request):
return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id)
name = request.session.get('username', 'admin')
if asset.use_default_auth:
username = 'root'
password = '123456'
default = Setting.objects.all()
if default:
default = default[0]
username = default.default_user
password = default.default_password
port = default.default_port
else:
return HttpResponse(u'没有设置默认用户名和密码!')
else:
username = asset.username
password = asset.password
port = asset.port
resource = [{"hostname": asset.ip, "port": asset.port,
resource = [{"hostname": asset.ip, "port": port,
"username": username, "password": password}]
ansible_instance = Tasks(resource)
@ -446,16 +456,17 @@ def idc_del(request):
"""
IDC delete view
"""
uuid = request.GET.get('uuid', '')
idc = get_object_or_404(IDC, uuid=uuid)
idc.delete()
uuid = request.GET.get('id', '')
idc = get_object(IDC, id=uuid)
if idc:
idc.delete()
return HttpResponseRedirect('/jasset/idc_list/')
@require_role('admin')
def asset_upload(request):
"""
Upload file view
Upload asset excel file view
"""
if request.method == 'POST':
excel_file = request.FILES.get('file_name', '')

View File

@ -15,11 +15,11 @@ from utils import get_rand_pass
import os.path
API_DIR = os.path.dirname(os.path.abspath(__file__))
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
class AnsibleError(StandardError):
"""
the base AnsibleError which contains error(required),
@ -61,7 +61,7 @@ class MyInventory(object):
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
"""
self.resource = resource
self.inventory = Inventory()
self.inventory = Inventory(host_list=[])
self.gen_inventory()
def add_group(self, hosts, groupname, groupvars=None):
@ -101,7 +101,7 @@ class MyInventory(object):
add hosts to inventory.
"""
if isinstance(self.resource, list):
self.add_group(self.resource, 'my_group')
self.add_group(self.resource, 'default_group')
elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.iteritems():
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
@ -115,21 +115,23 @@ class Command(MyInventory):
super(Command, self).__init__(*args, **kwargs)
self.results = ''
def run(self, command, module_name="command", timeout=5, forks=10, group='my_group'):
def run(self, command, module_name="command", timeout=10, forks=10, group='default_group', pattern='*'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如
'uname -a'
"""
if module_name not in ["raw", "command", "shell"]:
raise CommandValueError("module_name",
raise CommandValueError("module_name",
"module_name must be of the 'raw, command, shell'")
hoc = Runner(module_name=module_name,
module_args=command,
timeout=timeout,
inventory=self.inventory,
subset=group,
forks=forks
pattern=pattern,
forks=forks,
)
self.results = hoc.run()
@ -203,7 +205,7 @@ class Tasks(Command):
def __init__(self, *args, **kwargs):
super(Tasks, self).__init__(*args, **kwargs)
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='my_group'):
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='default_group', pattern='*'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如
@ -214,7 +216,8 @@ class Tasks(Command):
timeout=timeout,
inventory=self.inventory,
subset=group,
forks=forks
pattern=pattern,
forks=forks,
)
self.results = hoc.run()
@ -425,7 +428,6 @@ class MyPlaybook(MyInventory):
def __init__(self, *args, **kwargs):
super(MyPlaybook, self).__init__(*args, **kwargs)
def run(self, playbook_relational_path, extra_vars=None):
"""
run ansible playbook,
@ -464,7 +466,6 @@ class App(MyPlaybook):
if __name__ == "__main__":
pass
# resource = {
# "group1": {
@ -472,8 +473,10 @@ if __name__ == "__main__":
# "vars" : {"var1": "value1", "var2": "value2"},
# },
# }
# command = Command(resource)
# print command.run("who", group="group1")
resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902"}]
command = Command(resource)
print command.run("who")
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
# task = Tasks(resource)

View File

@ -32,14 +32,13 @@ class PermRole(models.Model):
class PermRule(models.Model):
date_added = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
name = models.CharField(max_length=100, unique=True)
comment = models.CharField(max_length=100)
asset = models.ManyToManyField(Asset, related_name='perm_rule')
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule')
user = models.ManyToManyField(User, related_name='perm_rule')
user_group = models.ManyToManyField(UserGroup, related_name='perm_rule')
role = models.ManyToManyField(PermRole, related_name='perm_rule')
ssh_type = models.BooleanField()
def __unicode__(self):
return self.name

View File

@ -89,7 +89,7 @@ def perm_user_api(perm_info):
the_new_users = ','.join(new_username)
the_del_users = ','.join(del_username)
playbook = get_playbook(os.path.join(BASE_DIR, 'playbook', 'user_perm.yaml'),
playbook = get_playbook(os.path.join(BASE_DIR, 'keys/../playbook', 'user_perm.yaml'),
{'the_new_group': 'new', 'the_del_group': 'del',
'the_new_users': the_new_users, 'the_del_users': the_del_users,
'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')})

View File

@ -4,7 +4,7 @@ import random
import os.path
from paramiko.rsakey import RSAKey
from os import chmod, mkdir
from jumpserver.api import mkdir
from uuid import uuid4
from jumpserver.settings import KEY_DIR
@ -45,9 +45,8 @@ def gen_keys():
:return: 返回目录名(uuid)
"""
key_basename = "key-" + uuid4().hex
key_path_dir = os.path.join(KEY_DIR, key_basename)
mkdir(key_path_dir, 0700)
key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
mkdir(key_path_dir, 0755)
key = RSAKey.generate(2048)
private_key = os.path.join(key_path_dir, 'id_rsa')
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
@ -62,8 +61,6 @@ def gen_keys():
return key_path_dir
if __name__ == "__main__":
print gen_keys()

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
from django.db.models import Q
from jperm.perm_api import *
from jperm.models import PermLog as Log
@ -11,12 +10,13 @@ from juser.user_api import gen_ssh_key
from juser.models import User, UserGroup
from jasset.models import Asset, AssetGroup
from jperm.models import PermRole, PermRule
from jumpserver.models import Setting
from jperm.utils import updates_dict, gen_keys, get_rand_pass
from jperm.ansible_api import Tasks
from jperm.perm_api import get_role_info
from jumpserver.api import my_render, get_object
from jumpserver.api import my_render, get_object, CRYPTOR
@require_role('admin')
@ -62,7 +62,7 @@ def perm_rule_detail(request):
assets = asset_obj
return my_render('jperm/perm_rule_detail.html', locals(), request)
def perm_rule_add(request):
"""
@ -89,7 +89,8 @@ def perm_rule_add(request):
asset_groups_select = request.POST.getlist('assetgroup', [])
roles_select = request.POST.getlist('role', [])
rule_name = request.POST.get('rulename')
rule_comment = request.POST.get('comment')
rule_comment = request.POST.get('rule_comment')
rule_ssh_key = request.POST.get("use_publicKey")
# 获取需要授权的主机列表
assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
@ -115,7 +116,19 @@ def perm_rule_add(request):
rule.asset_group = asset_groups_obj
rule.role = roles_obj
rule.save()
return HttpResponse(u"添加授权规则:%s" % rule.name)
msg = u"添加授权规则:%s" % rule.name
# 渲染数据
header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
rules_list = PermRule.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
rules_list = rules_list.filter(Q(name=keyword))
rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin')
@ -131,17 +144,69 @@ def perm_rule_edit(request):
rule = PermRule.objects.get(id=rule_id)
if request.method == 'GET' and rule_id:
# 渲染数据, 获取所有的rule对象
users = rule.user.all()
user_groups = rule.user_group.all()
assets = rule.asset.all()
asset_groups = rule.asset_group.all()
roles = rule.role.all()
# 渲染数据, 获取所选的rule对象
rule_comment = rule.comment
users_select = rule.user.all()
user_groups_select = rule.user_group.all()
assets_select = rule.asset.all()
asset_groups_select = rule.asset_group.all()
roles_select = rule.role.all()
users = User.objects.all()
user_groups = UserGroup.objects.all()
assets = Asset.objects.all()
asset_groups = AssetGroup.objects.all()
roles = PermRole.objects.all()
return my_render('jperm/perm_rule_edit.html', locals(), request)
elif request.method == 'POST' and rule_id:
return HttpResponse("uncompleted")
# 获取用户选择的 用户,用户组,资产,资产组,用户角色
rule_name = request.POST.get('rule_name')
rule_comment = request.POST.get("rule_comment")
users_select = request.POST.getlist('user', [])
user_groups_select = request.POST.getlist('usergroup', [])
assets_select = request.POST.getlist('asset', [])
asset_groups_select = request.POST.getlist('assetgroup', [])
roles_select = request.POST.getlist('role', [])
# 获取需要授权的主机列表
assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
asset_groups_obj = [AssetGroup.objects.get(name=group) for group in asset_groups_select]
group_assets_obj = [asset for asset in [group.asset_set.all() for group in asset_groups_obj]]
calc_assets = set(group_assets_obj) | set(assets_obj)
# 获取需要授权的用户列表
users_obj = [User.objects.get(name=user) for user in users_select]
user_groups_obj = [UserGroup.objects.get(name=group) for group in user_groups_select]
group_users_obj = [user for user in [group.user_set.all() for group in user_groups_obj]]
calc_users = set(group_users_obj) | set(users_obj)
# 获取授予的角色列表
roles_obj = [PermRole.objects.get(name=role) for role in roles_select]
# 仅授权成功的,写回数据库(授权规则,用户,用户组,资产,资产组,用户角色)
rule.user = users_obj
rule.usergroup = user_groups_obj
rule.asset = assets_obj
rule.asset_group = asset_groups_obj
rule.role = roles_obj
rule.name = rule_name
rule.comment = rule.comment
rule.save()
msg = u"更新授权规则:%s" % rule.name
# 渲染数据
header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
rules_list = PermRule.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
rules_list = rules_list.filter(Q(name=keyword))
rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin')
@ -201,12 +266,24 @@ def perm_role_add(request):
name = request.POST.get("role_name")
comment = request.POST.get("role_comment")
password = request.POST.get("role_password")
encrypt_pass = CRYPTOR.encrypt(password)
# 生成随机密码,生成秘钥对
key_path = gen_keys()
role = PermRole(name=name, comment=comment, password=password, key_path=key_path)
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
role.save()
return HttpResponse(u"添加角色: %s" % name)
msg = u"添加角色: %s" % name
# 渲染 刷新数据
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
roles_list = PermRole.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
roles_list = roles_list.filter(Q(name=keyword))
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
return my_render('jperm/perm_role_list.html', locals(), request)
else:
return HttpResponse(u"不支持该操作")
@ -252,8 +329,12 @@ def perm_role_detail(request):
role_info = get_role_info(role_id)
# 渲染数据
for key, value in role_info.iteritems():
key = value
rules = role_info.get("rules")
assets = role_info.get("assets")
asset_groups = role_info.get("asset_groups")
users = role_info.get("users")
user_groups = role_info.get("user_groups")
return my_render('jperm/perm_role_detail.html', locals(), request)
@ -265,15 +346,40 @@ def perm_role_edit(request):
# 渲染数据
header_title, path1, path2 = "系统角色", "角色管理", "角色编辑"
# 渲染数据
role_id = request.GET.get("id")
role = PermRole.objects.get(id=role_id)
role_pass = CRYPTOR.decrypt(role.password)
if request.method == "GET":
role_id = request.GET.get("id")
# 渲染数据
role = PermRole.objects.get(id=role_id)
return my_render('jperm/perm_role_edit.html', locals(), request)
if request.method == "POST":
return HttpResponse(u"未实现")
# 获取 POST 数据
role_name = request.POST.get("role_name")
role_password = request.POST.get("role_password")
encrypt_role_pass = CRYPTOR.encrypt(role_password)
role_comment = request.POST.get("role_comment")
# 写入数据库
role.name = role_name
role.password = encrypt_role_pass
role.comment = role_comment
role.save()
msg = u"更新系统角色: %s" % role.name
# 渲染 刷新数据
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
roles_list = PermRole.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
roles_list = roles_list.filter(Q(name=keyword))
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
return my_render('jperm/perm_role_list.html', locals(), request)
@require_role('admin')
@ -307,10 +413,20 @@ def perm_role_push(request):
calc_assets = set(assets_obj) | set(group_assets_obj)
# 生成Inventory
push_resource = [{"hostname": asset.ip,
"port": asset.port,
"username": asset.username,
"password": asset.password} for asset in calc_assets]
push_resource = []
for asset in calc_assets:
if asset.use_default_auth:
username = Setting.default_user
password = Setting.default_password
port = Setting.default_port
else:
username = asset.username
password = asset.password
port = asset.port
push_resource.append({"hostname": asset.ip,
"port": port,
"username": username,
"password": password})
# 获取角色的推送方式,以及推送需要的信息
roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names]
@ -326,10 +442,13 @@ def perm_role_push(request):
task = Tasks(push_resource)
ret = {}
ret_failed = []
if password_push:
ret["password_push"] = task.add_multi_user(**role_pass)
if ret["password_push"].get("status") != "success":
ret_failed.append(1)
# 因为要先建立用户所以password 是必选项,
# 而push key是在 password也完成的情况下的 可选项
ret["password_push"] = task.add_multi_user(**role_pass)
if ret["password_push"].get("status") != "success":
ret_failed.append(1)
if key_push:
ret["key_push"] = task.push_multi_key(**role_key)
if ret["key_push"].get("status") != "success":

View File

@ -14,10 +14,8 @@ from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.http import HttpResponse, Http404
from django.template import RequestContext
from juser.models import User, UserGroup
from jlog.models import Log
from jasset.models import Asset, AssetGroup
# from jlog.models import Log
from jlog.models import Log, TtyLog
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.core.mail import send_mail
@ -197,9 +195,9 @@ def require_role(role='user'):
def _deco(func):
def __deco(request, *args, **kwargs):
request.session['pre_url'] = request.path
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
if role == 'admin':
# if request.session.get('role_id', 0) < 1:
if request.user.role == 'CU':
@ -395,8 +393,9 @@ def mkdir(dir_name, username='root', mode=0755):
"""
if not os.path.isdir(dir_name):
os.makedirs(dir_name)
bash("chown %s:%s '%s'" % (username, username, dir_name))
os.chmod(dir_name, mode)
if username:
bash('chown %s:%s %s' % (username, username, dir_name))
def http_success(request, msg):
@ -414,4 +413,3 @@ def my_render(template, data, request):
CRYPTOR = PyCrypt(KEY)
logger = set_log(LOG_LEVEL)
KEY_DIR = os.path.join(BASE_DIR, 'keys')

View File

@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser()
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
config.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
KEY_DIR = os.path.join(BASE_DIR, 'keys')
KEY_DIR = os.path.join(BASE_DIR, 'role_keys')
DB_HOST = config.get('db', 'host')
DB_PORT = config.getint('db', 'port')
@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5
# ======== Log ==========
LOG_DIR = os.path.join(BASE_DIR, 'logs')
SSH_KEY_DIR = os.path.join(BASE_DIR, 'role_keys')
SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys/role_keys')
KEY = config.get('base', 'key')
URL = config.get('base', 'url')
LOG_LEVEL = config.get('base', 'log')

View File

@ -226,3 +226,14 @@ def ip_str_to_list(ip_str):
ip str to list
"""
return ip_str.split(',')
@register.filter(name='key_exist')
def key_exist(username):
"""
ssh key is exist or not
"""
if os.path.isfile(os.path.join(KEY_DIR, 'user', username)):
return True
else:
return False

View File

@ -15,7 +15,6 @@ from jumpserver.api import *
from jumpserver.models import Setting
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from settings import BASE_DIR
from jlog.models import Log
@ -236,7 +235,7 @@ def Login(request):
request.session['role_id'] = 1
else:
request.session['role_id'] = 0
return HttpResponseRedirect(request.GET.get('next', '/'), )
return HttpResponseRedirect(request.session.get('pre_url', '/'))
# response.set_cookie('username', username, expires=604800)
# response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800)
# return response
@ -269,7 +268,7 @@ def setting(request):
if '' in [username, port] and ('' in password or '' in private_key):
return HttpResponse('所填内容不能为空, 且密码和私钥填一个')
else:
private_key_path = os.path.join(BASE_DIR, 'role_keys', 'default', 'default_private_key.pem')
private_key_path = os.path.join(BASE_DIR, 'keys/role_keys', 'default', 'default_private_key.pem')
if private_key:
with open(private_key_path, 'w') as f:
f.write(private_key)

View File

@ -123,21 +123,21 @@ def db_del_user(username):
def gen_ssh_key(username, password='',
key_dir=os.path.join(KEY_DIR, 'user'),
authorized_keys=True, home="/home", length=2048):
"""
generate a user ssh key in a property dir
生成一个用户ssh密钥对
"""
logger.debug('生成ssh key 并设置authorized_keys')
private_key_file = os.path.join(key_dir, username)
mkdir(private_key_file, username)
mkdir(key_dir)
if os.path.isfile(private_key_file):
os.unlink(private_key_file)
ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
if authorized_keys:
auth_key_dir = os.path.join(home, username, '.ssh')
mkdir(auth_key_dir, username, mode=0700)
mkdir(auth_key_dir, mode=0700)
authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys')
with open(private_key_file+'.pub') as pub_f:
with open(authorized_key_file, 'w') as auth_f:

3
keys/README.md Normal file
View File

@ -0,0 +1,3 @@
看山是山,看水是水
看山不是山,看水不是水
看山是山,看水是水

1
logs/README.md Normal file
View File

@ -0,0 +1 @@
永远年轻,永远热泪盈眶

View File

@ -1,17 +0,0 @@
- hosts: the_del_group
tasks:
- name: del user
user: name={{ item }} state=absent remove=yes
with_items: [ the_del_users ]
- hosts: the_new_group
tasks:
- name: add user
user: name={{ item }} state=present
with_items: [ the_new_users ]
- name: .ssh direcotory
file: name=/home/{{ item }}/.ssh mode=700 owner={{ item }} group={{ item }} state=directory
with_items: [ the_new_users ]
- name: set authorizied_file
copy: src=KEY_DIR/{{ item }}.pub dest=/home/{{ item }}/.ssh/authorizied_keys owner={{ item }} group={{ item }} mode=600
with_items: [ the_new_users ]

View File

@ -14,7 +14,6 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="/juser/user_list/">{{ users.count}}</a></h1>
{# <div class="stat-percent font-bold text-success">{{ percent_user }} <i class="fa fa-bolt"></i></div>#}
<small>All user</small>
</div>
</div>
@ -27,7 +26,6 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="/jasset/host_list/">{{ hosts.count }}</a></h1>
{# <div class="stat-percent font-bold text-info">{{ percent_host }} <i class="fa fa-level-up"></i></div>#}
<small>All host</small>
</div>
</div>
@ -37,7 +35,7 @@
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label label-primary pull-right">Online</span>
<h5>实时在线用户</h5>
<h5>在线用户</h5>
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_users">{{ online_user | length }}</span></a></h1>
@ -55,7 +53,6 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_hosts">{{ online_host | length }}</span></a></h1>
{# <div class="stat-percent font-bold text-danger">{{ percent_online_host }} <i class="fa fa-level-down"></i></div>#}
<small>Connected host</small>
</div>
</div>
@ -169,7 +166,7 @@
</div>
</div>
<div class="ibox-content ibox-heading">
<h3><i class="fa fa-user"></i> 一周Top10资产 </h3>
<h3><i class="fa fa-inbox"></i> 一周Top10资产 </h3>
<small><i class="fa fa-map-marker"></i> 登录次数及最近一次登录记录. </small>
</div>
<div class="ibox-content inspinia-timeline">
@ -309,14 +306,7 @@
</div>
</div>
</div>
<!--</div>-->
<!--<div class="col-xm-6" id="top10" style="width:50%;height:400px;"></div>-->
<!--<div class="col-xm-6" id="usertop10" style="width:50%;height:400px;"></div>-->
<!--<div class="row">-->
<!--<div class="col-lg-6" id="hosttop10" style="width:50%;height:400px; margin-top: 20px"></div>-->
<!--</div>-->
</div>
</div>
</div>
{% endblock %}

View File

@ -31,11 +31,11 @@
<table class="table">
<tr>
<td class="text-navy">IP</td>
<td>{{ asset.ip }}</td>
<td>{{ asset.ip|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">主机名</td>
<td>{{ asset.hostname }}</td>
<td>{{ asset.hostname|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">其他IP</td>
@ -53,11 +53,11 @@
</tr>
<tr>
<td class="text-navy">远控IP</td>
<td>{{ asset.remote_ip }}</td>
<td>{{ asset.remote_ip|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">端口</td>
<td>{{ asset.port }}</td>
<td>{{ asset.port|default_if_none:"" }}</td>
</tr>
<tr>
@ -66,7 +66,7 @@
<table class="table">
{% for asset_group in asset.group.all %}
<tr>
<td>{{ asset_group.name }}</td>
<td>{{ asset_group.name|default_if_none:"" }}</td>
</tr>
{% endfor %}
</table>
@ -79,19 +79,19 @@
</tr>
<tr>
<td class="text-navy">机房</td>
<td>{{ asset.idc.name }}</td>
<td>{{ asset.idc.name|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">硬件厂商型号</td>
<td>{{ asset.brand }}</td>
<td>{{ asset.brand|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">CPU</td>
<td>{{ asset.cpu }}</td>
<td>{{ asset.cpu|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">内存</td>
<td>{{ asset.memory }}M</td>
<td>{{ asset.memory|default_if_none:"" }}{% if asset.memory %}M{% endif %}</td>
</tr>
<tr>
<td class="text-navy">硬盘</td>
@ -100,7 +100,7 @@
{% if asset.disk %}
{% for disk, value in asset.disk|str_to_dic %}
<tr>
<td><span class="text-navy">{{ disk }}</span> &nbsp&nbsp&nbsp {{ value }}</td>
<td><span class="text-navy">{{ disk|default_if_none:"" }}</span> &nbsp&nbsp&nbsp {{ value|default_if_none:"" }}</td>
</tr>
{% endfor %}
{% endif %}
@ -109,35 +109,35 @@
</tr>
<tr>
<td class="text-navy">资产编号</td>
<td>{{ asset.number }}</td>
<td>{{ asset.number|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">SN</td>
<td>{{ asset.sn }}</td>
<td>{{ asset.sn|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">主机类型</td>
<td>{{ asset.get_asset_type_display }}</td>
<td>{{ asset.get_asset_type_display|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">系统版本</td>
<td>{{ asset.system_type }} {{ asset.system_version }}</td>
<td>{{ asset.system_type|default_if_none:"" }} {{ asset.system_version|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">运行环境</td>
<td>{{ asset.get_env_display }}</td>
<td>{{ asset.get_env_display|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">机器状态</td>
<td>{{ asset.get_status_display }}</td>
<td>{{ asset.get_status_display|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">机柜号</td>
<td>{{ asset.cabinet }}</td>
<td>{{ asset.cabinet|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">机柜位置</td>
<td>{{ asset.position }}</td>
<td>{{ asset.position|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">激活</td>
@ -149,7 +149,7 @@
</tr>
<tr>
<td class="text-navy">备注</td>
<td>{{ asset.comment }}</td>
<td>{{ asset.comment|default_if_none:"" }}</td>
</tr>
</table>
</div>

View File

@ -54,17 +54,17 @@
<div class="col-sm-2">
<div class="radio i-checks">
<label>
<input type="radio" checked="" value="no_action" name="use_default_auth"><span> 不修改 </span>
<input type="radio" checked="" value="no_action" id="no" name="use_default_auth" class="auth"><span> 不修改 </span>
</label>
</div>
<div class="radio i-checks">
<label>
<input type="radio" name="use_default_auth"><span> 使用默认 </span>
<input type="radio" id="default" name="use_default_auth" class="auth"><span> 使用默认 </span>
</label>
</div>
<div class="radio i-checks">
<label>
<input type="radio" id="id_use_default_auth" name="use_default_auth"><span> 用户名密码 </span>
<input type="radio" id="pass" name="use_default_auth" class="auth"><span> 用户名密码 </span>
</label>
</div>
</div>
@ -140,8 +140,8 @@
$('#uuid').val(ids)
});
$('#id_use_default_auth').click(function(){
if ($(this).is(':checked')){
$('.auth').click(function(){
if ($(this).attr('id') == 'pass'){
$('#admin_account').css('display', 'block')
}
else {

View File

@ -1,7 +1,6 @@
<div class="col-md-12 column">
<div class="alert alert-success alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4>
</h4> <strong>Nice!</strong> excel文件已生成请点击 <a href="/static/files/excels/{{ file_name }}" target="_blank" class="alert-link">下载</a>
<strong>Nice!</strong> excel文件已生成请点击 <a href="/static/files/excels/{{ file_name }}" target="_blank" class="alert-link">下载</a>
</div>
</div>

View File

@ -119,12 +119,12 @@
<td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'>
<input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks">
</td>
<td class="text-center"> {{ asset.ip }} </td>
<td class="text-center"> {{ asset.hostname }} </td>
<td class="text-center"> {{ asset.idc.name }} </td>
<td class="text-center"> {{ asset.ip|default_if_none:"" }} </td>
<td class="text-center"> {{ asset.hostname|default_if_none:"" }} </td>
<td class="text-center"> {{ asset.idc.name|default_if_none:"" }} </td>
<td class="text-center">{{ asset.group.all|group_str2 }}</td>
{# <td class="text-center">{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#}
<td class="text-center">{{ asset.system_type }}{{ asset.system_version }}</td>
<td class="text-center">{{ asset.system_type|default_if_none:"" }}{{ asset.system_version|default_if_none:"" }}</td>
<td class="text-center"> {{ asset.use_default_auth|bool2str }} </td>
<td class="text-center" data-editable='false'>
<a href="/jasset/asset_detail/?id={{ asset.id }}" class="btn btn-xs btn-primary">详情</a>
@ -169,17 +169,17 @@
});
$(document).ready(function(){
$('#editable').editableTableWidget({editor: $('<textarea>')});
$('.asset_del').click(function(){
var row = $(this).closest('tr');
$.get(
$(this).attr('value'),
{},
function(data){
alert(data);
row.remove()
}
)
if (confirm("确定删除")) {
$.get(
$(this).attr('value'),
{},
function (data) {
row.remove()
}
)
}
})
});

View File

@ -75,12 +75,12 @@
<div class="form-group">
<label for="" class="col-sm-2 control-label">主机<span class="red-fonts">*</span></label>
<label for="" class="col-sm-2 control-label">主机</label>
<div class="col-sm-4">
<div>
<select id="assets" name="assets" class="form-control m-b" size="12" multiple>
{% for asset in asset_all %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
<option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
{% endfor %}
</select>
</div>
@ -133,12 +133,12 @@
timely: 2,
theme: "yellow_right_effect",
fields: {
"j_group": {
"name": {
rule: "required",
tip: "输入业务组名",
tip: "输入主机组名",
ok: "",
msg: {required: "业务组名必须填写!"},
data: {'data-ok':"业务组名可以使用"}
msg: {required: "主机组名必须填写!"},
data: {'data-ok':"主机组名可以使用"}
}
},
valid: function(form) {

View File

@ -52,17 +52,17 @@
<tbody>
{% for asset in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" name="j_id" value="{{ asset.id }}" data-editable='false'><input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" name="j_ip"> {{ asset.ip }} </td>
<td class="text-center" name="j_port"> {{ asset.port }} </td>
<td class="text-center" name="j_idc"> {{ asset.idc.name }} </td>
<td class="text-center" name="j_id" value="{{ asset.id|default_if_none:"" }}" data-editable='false'><input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" name="j_ip"> {{ asset.ip|default_if_none:"" }} </td>
<td class="text-center" name="j_port"> {{ asset.port|default_if_none:"" }} </td>
<td class="text-center" name="j_idc"> {{ asset.idc.name|default_if_none:"" }} </td>
<td class="text-center" name="j_group">{{ asset.bis_group.all | group_str2 }}</td>
<td class="text-center" name="j_active"> {{ asset.is_active|bool2str }} </td>
<td class="text-center"> {{ asset.date_added|date:"Y-m-d H:i:s" }} </td>
<td class="text-center" name="j_comment"> {{ asset.comment }} </td>
<td class="text-center" name="j_comment"> {{ asset.comment|default_if_none:"" }} </td>
<td class="text-center" data-editable='false'>
<a href="/jasset/host_detail/?id={{ asset.id }}" class="iframe btn btn-xs btn-primary">详情</a>
<a href="/jasset/host_edit/?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/asset_detail/?id={{ asset.id }}" class="iframe btn btn-xs btn-primary">详情</a>
<a href="/jasset/asset_edit/?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/group_del_host/?id={{ asset.id }}&gid={{ group.id }}" class="btn btn-xs btn-danger">删除</a>
</td>
</tr>

View File

@ -86,7 +86,7 @@
<div>
<select id="assets" name="assets" class="form-control m-b" size="12" multiple>
{% for asset in asset_no_select %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
<option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
{% endfor %}
</select>
</div>
@ -103,7 +103,7 @@
<div>
<select id="asset_select" name="asset_select" class="form-control m-b" size="12" multiple>
{% for asset in asset_select %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
<option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
{% endfor %}
</select>
</div>

View File

@ -63,7 +63,7 @@
<td class="text-center">
<a href="/jasset/group_detail/?id={{ asset_group.id }}" class="btn btn-xs btn-info">详情</a>
<a href="/jasset/group_edit/?id={{ asset_group.id }}" class="btn btn-xs btn-info">编辑</a>
<a value="/jasset/group_del/?id={{ asset_group.id }}" id="del" class="btn btn-xs btn-danger">删除</a>
<a value="/jasset/group_del/?id={{ asset_group.id }}" class="btn btn-xs btn-danger group_del">删除</a>
</td>
</tr>
{% endfor %}
@ -88,16 +88,17 @@
{% block self_footer_js %}
<script>
$(document).ready(function(){
$('#del').click(function(){
$('.group_del').click(function(){
var row = $(this).closest('tr');
$.get(
$(this).attr('value'),
{},
function(data){
row.remove();
alert(data)
}
)
if (confirm('确定删除')) {
$.get(
$(this).attr('value'),
{},
function (data) {
row.remove();
}
)
}
});
$('#del_check').click(function(){
@ -111,15 +112,12 @@
{id: check_array.join(',')},
function(data){
$('tr.gradeX input:checked').closest('tr').remove();
alert(data);
}
)
}
})
});
</script>
{% endblock %}

View File

@ -40,6 +40,13 @@
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="role_password_label" class="col-sm-2 control-label">角色密码<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="role_password" name="role_password" type="password" class="form-control" value="{{ role_pass }}">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="role_comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">

View File

@ -7,6 +7,14 @@
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<div class="ibox-title">
<h5> 所有系统角色</h5>
<div class="ibox-tools">

View File

@ -67,16 +67,6 @@
</div>
<div class="hr-line-dashed"></div>
<div class="row">
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1">

View File

@ -95,51 +95,11 @@
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="0" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_password" style="display: none">
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_publicKey" name="use_publicKey">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_publicKey" style="display: none">
<label class="col-sm-1 control-label"> 秘钥<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="Rule Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
<input id="rule_comment" name="rule_comment" placeholder="Rule Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
</div>
</div>
<div class="hr-line-dashed"></div>

View File

@ -45,7 +45,7 @@
<div class="col-sm-8">
<select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user in users %}
<option value="{{ user.name }}">{{ user.name }}</option>
<option value="{{ user.name }}" {% if user in users_select %} selected {% endif %}>{{ user.name }}</option>
{% endfor %}
</select>
</div>
@ -56,7 +56,7 @@
<div class="col-sm-8">
<select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user_group in user_groups %}
<option value="{{ user_group.name }}">{{ user_group.name }}</option>
<option value="{{ user_group.name }}"{% if user_group in users_groups_select %} selected {% endif %}>{{ user_group.name }}</option>
{% endfor %}
</select>
</div>
@ -67,7 +67,7 @@
<div class="col-sm-8">
<select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
<option value="{{ asset.ip }}"{% if asset in assets_select %} selected {% endif %}>{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
@ -78,7 +78,7 @@
<div class="col-sm-8">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %}
<option value="{{ asset_group.name }}">{{ asset_group.name }}</option>
<option value="{{ asset_group.name }}"{% if asset_group in asset_groups_select %} selected {% endif %}>{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
@ -89,57 +89,17 @@
<div class="col-sm-8">
<select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
{% for role in roles %}
<option value="{{ role.name }}">{{ role.name }}</option>
<option value="{{ role.name }}"{% if role in roles_select %} selected {% endif %}>{{ role.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="0" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_password" style="display: none">
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_publicKey" name="use_publicKey">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_publicKey" style="display: none">
<label class="col-sm-1 control-label"> 秘钥<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
<input id="role_comment" name="role_comment" placeholder="Rule Comment" type="text" class="form-control" value="{{ rule_comment }}">
</div>
</div>
<div class="hr-line-dashed"></div>

View File

@ -3,10 +3,20 @@
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<div class="ibox-title">
<h5> 所有规则</h5>
<div class="ibox-tools">
@ -55,19 +65,19 @@
<tr class="gradeX" id={{ rule.id }}>
<td class="text-center"> {{ rule.name }} </td>
<td class="text-center">
<a href="/jasset/asset_list/?gid={{ user.id }}">{{ rule | rule_member_count:"user" }} </a>
{{ rule | rule_member_count:"user" }}
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"user_group" }}</a>
{{ rule | rule_member_count:"user_group" }}
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"asset" }}</a>
{{ rule | rule_member_count:"asset" }}
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"asset_group" }}</a>
{{ rule | rule_member_count:"asset_group" }}
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"role" }}</a>
{{ rule | rule_member_count:"role" }}
</td>
<td class="text-center">
<a href="/jperm/perm_rule_detail/?id={{ rule.id }}" class="btn btn-xs btn-primary">详情</a>

View File

@ -64,7 +64,13 @@
<td class="text-center" title="{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"> {{ user.group.all | groups2str }} </td>
<td class="text-center"> {{ user.id | get_role }}</td>
<td class="text-center">{{ user.is_active | bool2str }}</td>
<td class="text-center"><a href="/juser/down_key/?id={{ user.id }}">下载</a></td>
<td class="text-center">
{% if user.username|key_exist %}
<a href="/juser/down_key/?id={{ user.id }}" >下载</a>
{% else %}
<span style="color: #586b7d">下载</span>
{% endif %}
</td>
<td class="text-center">
<a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a>
<a href="../user_edit/?id={{ user.id }}" class="btn btn-xs btn-info">编辑</a>

View File

@ -4,10 +4,10 @@
<ul class="nav" id="side-menu">
{% include 'nav_li_profile.html' %}
<li id="index">
<a href="/"><i class="fa fa-th-large"></i> <span class="nav-label">仪表盘</span><span class="label label-info pull-right"></span></a>
<a href="/"><i class="fa fa-dashboard"></i> <span class="nav-label">仪表盘</span><span class="label label-info pull-right"></span></a>
</li>
<li id="juser">
<a href="#"><i class="fa fa-rebel"></i> <span class="nav-label">用户管理</span><span class="fa arrow"></span></a>
<a href="#"><i class="fa fa-group"></i> <span class="nav-label">用户管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li class="group_list group_edit"><a href="/juser/group_list/">查看用户组</a></li>
<li class="group_add"><a href="/juser/group_add/">添加用户组</a></li>
@ -16,7 +16,7 @@
</ul>
</li>
<li id="jasset">
<a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<a><i class="fa fa-inbox"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li class="group_add"><a href="/jasset/group_add/">添加资产组</a></li>
<li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看资产组</a></li>
@ -44,7 +44,7 @@
<a href="/jlog/log_list/online/"><i class="fa fa-files-o"></i> <span class="nav-label">日志审计</span><span class="label label-info pull-right"></span></a>
</li>
<li id="setting">
<a href="/setting/"><i class="fa fa-files-o"></i> <span class="nav-label">设置</span><span class="label label-info pull-right"></span></a>
<a href="/setting/"><i class="fa fa-gears"></i> <span class="nav-label">设置</span><span class="label label-info pull-right"></span></a>
</li>
<li class="special_link">
<a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i> <span class="nav-label">访问官网</span></a>
@ -76,7 +76,7 @@
<a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
{# <li class="host_add host_add_multi"><a href="/jasset/host_add/">添加资产</a></li>#}
<li class="host_list host_detail host_edit"><a href="/jasset/asset_list/">查看资产<span class="label label-info pull-right">{{ host_active_num }}/{{ host_total_num}}</span></a></li>
<li class="asset_list asset_detail asset_edit"><a href="/jasset/asset_list/">查看资产<span class="label label-info pull-right">{{ host_active_num }}/{{ host_total_num}}</span></a></li>
<li class="idc_list idc_detail idc_edit"><a href="/jasset/idc_list/">查看IDC</a></li>
<li class="group_add"><a href="/jasset/group_add/">添加主机组</a></li>
<li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看主机组</a></li>

View File

@ -1 +0,0 @@
1.1