Commit b8cb6f42 authored by wangyong's avatar wangyong

Merge branch 'dev' into cmdb

parents d25e2362 a143797a
...@@ -37,6 +37,7 @@ nosetests.xml ...@@ -37,6 +37,7 @@ nosetests.xml
.mr.developer.cfg .mr.developer.cfg
.project .project
.pydevproject .pydevproject
*.log
logs/* logs/*
keys/* keys/*
jumpserver.conf jumpserver.conf
......
...@@ -19,10 +19,11 @@ import struct, fcntl, signal, socket, select ...@@ -19,10 +19,11 @@ import struct, fcntl, signal, socket, select
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
if django.get_version() != '1.6': if django.get_version() != '1.6':
django.setup() django.setup()
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir, get_asset_info, get_role
from jumpserver.api import logger, mkdir, Log, TtyLog from jumpserver.api import logger, Log, TtyLog, get_role_key
from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm
from jumpserver.settings import LOG_DIR from jumpserver.settings import LOG_DIR
from jperm.ansible_api import Command
login_user = get_object(User, username=getpass.getuser()) login_user = get_object(User, username=getpass.getuser())
VIM_FLAG = False VIM_FLAG = False
...@@ -68,23 +69,20 @@ def check_vim_status(command, ssh): ...@@ -68,23 +69,20 @@ def check_vim_status(command, ssh):
return False return False
class Tty(object): class Tty(object):
""" """
A virtual tty class A virtual tty class
一个虚拟终端类,实现连接ssh和记录日志,基类 一个虚拟终端类,实现连接ssh和记录日志,基类
""" """
def __init__(self, username, asset_name): def __init__(self, user, asset, role):
self.username = username self.username = user.username
self.asset_name = asset_name self.asset_name = asset.hostname
self.ip = None self.ip = None
self.port = 22 self.port = 22
self.channel = None self.channel = None
#self.asset = get_object(Asset, name=asset_name) self.asset = asset
#self.user = get_object(User, username=username) self.user = user
self.role = None self.role = role
self.ssh = None self.ssh = None
self.connect_info = None self.connect_info = None
self.login_type = 'ssh' self.login_type = 'ssh'
...@@ -252,6 +250,7 @@ class Tty(object): ...@@ -252,6 +250,7 @@ class Tty(object):
log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.asset_name, time_start)) log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.asset_name, time_start))
try: try:
mkdir(os.path.dirname(today_connect_log_dir), mode=0777)
mkdir(today_connect_log_dir, mode=0777) mkdir(today_connect_log_dir, mode=0777)
except OSError: except OSError:
logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir)) logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir))
...@@ -289,7 +288,10 @@ class Tty(object): ...@@ -289,7 +288,10 @@ class Tty(object):
# 2. get 映射用户 # 2. get 映射用户
# 3. get 映射用户的账号,密码或者key # 3. get 映射用户的账号,密码或者key
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_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'} asset_info = get_asset_info(self.asset)
self.connect_info = {'user': self.user, 'asset': self.asset, 'ip': asset_info.get('ip'),
'port': int(asset_info.get('port')), 'role_name': self.role.name,
'role_pass': self.role.password, 'role_key': self.role.key_path}
return self.connect_info return self.connect_info
def get_connection(self): def get_connection(self):
...@@ -303,17 +305,23 @@ class Tty(object): ...@@ -303,17 +305,23 @@ class Tty(object):
ssh.load_system_host_keys() ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try: try:
if connect_info.get('role_pass'): role_key = get_role_key(self.user, self.role)
if role_key and os.path.isfile(role_key):
try:
ssh.connect(connect_info.get('ip'), ssh.connect(connect_info.get('ip'),
port=connect_info.get('port'), port=connect_info.get('port'),
username=connect_info.get('role_name'), username=connect_info.get('role_name'),
password=connect_info.get('role_pass'), key_filename=role_key,
look_for_keys=False) look_for_keys=False)
else: self.ssh = ssh
return ssh
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
pass
ssh.connect(connect_info.get('ip'), ssh.connect(connect_info.get('ip'),
port=connect_info.get('port'), port=connect_info.get('port'),
username=connect_info.get('role_name'), username=connect_info.get('role_name'),
key_filename=connect_info.get('role_key'), password=connect_info.get('role_pass'),
look_for_keys=False) look_for_keys=False)
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException: except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
...@@ -452,7 +460,7 @@ class SshTty(Tty): ...@@ -452,7 +460,7 @@ class SshTty(Tty):
#print 'ok'+tmp+'ok' #print 'ok'+tmp+'ok'
# SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip() # SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
# SSH_TTY = '' # SSH_TTY = ''
channel.send('clear\n') # channel.send('clear\n')
# Make ssh interactive tunnel # Make ssh interactive tunnel
self.posix_shell() self.posix_shell()
...@@ -460,29 +468,124 @@ class SshTty(Tty): ...@@ -460,29 +468,124 @@ class SshTty(Tty):
channel.close() channel.close()
ssh.close() ssh.close()
def execute(self, cmd):
"""
execute cmd on the asset
执行命令
"""
pass
class Nav(object):
def __init__(self, user):
self.user = user
self.search_result = {}
self.user_perm = {}
def print_prompt(): @staticmethod
def print_nav():
""" """
Print prompt Print prompt
打印提示导航 打印提示导航
""" """
msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m msg = """\n\033[1;32m### Welcome To Use JumpServer, A Open Source System . ### \033[0m
1) Type \033[32mIP or Part IP, Host Alias or Comments \033[0m To Login. 1) Type \033[32mID\033[0m To Login.
2) Type \033[32mP/p\033[0m To Print The Servers You Available. 2) Type \033[32m/\033[0m + \033[32mIP, Host Name, Host Alias or Comments \033[0mTo Search.
3) Type \033[32mG/g\033[0m To Print The Server Groups You Available. 3) Type \033[32mP/p\033[0m To Print The Servers You Available.
4) Type \033[32mG/g(1-N)\033[0m To Print The Server Group Hosts You Available. 4) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
5) Type \033[32mE/e\033[0m To Execute Command On Several Servers. 5) Type \033[32mG/g\033[0m\033[0m + \033[32mGroup ID\033[0m To Print The Server Group You Available.
6) Type \033[32mQ/q\033[0m To Quit. 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) print textwrap.dedent(msg)
def search(self, str_r=''):
gid_pattern = re.compile(r'^g\d+$')
if not self.user_perm:
self.user_perm = get_group_user_perm(self.user)
user_asset_all = self.user_perm.get('asset').keys()
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 %-10s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
for index, asset in self.search_result.items():
asset_info = get_asset_info(asset)
role = [str(role.name) for role in self.user_perm.get('asset').get(asset).get('role')]
if asset.comment:
print '[%-3s] %-15s %-15s %-5s %-10s %s' % (index, asset.hostname, asset.ip, asset_info.get('port'),
role, asset.comment)
else:
print '[%-3s] %-15s %-15s %-5s %-10s' % (index, asset.hostname, asset.ip, asset_info.get('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 exec_cmd(self):
self.search()
while True:
print "请输入主机名、IP或ansile支持的pattern, q退出"
try:
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
if pattern == 'q':
break
else:
if not self.user_perm:
self.user_perm = get_group_user_perm(self.user)
res = gen_resource(self.user, perm=self.user_perm)
cmd = Command(res)
logger.debug(res)
for inv in cmd.inventory.get_hosts(pattern=pattern):
print inv.name
confirm_host = raw_input("\033[1;32mIs that [y/n]>:\033[0m ").strip()
if confirm_host == 'y':
while True:
print "请输入执行的命令, 按q退出"
command = raw_input("\033[1;32mCmds>:\033[0m ").strip()
if command == 'q':
break
result = cmd.run(module_name='shell', command=command, pattern=pattern)
for k, v in result.items():
if k == 'ok':
for host, output in v.items():
color_print("%s => %s" % (host, 'Ok'), 'green')
print output
print
else:
for host, output in v.items():
color_print("%s => %s" % (host, k), 'red')
color_print(output, 'red')
print
print "=" * 20
print
else:
continue
except EOFError:
print
break
def main(): def main():
""" """
...@@ -492,38 +595,60 @@ def main(): ...@@ -492,38 +595,60 @@ def main():
if not login_user: # 判断用户是否存在 if not login_user: # 判断用户是否存在
color_print(u'没有该用户,或许你是以root运行的 No that user.', exits=True) color_print(u'没有该用户,或许你是以root运行的 No that user.', exits=True)
print_prompt()
gid_pattern = re.compile(r'^g\d+$') gid_pattern = re.compile(r'^g\d+$')
nav = Nav(login_user)
nav.print_nav()
try: try:
while True: while True:
try: try:
option = raw_input("\033[1;32mOpt or IP>:\033[0m ") option = raw_input("\033[1;32mOpt or ID>:\033[0m ").strip()
except EOFError: except EOFError:
print_prompt() nav.print_nav()
continue continue
except KeyboardInterrupt: except KeyboardInterrupt:
sys.exit(0) sys.exit(0)
if option in ['P', 'p']: if option in ['P', 'p', '\n', '']:
login_user.get_asset_info(printable=True) nav.search()
continue continue
if option.startswith('/') or gid_pattern.match(option):
nav.search(option.lstrip('/'))
elif option in ['G', 'g']: elif option in ['G', 'g']:
login_user.get_asset_group_info(printable=True) nav.print_asset_group()
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)
continue continue
elif option in ['E', 'e']: elif option in ['E', 'e']:
# exec_cmd_servers(login_name) nav.exec_cmd()
pass continue
elif option in ['Q', 'q', 'exit']: elif option in ['Q', 'q', 'exit']:
sys.exit() sys.exit()
else: else:
try: try:
verify_connect(login_user, option) asset = nav.search_result[int(option)]
roles = get_role(login_user, asset)
if len(roles) > 1:
role_check = dict(zip(range(len(roles)), roles))
print role_check
for index, role in role_check.items():
print "[%s] %s" % (index, role.name)
print "输入角色ID, q退出"
try:
role_index = raw_input("\033[1;32mID>:\033[0m ").strip()
if role_index == 'q':
continue
else:
role = role_check[int(role_index)]
except IndexError:
color_print('请输入正确ID', 'red')
continue
elif len(roles) == 1:
role = roles[0]
else:
color_print('没有映射用户', 'red')
continue
ssh_tty = SshTty(login_user, asset, role)
ssh_tty.connect()
except (KeyError, ValueError):
color_print('请输入正确ID', 'red')
except ServerError, e: except ServerError, e:
color_print(e, 'red') color_print(e, 'red')
except IndexError: except IndexError:
......
sphinx-me==0.3 sphinx-me==0.3
django==1.6 django==1.6
python-ldap==2.4.19
pycrypto==2.6.1 pycrypto==2.6.1
paramiko==1.15.2 paramiko==1.15.2
ecdsa==0.13 ecdsa==0.13
...@@ -10,3 +9,8 @@ psutil==2.2.1 ...@@ -10,3 +9,8 @@ psutil==2.2.1
xlsxwriter==0.7.7 xlsxwriter==0.7.7
xlrd==0.9.4 xlrd==0.9.4
django-bootstrap-form django-bootstrap-form
tornado
ansible
pyinotify
passlib
argparse
\ No newline at end of file
...@@ -145,7 +145,7 @@ def asset_add(request): ...@@ -145,7 +145,7 @@ def asset_add(request):
asset_save = af_post.save(commit=False) asset_save = af_post.save(commit=False)
if not use_default_auth: if not use_default_auth:
password = request.POST.get('password', '') password = request.POST.get('password', '')
password_encode = CRYPTOR.encrypt(password) password_encode = password
asset_save.password = password_encode asset_save.password = password_encode
if not ip: if not ip:
asset_save.ip = hostname asset_save.ip = hostname
......
...@@ -15,11 +15,11 @@ from utils import get_rand_pass ...@@ -15,11 +15,11 @@ from utils import get_rand_pass
import os.path import os.path
API_DIR = os.path.dirname(os.path.abspath(__file__)) API_DIR = os.path.dirname(os.path.abspath(__file__))
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks') ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
class AnsibleError(StandardError): class AnsibleError(StandardError):
""" """
the base AnsibleError which contains error(required), the base AnsibleError which contains error(required),
...@@ -61,7 +61,7 @@ class MyInventory(object): ...@@ -61,7 +61,7 @@ class MyInventory(object):
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...] [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
""" """
self.resource = resource self.resource = resource
self.inventory = Inventory() self.inventory = Inventory(host_list=[])
self.gen_inventory() self.gen_inventory()
def add_group(self, hosts, groupname, groupvars=None): def add_group(self, hosts, groupname, groupvars=None):
...@@ -79,14 +79,17 @@ class MyInventory(object): ...@@ -79,14 +79,17 @@ class MyInventory(object):
for host in hosts: for host in hosts:
# set connection variables # set connection variables
hostname = host.get("hostname") hostname = host.get("hostname")
hostip = host.get('ip', hostname)
hostport = host.get("port") hostport = host.get("port")
username = host.get("username") username = host.get("username")
password = host.get("password") password = host.get("password")
ssh_key = host.get("ssh_key")
my_host = Host(name=hostname, port=hostport) my_host = Host(name=hostname, port=hostport)
my_host.set_variable('ansible_ssh_host', hostname) my_host.set_variable('ansible_ssh_host', hostip)
my_host.set_variable('ansible_ssh_port', hostport) my_host.set_variable('ansible_ssh_port', hostport)
my_host.set_variable('ansible_ssh_user', username) my_host.set_variable('ansible_ssh_user', username)
my_host.set_variable('ansible_ssh_pass', password) my_host.set_variable('ansible_ssh_pass', password)
my_host.set_variable('ansible_ssh_private_key_file', ssh_key)
# set other variables # set other variables
for key, value in host.iteritems(): for key, value in host.iteritems():
if key not in ["hostname", "port", "username", "password"]: if key not in ["hostname", "port", "username", "password"]:
...@@ -101,26 +104,58 @@ class MyInventory(object): ...@@ -101,26 +104,58 @@ class MyInventory(object):
add hosts to inventory. add hosts to inventory.
""" """
if isinstance(self.resource, list): if isinstance(self.resource, list):
self.add_group(self.resource, 'my_group') self.add_group(self.resource, 'default_group')
elif isinstance(self.resource, dict): elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.iteritems(): for groupname, hosts_and_vars in self.resource.iteritems():
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
class MyRunner(MyInventory):
"""
This is a General object for parallel execute modules.
"""
def __init__(self, *args, **kwargs):
super(MyRunner, self).__init__(*args, **kwargs)
self.results = {}
def run(self, module_name, module_args='', timeout=10, forks=10, pattern='',
sudo=False, sudo_user='root', sudo_pass=''):
"""
run module from andible ad-hoc.
module_name: ansible module_name
module_args: ansible module args
"""
hoc = Runner(module_name=module_name,
module_args=module_args,
timeout=timeout,
inventory=self.inventory,
pattern=pattern,
forks=forks,
become=sudo,
become_method='sudo',
become_user=sudo_user,
become_pass=sudo_pass
)
self.results = hoc.run()
return self.results
class Command(MyInventory): class Command(MyInventory):
""" """
this is a command object for parallel execute command. this is a command object for parallel execute command.
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs) super(Command, self).__init__(*args, **kwargs)
self.results = '' 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, pattern='*'):
""" """
run command from andible ad-hoc. run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如 command : 必须是一个需要执行的命令字符串, 比如
'uname -a' 'uname -a'
""" """
data = {}
if module_name not in ["raw", "command", "shell"]: 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'") "module_name must be of the 'raw, command, shell'")
...@@ -128,20 +163,19 @@ class Command(MyInventory): ...@@ -128,20 +163,19 @@ class Command(MyInventory):
module_args=command, module_args=command,
timeout=timeout, timeout=timeout,
inventory=self.inventory, inventory=self.inventory,
subset=group, pattern=pattern,
forks=forks forks=forks,
) )
self.results = hoc.run() self.results = hoc.run()
if self.stdout: if self.stdout:
return {"ok": self.stdout} data['ok'] = self.stdout
else:
msg = []
if self.stderr: if self.stderr:
msg.append(self.stderr) data['err'] = self.stderr
if self.dark: if self.dark:
msg.append(self.dark) data['dark'] = self.dark
return {"failed": msg}
return data
@property @property
def raw_results(self): def raw_results(self):
...@@ -183,6 +217,7 @@ class Command(MyInventory): ...@@ -183,6 +217,7 @@ class Command(MyInventory):
result = {} result = {}
all = self.results.get("contacted") all = self.results.get("contacted")
for key, value in all.iteritems(): for key, value in all.iteritems():
if value.get("stderr") or value.get("warnings"):
result[key] = { result[key] = {
"stderr": value.get("stderr"), "stderr": value.get("stderr"),
"warnings": value.get("warnings"),} "warnings": value.get("warnings"),}
...@@ -203,7 +238,7 @@ class Tasks(Command): ...@@ -203,7 +238,7 @@ class Tasks(Command):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Tasks, self).__init__(*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. run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如 command : 必须是一个需要执行的命令字符串, 比如
...@@ -214,7 +249,8 @@ class Tasks(Command): ...@@ -214,7 +249,8 @@ class Tasks(Command):
timeout=timeout, timeout=timeout,
inventory=self.inventory, inventory=self.inventory,
subset=group, subset=group,
forks=forks pattern=pattern,
forks=forks,
) )
self.results = hoc.run() self.results = hoc.run()
...@@ -368,7 +404,7 @@ class Tasks(Command): ...@@ -368,7 +404,7 @@ class Tasks(Command):
result[key] = { result[key] = {
"all_ip": setup.get("ansible_all_ipv4_addresses"), "all_ip": setup.get("ansible_all_ipv4_addresses"),
"hostname" : setup.get("ansible_hostname" ), "hostname" : setup.get("ansible_hostname"),
"default_ip": setup.get("ansible_default_ipv4").get("address"), "default_ip": setup.get("ansible_default_ipv4").get("address"),
"default_mac": setup.get("ansible_default_ipv4").get("macaddress"), "default_mac": setup.get("ansible_default_ipv4").get("macaddress"),
"product_name": setup.get("ansible_product_name"), "product_name": setup.get("ansible_product_name"),
...@@ -385,8 +421,6 @@ class Tasks(Command): ...@@ -385,8 +421,6 @@ class Tasks(Command):
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result} return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result}
class CustomAggregateStats(callbacks.AggregateStats): class CustomAggregateStats(callbacks.AggregateStats):
""" """
Holds stats about per-host activity during playbook runs. Holds stats about per-host activity during playbook runs.
...@@ -405,7 +439,6 @@ class CustomAggregateStats(callbacks.AggregateStats): ...@@ -405,7 +439,6 @@ class CustomAggregateStats(callbacks.AggregateStats):
self.results.append(runner_results) self.results.append(runner_results)
def summarize(self, host): def summarize(self, host):
""" """
Return information about a particular host Return information about a particular host
...@@ -425,7 +458,6 @@ class MyPlaybook(MyInventory): ...@@ -425,7 +458,6 @@ class MyPlaybook(MyInventory):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(MyPlaybook, self).__init__(*args, **kwargs) super(MyPlaybook, self).__init__(*args, **kwargs)
def run(self, playbook_relational_path, extra_vars=None): def run(self, playbook_relational_path, extra_vars=None):
""" """
run ansible playbook, run ansible playbook,
...@@ -464,7 +496,6 @@ class App(MyPlaybook): ...@@ -464,7 +496,6 @@ class App(MyPlaybook):
if __name__ == "__main__": if __name__ == "__main__":
pass
# resource = { # resource = {
# "group1": { # "group1": {
...@@ -472,8 +503,10 @@ if __name__ == "__main__": ...@@ -472,8 +503,10 @@ if __name__ == "__main__":
# "vars" : {"var1": "value1", "var2": "value2"}, # "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"}] # resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
# task = Tasks(resource) # task = Tasks(resource)
......
...@@ -5,20 +5,6 @@ from jasset.models import Asset, AssetGroup ...@@ -5,20 +5,6 @@ from jasset.models import Asset, AssetGroup
from juser.models import User, UserGroup from juser.models import User, UserGroup
class PermLog(models.Model):
datetime = models.DateTimeField(auto_now_add=True)
action = models.CharField(max_length=100, null=True, blank=True, default='')
results = models.CharField(max_length=1000, null=True, blank=True, default='')
is_success = models.BooleanField(default=False)
is_finish = models.BooleanField(default=False)
class SysUser(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=100)
comment = models.CharField(max_length=100, null=True, blank=True, default='')
class PermRole(models.Model): class PermRole(models.Model):
name = models.CharField(max_length=100, unique=True) name = models.CharField(max_length=100, unique=True)
comment = models.CharField(max_length=100, null=True, blank=True, default='') comment = models.CharField(max_length=100, null=True, blank=True, default='')
...@@ -32,14 +18,13 @@ class PermRole(models.Model): ...@@ -32,14 +18,13 @@ class PermRole(models.Model):
class PermRule(models.Model): class PermRule(models.Model):
date_added = models.DateTimeField(auto_now=True) 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) comment = models.CharField(max_length=100)
asset = models.ManyToManyField(Asset, related_name='perm_rule') asset = models.ManyToManyField(Asset, related_name='perm_rule')
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule') asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule')
user = models.ManyToManyField(User, related_name='perm_rule') user = models.ManyToManyField(User, related_name='perm_rule')
user_group = models.ManyToManyField(UserGroup, related_name='perm_rule') user_group = models.ManyToManyField(UserGroup, related_name='perm_rule')
role = models.ManyToManyField(PermRole, related_name='perm_rule') role = models.ManyToManyField(PermRole, related_name='perm_rule')
ssh_type = models.BooleanField()
def __unicode__(self): def __unicode__(self):
return self.name return self.name
# coding: utf-8 # coding: utf-8
from django.db.models.query import QuerySet
from jumpserver.api import * from jumpserver.api import *
import uuid import uuid
import re import re
from jumpserver.tasks import playbook_run
from jumpserver.models import Setting from jumpserver.models import Setting
from jperm.models import PermLog
from jperm.models import PermRole from jperm.models import PermRole
from jperm.models import PermRule
def get_object_list(model, id_list): def get_group_user_perm(ob):
"""根据id列表获取对象列表"""
object_list = []
for object_id in id_list:
if object_id:
object_list.extend(model.objects.filter(id=int(object_id)))
return object_list
def get_rand_file_path(base_dir=os.path.join(BASE_DIR, 'tmp')):
"""获取随机文件路径"""
filename = uuid.uuid1().hex
return os.path.join(base_dir, filename)
def get_inventory(host_group):
"""生成资产表库存清单"""
path = get_rand_file_path()
f = open(path, 'w')
for group, host_list in host_group.items():
f.write('[%s]\n' % group)
for ip in host_list:
asset = get_object(Asset, ip=ip)
if asset.use_default:
f.write('%s\n' % ip)
else:
f.write('%s ansible_ssh_port=%s ansible_ssh_user=%s ansible_ssh_pass=%s\n' %
(ip, asset.port, asset.username, CRYPTOR.decrypt(asset.password)))
f.close()
return path
def get_playbook(template, var):
"""根据playbook模板,生成playbook"""
str_playbook = open(template).read()
for k, v in var.items():
str_playbook = re.sub(r'%s' % k, v, str_playbook) # 正则来替换传入的字符
path = get_rand_file_path()
f = open(path, 'w')
f.write(str_playbook)
return path
def perm_user_api(perm_info):
""" """
用户授权api,通过调用ansible API完成用户新建等,传入参数必须如下,列表中可以是对象,也可以是用户名和ip ob为用户或用户组
perm_info = {'del': {'users': [], 获取用户、用户组授权的资产、资产组
'assets': [], return:
}, {’asset_group': {
'new': {'users': [], asset_group1: {'asset': [], 'role': [role1, role2], 'rule': [rule1, rule2]},
'assets': []}} asset_group2: {'asset: [], 'role': [role1, role2], 'rule': [rule1, rule2]},
}
'asset':{
asset1: {'role': [role1, role2], 'rule': [rule1, rule2]},
asset2: {'role': [role1, role2], 'rule': [rule1, rule2]},
}
]},
'rule':[rule1, rule2,]
}
""" """
log = PermLog(action=perm_info.get('action', '')) perm = {}
try: if isinstance(ob, User):
new_users = perm_info.get('new', {}).get('users', []) rule_all = PermRule.objects.filter(user=ob)
new_assets = perm_info.get('new', {}).get('assets', []) elif isinstance(ob, UserGroup):
del_users = perm_info.get('del', {}).get('users', []) rule_all = PermRule.objects.filter(user_group=ob)
del_assets = perm_info.get('del', {}).get('assets', [])
print new_users, new_assets
except IndexError:
raise ServerError("Error: function perm_user_api传入参数错误")
try:
new_ip = [asset.ip for asset in new_assets if isinstance(asset, Asset)]
del_ip = [asset.ip for asset in del_assets if isinstance(asset, Asset)]
new_username = [user.username for user in new_users]
del_username = [user.username for user in del_users]
except IndexError:
raise ServerError("Error: function perm_user_api传入参数类型错误")
host_group = {'new': new_ip, 'del': del_ip}
inventory = get_inventory(host_group)
the_new_users = ','.join(new_username)
the_del_users = ','.join(del_username)
playbook = get_playbook(os.path.join(BASE_DIR, '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')})
print playbook, inventory
settings = get_object(Setting, name='default')
results = playbook_run(inventory, playbook, settings)
if not results.get('failures', 1) and not results.get('unreachable', ''):
is_success = True
else: else:
is_success = False rule_all = []
log.results = results perm['rule'] = rule_all
log.is_finish = True perm_asset_group = perm['asset_group'] = {}
log.is_success = is_success perm_asset = perm['asset'] = {}
log.save() for rule in rule_all:
return results asset_groups = rule.asset_group.all()
assets = rule.asset.all()
def user_group_permed(user_group): # 获取一个规则用户授权的资产
assets = user_group.asset.all() for asset in assets:
asset_groups = user_group.asset_group.all() if perm_asset.get(asset):
perm_asset[asset].get('role', set()).update(set(rule.role.all()))
perm_asset[asset].get('rule', set()).add(rule)
else:
perm_asset[asset] = {'role': set(rule.role.all()), 'rule': set([rule])}
# 获取一个规则用户授权的资产组
for asset_group in asset_groups: for asset_group in asset_groups:
assets.extend(asset_group.asset.all()) asset_group_assets = asset_group.asset_set.all()
if perm_asset_group.get(asset_group):
return {'assets': assets, 'asset_groups': asset_groups} perm_asset_group[asset_group].get('role', set()).update(set(rule.role.all()))
perm_asset_group[asset_group].get('rule', set()).add(rule)
else:
def user_permed(user): perm_asset_group[asset_group] = {'role': set(rule.role.all()), 'rule': set([rule]),
asset_groups = [] 'asset': asset_group_assets}
assets = []
user_groups = user.group.all() # 将资产组中的资产添加到资产授权中
asset_groups.extend(user.asset_group.all()) for asset in asset_group_assets:
assets.extend(user.asset.all()) if perm_asset.get(asset):
perm_asset[asset].get('role', set()).update(perm_asset_group[asset_group].get('role', set()))
for user_group in user_groups: perm_asset[asset].get('rule', set()).update(perm_asset_group[asset_group].get('rule', set()))
asset_groups.extend(user_group_permed(user_group).get('assets', [])) else:
assets.extend((user_group_permed(user_group).get('asset_groups', []))) perm_asset[asset] = {'role': perm_asset_group[asset_group].get('role', set()),
'rule': perm_asset_group[asset_group].get('rule', set())}
return {'assets': assets, 'asset_groups': asset_groups} return perm
def _public_perm_api(info): def get_group_asset_perm(ob):
""" """
公用的用户,用户组,主机,主机组编辑修改新建调用的api,用来完成授权 ob为资产或资产组
info like that: 获取资产,资产组授权的用户,用户组
{ return:
'type': 'new_user', {’user_group': {
'user': 'a', user_group1: {'user': [], 'role': [role1, role2], 'rule': [rule1, rule2]},
'group': ['A', 'B'] user_group2: {'user: [], 'role': [role1, role2], 'rule': [rule1, rule2]},
} }
'user':{
{ user1: {'role': [role1, role2], 'rule': [rule1, rule2]},
'type': 'edit_user', user2: {'role': [role1, role2], 'rule': [rule1, rule2]},
'user': 'a',
'group': {'new': ['A'], 'del': []}
} }
]},
{ 'rule':[rule1, rule2,]
'type': 'del_user',
'user': ['a', 'b']
}
{
'type': 'edit_user_group',
'group': 'A',
'user': {'del': ['a', 'b'], 'new': ['c', 'd']}
}
{
'type': 'del_user_group',
'group': ['A']
}
{
'type': 'new_asset',
'asset': 'a',
'group': ['A', 'B']
}
{
'type': 'edit_asset',
'asset': 'a',
'group': {
'del': ['A', ['B'],
'new': ['C', ['D']]
}
}
{
'type': 'del_asset',
'asset': ['a', 'b']
}
{
'type': 'edit_asset_group',
'group': 'A',
'asset': {'new': ['a', 'b'], 'del': ['c', 'd']}
}
{
'type': 'del_asset_group',
'group': ['A', 'B']
} }
""" """
perm = {}
if isinstance(ob, Asset):
rule_all = PermRule.objects.filter(asset=ob)
elif isinstance(ob, AssetGroup):
rule_all = PermRule.objects.filter(asset_group=ob)
else:
rule_all = []
perm['rule'] = rule_all
perm_user_group = perm['user_group'] = {}
perm_user = perm['user'] = {}
for rule in rule_all:
user_groups = rule.user_group.all()
users = rule.user.all()
# 获取一个规则资产的用户
for user in users:
if perm_user.get(user):
perm_user[user].get('role', set()).update(set(rule.role.all()))
perm_user[user].get('rule', set()).add(rule)
else:
perm_user[user] = {'role': set(rule.role.all()), 'rule': set([rule])}
if info.get('type') == 'new_user': # 获取一个规则资产授权的用户组
new_assets = []
user = info.get('user')
user_groups = info.get('group')
for user_group in user_groups: for user_group in user_groups:
new_assets.extend(user_group_permed(user_group).get('assets', [])) user_group_users = user_group.user_set.all()
if perm_user_group.get(user_group):
perm_info = { perm_user_group[user_group].get('role', set()).update(set(rule.role.all()))
'action': 'new user: ' + user.name, perm_user_group[user_group].get('rule', set()).add(rule)
'new': {'users': [user], 'assets': new_assets} else:
} perm_user_group[user_group] = {'role': set(rule.role.all()), 'rule': set([rule]),
elif info.get('type') == 'edit_user': 'user': user_group_users}
new_assets = []
del_assets = [] # 将用户组中的资产添加到用户授权中
user = info.get('user') for user in user_group_users:
new_group = info.get('group').get('new') if perm_user.get(user):
del_group = info.get('group').get('del') perm_user[user].get('role', set()).update(perm_user_group[user_group].get('role', set()))
perm_user[user].get('rule', set()).update(perm_user_group[user_group].get('rule', set()))
for user_group in new_group:
new_assets.extend(user_group_permed(user_group).get('assets', []))
for user_group in del_group:
del_assets.extend((user_group_permed(user_group).get('assets', [])))
perm_info = {
'action': 'edit user: ' + user.name,
'del': {'users': [user], 'assets': del_assets},
'new': {'users': [user], 'assets': new_assets}
}
elif info.get('type') == 'del_user':
user = info.get('user')
del_assets = user_permed(user).get('assets', [])
perm_info = {
'action': 'del user: ' + user.name, 'del': {'users': [user], 'assets': del_assets},
}
elif info.get('type') == 'edit_user_group':
user_group = info.get('group')
new_users = info.get('user').get('new')
del_users = info.get('user').get('del')
assets = user_group_permed(user_group).get('assets', [])
perm_info = {
'action': 'edit user group: ' + user_group.name,
'new': {'users': new_users, 'assets': assets},
'del': {'users': del_users, 'assets': assets}
}
elif info.get('type') == 'del_user_group':
user_group = info.get('group', [])
del_users = user_group.user_set.all()
assets = user_group_permed(user_group).get('assets', [])
perm_info = {
'action': "del user group: " + user_group.name, 'del': {'users': del_users, 'assets': assets}
}
else: else:
return perm_user[user] = {'role': perm_user_group[user_group].get('role', set()),
'rule': perm_user_group[user_group].get('rule', set())}
return perm
def gen_resource(ob, ex='', perm=None):
"""
ob为用户或资产列表或资产queryset, 如果同时输入用户和资产,则获取用户在这些资产上的信息
生成MyInventory需要的 resource文件
"""
res = []
if isinstance(ob, User) and isinstance(ex, (list, QuerySet)):
if not perm:
perm = get_group_user_perm(ob)
for asset, asset_info in perm.get('asset').items():
if asset not in ex:
continue
asset_info = get_asset_info(asset)
info = {'hostname': asset.hostname, 'ip': asset.ip, 'port': asset_info.get('port', 22)}
try: try:
results = perm_user_api(perm_info) # 通过API授权或回收 role = sorted(list(perm.get('asset').get(asset).get('role')))[0]
except ServerError, e: except IndexError:
return e continue
else: info['username'] = role.name
return results info['password'] = role.password
info['ssh_key'] = get_role_key(ob, role)
res.append(info)
elif isinstance(ob, User):
if not perm:
perm = get_group_user_perm(ob)
for asset, asset_info in perm.get('asset').items():
asset_info = get_asset_info(asset)
info = {'hostname': asset.hostname, 'ip': asset.ip, 'port': asset_info.get('port', 22)}
try:
role = sorted(list(perm.get('asset').get(asset).get('role')))[0]
except IndexError:
continue
info['username'] = role.name
info['password'] = role.password
info['ssh_key'] = get_role_key(ob, role)
res.append(info)
elif isinstance(ob, (list, QuerySet)):
for asset in ob:
info = get_asset_info(asset)
res.append(info)
return res
def push_user(user, asset_groups_id): def get_object_list(model, id_list):
assets = [] """根据id列表获取对象列表"""
if not user: object_list = []
return {'error': '没有该用户'} for object_id in id_list:
for group_id in asset_groups_id: if object_id:
asset_group = get_object(AssetGroup, id=group_id) object_list.extend(model.objects.filter(id=int(object_id)))
if asset_group:
assets.extend(asset_group.asset_set.all())
perm_info = {
'action': 'Push user:' + user.username,
'new': {'users': [user], 'assets': assets}
}
results = perm_user_api(perm_info) return object_list
return results
def get_role_info(role_id, type="all"): def get_role_info(role_id, type="all"):
......
...@@ -13,11 +13,4 @@ urlpatterns = patterns('jperm.views', ...@@ -13,11 +13,4 @@ urlpatterns = patterns('jperm.views',
(r'^role/perm_role_detail/$', perm_role_detail), (r'^role/perm_role_detail/$', perm_role_detail),
(r'^role/perm_role_edit/$', perm_role_edit), (r'^role/perm_role_edit/$', perm_role_edit),
(r'^role/perm_role_push/$', perm_role_push), (r'^role/perm_role_push/$', perm_role_push),
(r'^log/$', log),
(r'^sys_user_add/$', sys_user_add),
(r'^perm_user_list/$', sys_user_list),
(r'^sys_user_del/$', sys_user_del),
(r'^sys_user_edit/$', sys_user_edit),
) )
...@@ -4,7 +4,7 @@ import random ...@@ -4,7 +4,7 @@ import random
import os.path import os.path
from paramiko.rsakey import RSAKey from paramiko.rsakey import RSAKey
from os import chmod, mkdir from jumpserver.api import mkdir
from uuid import uuid4 from uuid import uuid4
from jumpserver.settings import KEY_DIR from jumpserver.settings import KEY_DIR
...@@ -45,13 +45,13 @@ def gen_keys(): ...@@ -45,13 +45,13 @@ def gen_keys():
:return: 返回目录名(uuid) :return: 返回目录名(uuid)
""" """
key_basename = "key-" + uuid4().hex key_basename = "key-" + uuid4().hex
key_path_dir = os.path.join(KEY_DIR, key_basename) key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
mkdir(key_path_dir, 0700) mkdir(key_path_dir, 0755)
key = RSAKey.generate(2048) key = RSAKey.generate(2048)
private_key = os.path.join(key_path_dir, 'id_rsa') private_key = os.path.join(key_path_dir, 'id_rsa')
public_key = os.path.join(key_path_dir, 'id_rsa.pub') public_key = os.path.join(key_path_dir, 'id_rsa.pub')
key.write_private_key_file(private_key) key.write_private_key_file(private_key)
os.chmod(private_key, 0644)
with open(public_key, 'w') as content_file: with open(public_key, 'w') as content_file:
for data in [key.get_name(), for data in [key.get_name(),
...@@ -62,8 +62,6 @@ def gen_keys(): ...@@ -62,8 +62,6 @@ def gen_keys():
return key_path_dir return key_path_dir
if __name__ == "__main__": if __name__ == "__main__":
print gen_keys() print gen_keys()
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db.models import Q from django.db.models import Q
from jperm.perm_api import * from jperm.perm_api import *
from jperm.models import PermLog as Log
from jperm.models import SysUser
from juser.user_api import gen_ssh_key from juser.user_api import gen_ssh_key
from juser.models import User, UserGroup from juser.models import User, UserGroup
from jasset.models import Asset, AssetGroup from jasset.models import Asset, AssetGroup
from jperm.models import PermRole, PermRule from jperm.models import PermRole, PermRule
from jumpserver.models import Setting
from jperm.utils import updates_dict, gen_keys, get_rand_pass from jperm.utils import updates_dict, gen_keys, get_rand_pass
from jperm.ansible_api import Tasks from jperm.ansible_api import Tasks
from jperm.perm_api import get_role_info 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') @require_role('admin')
...@@ -89,7 +87,8 @@ def perm_rule_add(request): ...@@ -89,7 +87,8 @@ def perm_rule_add(request):
asset_groups_select = request.POST.getlist('assetgroup', []) asset_groups_select = request.POST.getlist('assetgroup', [])
roles_select = request.POST.getlist('role', []) roles_select = request.POST.getlist('role', [])
rule_name = request.POST.get('rulename') 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] assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
...@@ -115,7 +114,19 @@ def perm_rule_add(request): ...@@ -115,7 +114,19 @@ def perm_rule_add(request):
rule.asset_group = asset_groups_obj rule.asset_group = asset_groups_obj
rule.role = roles_obj rule.role = roles_obj
rule.save() 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') @require_role('admin')
...@@ -131,17 +142,69 @@ def perm_rule_edit(request): ...@@ -131,17 +142,69 @@ def perm_rule_edit(request):
rule = PermRule.objects.get(id=rule_id) rule = PermRule.objects.get(id=rule_id)
if request.method == 'GET' and rule_id: if request.method == 'GET' and rule_id:
# 渲染数据, 获取所有的rule对象 # 渲染数据, 获取所选的rule对象
users = rule.user.all() rule_comment = rule.comment
user_groups = rule.user_group.all() users_select = rule.user.all()
assets = rule.asset.all() user_groups_select = rule.user_group.all()
asset_groups = rule.asset_group.all() assets_select = rule.asset.all()
roles = rule.role.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) return my_render('jperm/perm_rule_edit.html', locals(), request)
elif request.method == 'POST' and rule_id: 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') @require_role('admin')
...@@ -201,12 +264,24 @@ def perm_role_add(request): ...@@ -201,12 +264,24 @@ def perm_role_add(request):
name = request.POST.get("role_name") name = request.POST.get("role_name")
comment = request.POST.get("role_comment") comment = request.POST.get("role_comment")
password = request.POST.get("role_password") password = request.POST.get("role_password")
encrypt_pass = CRYPTOR.encrypt(password)
# 生成随机密码,生成秘钥对 # 生成随机密码,生成秘钥对
key_path = gen_keys() 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() 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: else:
return HttpResponse(u"不支持该操作") return HttpResponse(u"不支持该操作")
...@@ -252,8 +327,12 @@ def perm_role_detail(request): ...@@ -252,8 +327,12 @@ def perm_role_detail(request):
role_info = get_role_info(role_id) role_info = get_role_info(role_id)
# 渲染数据 # 渲染数据
for key, value in role_info.iteritems(): rules = role_info.get("rules")
key = value 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) return my_render('jperm/perm_role_detail.html', locals(), request)
...@@ -265,15 +344,38 @@ def perm_role_edit(request): ...@@ -265,15 +344,38 @@ def perm_role_edit(request):
# 渲染数据 # 渲染数据
header_title, path1, path2 = "系统角色", "角色管理", "角色编辑" header_title, path1, path2 = "系统角色", "角色管理", "角色编辑"
if request.method == "GET":
role_id = request.GET.get("id")
# 渲染数据 # 渲染数据
role_id = request.GET.get("id")
role = PermRole.objects.get(id=role_id) role = PermRole.objects.get(id=role_id)
role_pass = CRYPTOR.decrypt(role.password)
if request.method == "GET":
return my_render('jperm/perm_role_edit.html', locals(), request) return my_render('jperm/perm_role_edit.html', locals(), request)
if request.method == "POST": 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') @require_role('admin')
...@@ -307,10 +409,20 @@ def perm_role_push(request): ...@@ -307,10 +409,20 @@ def perm_role_push(request):
calc_assets = set(assets_obj) | set(group_assets_obj) calc_assets = set(assets_obj) | set(group_assets_obj)
# 生成Inventory # 生成Inventory
push_resource = [{"hostname": asset.ip, push_resource = []
"port": asset.port, for asset in calc_assets:
"username": asset.username, if asset.use_default_auth:
"password": asset.password} for asset in calc_assets] 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] roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names]
...@@ -326,10 +438,13 @@ def perm_role_push(request): ...@@ -326,10 +438,13 @@ def perm_role_push(request):
task = Tasks(push_resource) task = Tasks(push_resource)
ret = {} ret = {}
ret_failed = [] ret_failed = []
if password_push:
# 因为要先建立用户,所以password 是必选项,
# 而push key是在 password也完成的情况下的 可选项
ret["password_push"] = task.add_multi_user(**role_pass) ret["password_push"] = task.add_multi_user(**role_pass)
if ret["password_push"].get("status") != "success": if ret["password_push"].get("status") != "success":
ret_failed.append(1) ret_failed.append(1)
if key_push: if key_push:
ret["key_push"] = task.push_multi_key(**role_key) ret["key_push"] = task.push_multi_key(**role_key)
if ret["key_push"].get("status") != "success": if ret["key_push"].get("status") != "success":
...@@ -341,108 +456,3 @@ def perm_role_push(request): ...@@ -341,108 +456,3 @@ def perm_role_push(request):
else: else:
return HttpResponse(u"推送系统角色: %s" % ','.join(role_names)) return HttpResponse(u"推送系统角色: %s" % ','.join(role_names))
@require_role('admin')
def perm_group_list(request):
header_title, path1, path2 = '用户组授权', '授权管理', '用户组授权'
keyword = request.GET.get('search', '')
user_groups_list = UserGroup.objects.all()
if keyword:
request = user_groups_list.filter(Q(name=keyword) | Q(comment=keyword))
user_groups_list, p, user_groups, page_range, current_page, show_first, show_end = pages(user_groups_list, request)
return my_render('jperm/perm_group_list.html', locals(), request)
@require_role('admin')
def perm_group_edit(request):
header_title, path1, path2 = '用户组授权', '授权管理', '授权更改'
user_group_id = request.GET.get('id', '')
user_group = get_object(UserGroup, id=user_group_id)
asset_all = Asset.objects.all()
asset_group_all = AssetGroup.objects.all()
asset_permed = user_group.asset.all() # 获取授权的资产对象列表
asset_group_permed = user_group.asset_group.all() # 获取授权的资产组对象列表
if request.method == 'GET' and user_group:
assets = [asset for asset in asset_all if asset not in asset_permed]
asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed]
return my_render('jperm/perm_group_edit.html', locals(), request)
elif request.method == 'POST' and user_group:
asset_id_select = request.POST.getlist('asset_select', [])
asset_group_id_select = request.POST.getlist('asset_groups_select', [])
asset_select = get_object_list(Asset, asset_id_select)
asset_group_select = get_object_list(AssetGroup, asset_group_id_select)
asset_new = list(set(asset_select) - set(asset_permed)) # 计算的得到新授权的资产对象列表
asset_del = list(set(asset_permed) - set(asset_select)) # 计算得到回收权限的资产对象列表
asset_group_new = list(set(asset_group_select) - set(asset_group_permed)) # 新授权的资产组对象列表
asset_group_del = list(set(asset_group_permed) - set(asset_group_select)) # 回收的资产组对象列表
users = user_group.user_set.all()
perm_info = {
'action': 'perm group edit: ' + user_group.name,
'del': {'users': users, 'assets': asset_del},
'new': {'users': users, 'assets': asset_new}
}
results = perm_user_api(perm_info)
unreachable_asset = []
failures_asset = []
for ip in results.get('unreachable'):
unreachable_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip)))
for ip in results.get('failures'):
failures_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip)))
failures_asset.extend(unreachable_asset) # 失败的授权要统计
for asset in failures_asset:
if asset in asset_select:
asset_select.remove(asset)
else:
asset_select.append(asset)
user_group.asset = asset_select
user_group.asset_group = asset_group_select
user_group.save() # 保存到数据库
return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json")
else:
return HttpResponse('输入错误')
def log(request):
header_title, path1, path2 = '授权记录', '授权管理', '授权记录'
log_all = Log.objects.all().order_by('-datetime')
log_all, p, logs, page_range, current_page, show_first, show_end = pages(log_all, request)
return my_render('jperm/perm_log.html', locals(), request)
def sys_user_add(request):
asset_group_all = AssetGroup.objects.all()
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
asset_groups_id = request.POST.getlist('asset_groups_select', [])
comment = request.POST.get('comment')
sys_user = SysUser(username=username, password=password, comment=comment)
sys_user.save()
gen_ssh_key(username, key_dir=os.path.join(SSH_KEY_DIR, 'sysuser'), authorized_keys=False)
results = push_user(sys_user, asset_groups_id)
return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json")
return my_render('jperm/sys_user_add.html', locals(), request)
def sys_user_list(request):
users_list = SysUser.objects.all()
users_list, p, users, page_range, current_page, show_first, show_end = pages(users_list, request)
return my_render('jperm/sys_user_list.html', locals(), request)
def sys_user_edit(request):
pass
def sys_user_del(request):
pass
...@@ -3,26 +3,27 @@ ...@@ -3,26 +3,27 @@
import os, sys, time, re import os, sys, time, re
from Crypto.Cipher import AES from Crypto.Cipher import AES
import crypt import crypt
import pwd
from binascii import b2a_hex, a2b_hex from binascii import b2a_hex, a2b_hex
import hashlib import hashlib
import datetime import datetime
import random import random
import subprocess import subprocess
from settings import * import json
import logging
from settings import *
from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
from django.template import RequestContext from django.template import RequestContext
from juser.models import User, UserGroup from juser.models import User, UserGroup
from jasset.models import Asset, AssetGroup
# from jlog.models import Log
from jlog.models import Log, TtyLog from jlog.models import Log, TtyLog
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from jasset.models import Asset, AssetGroup
from jperm.models import PermRule, PermRole
from jumpserver.models import Setting
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.core.mail import send_mail from django.core.mail import send_mail
import json
import logging
def set_log(level): def set_log(level):
...@@ -30,11 +31,15 @@ def set_log(level): ...@@ -30,11 +31,15 @@ def set_log(level):
return a log file object return a log file object
根据提示设置log打印 根据提示设置log打印
""" """
log_file = os.path.join(LOG_DIR, 'jumpserver.log')
if not os.path.isfile(log_file):
os.mknod(log_file)
os.chmod(log_file, 0777)
log_level_total = {'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARN, 'error': logging.ERROR, log_level_total = {'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARN, 'error': logging.ERROR,
'critical': logging.CRITICAL} 'critical': logging.CRITICAL}
logger_f = logging.getLogger('jumpserver') logger_f = logging.getLogger('jumpserver')
logger_f.setLevel(logging.DEBUG) logger_f.setLevel(logging.DEBUG)
fh = logging.FileHandler(os.path.join(LOG_DIR, 'jumpserver.log')) fh = logging.FileHandler(log_file)
fh.setLevel(log_level_total.get(level, logging.DEBUG)) fh.setLevel(log_level_total.get(level, logging.DEBUG))
formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s') formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter) fh.setFormatter(formatter)
...@@ -42,6 +47,63 @@ def set_log(level): ...@@ -42,6 +47,63 @@ def set_log(level):
return logger_f return logger_f
def get_asset_info(asset):
default = get_object(Setting, name='default')
info = {'hostname': asset.hostname, 'ip': asset.ip}
if asset.use_default_auth:
if default:
info['port'] = default.default_port
info['username'] = default.default_user
info['password'] = CRYPTOR.decrypt(default.default_password)
info['ssh_key'] = default.default_pri_key_path
else:
info['port'] = asset.port
info['username'] = asset.username
info['password'] = asset.password
return info
def get_role(user, asset):
roles = []
rules = PermRule.objects.filter(user=user, asset=asset)
for rule in rules:
roles.extend(list(rule.role.all()))
return roles
def get_role_key(user, role):
"""
由于role的key的权限是所有人可以读的, ansible要求为600,所以拷贝一份到特殊目录
:param user:
:param role:
:return: self key path
"""
user_role_key_dir = os.path.join(KEY_DIR, 'user')
user_role_key_path = os.path.join(user_role_key_dir, '%s_%s.pem' % (user.username, role.name))
mkdir(user_role_key_dir, mode=777)
if not os.path.isfile(user_role_key_path):
with open(os.path.join(role.key_path, 'id_rsa')) as fk:
with open(user_role_key_path, 'w') as fu:
fu.write(fk.read())
print user_role_key_path, user.username
chown(user_role_key_path, user.username)
os.chmod(user_role_key_path, 0600)
return user_role_key_path
def chown(path, user, group=''):
if not group:
group = user
try:
uid = pwd.getpwnam(user).pw_uid
gid = pwd.getpwnam(group).pw_gid
os.chown(path, uid, gid)
except KeyError:
pass
def page_list_return(total, current=1): def page_list_return(total, current=1):
""" """
page page
...@@ -159,8 +221,7 @@ class PyCrypt(object): ...@@ -159,8 +221,7 @@ class PyCrypt(object):
try: try:
plain_text = cryptor.decrypt(a2b_hex(text)) plain_text = cryptor.decrypt(a2b_hex(text))
except TypeError: except TypeError:
# raise ServerError('Decrypt password error, TYpe error.') raise ServerError('Decrypt password error, TYpe error.')
pass
return plain_text.rstrip('\0') return plain_text.rstrip('\0')
...@@ -197,9 +258,9 @@ def require_role(role='user'): ...@@ -197,9 +258,9 @@ def require_role(role='user'):
def _deco(func): def _deco(func):
def __deco(request, *args, **kwargs): def __deco(request, *args, **kwargs):
request.session['pre_url'] = request.path
if not request.user.is_authenticated(): if not request.user.is_authenticated():
return HttpResponseRedirect('/login/') return HttpResponseRedirect('/login/')
if role == 'admin': if role == 'admin':
# if request.session.get('role_id', 0) < 1: # if request.session.get('role_id', 0) < 1:
if request.user.role == 'CU': if request.user.role == 'CU':
...@@ -388,15 +449,16 @@ def bash(cmd): ...@@ -388,15 +449,16 @@ def bash(cmd):
return subprocess.call(cmd, shell=True) return subprocess.call(cmd, shell=True)
def mkdir(dir_name, username='root', mode=0755): def mkdir(dir_name, username='', mode=0755):
""" """
insure the dir exist and mode ok insure the dir exist and mode ok
目录存在,如果不存在就建立,并且权限正确 目录存在,如果不存在就建立,并且权限正确
""" """
if not os.path.isdir(dir_name): if not os.path.isdir(dir_name):
os.makedirs(dir_name) os.makedirs(dir_name)
bash("chown %s:%s '%s'" % (username, username, dir_name))
os.chmod(dir_name, mode) os.chmod(dir_name, mode)
if username:
chown(dir_name, username)
def http_success(request, msg): def http_success(request, msg):
...@@ -414,4 +476,3 @@ def my_render(template, data, request): ...@@ -414,4 +476,3 @@ def my_render(template, data, request):
CRYPTOR = PyCrypt(KEY) CRYPTOR = PyCrypt(KEY)
logger = set_log(LOG_LEVEL) logger = set_log(LOG_LEVEL)
KEY_DIR = os.path.join(BASE_DIR, 'keys')
...@@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser() ...@@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser()
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
config.read(os.path.join(BASE_DIR, 'jumpserver.conf')) 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_HOST = config.get('db', 'host')
DB_PORT = config.getint('db', 'port') DB_PORT = config.getint('db', 'port')
...@@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5 ...@@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5
# ======== Log ========== # ======== Log ==========
LOG_DIR = os.path.join(BASE_DIR, 'logs') 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') KEY = config.get('base', 'key')
URL = config.get('base', 'url') URL = config.get('base', 'url')
LOG_LEVEL = config.get('base', 'log') LOG_LEVEL = config.get('base', 'log')
......
...@@ -226,3 +226,14 @@ def ip_str_to_list(ip_str): ...@@ -226,3 +226,14 @@ def ip_str_to_list(ip_str):
ip str to list ip str to list
""" """
return ip_str.split(',') 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
...@@ -15,7 +15,6 @@ from jumpserver.api import * ...@@ -15,7 +15,6 @@ from jumpserver.api import *
from jumpserver.models import Setting from jumpserver.models import Setting
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from settings import BASE_DIR
from jlog.models import Log from jlog.models import Log
...@@ -80,18 +79,19 @@ def index_cu(request): ...@@ -80,18 +79,19 @@ def index_cu(request):
# user = get_object(User, id=user_id) # user = get_object(User, id=user_id)
login_types = {'L': 'LDAP', 'M': 'MAP'} login_types = {'L': 'LDAP', 'M': 'MAP'}
username = request.user.username username = request.user.username
posts = Asset.object.all() # TODO: need fix,liuzheng need Asset help
host_count = len(posts) # posts = Asset.object.all()
# host_count = len(posts)
new_posts = [] #
post_five = [] # new_posts = []
for post in posts: # post_five = []
if len(post_five) < 5: # for post in posts:
post_five.append(post) # if len(post_five) < 5:
else: # post_five.append(post)
new_posts.append(post_five) # else:
post_five = [] # new_posts.append(post_five)
new_posts.append(post_five) # post_five = []
# new_posts.append(post_five)
return render_to_response('index_cu.html', locals(), context_instance=RequestContext(request)) return render_to_response('index_cu.html', locals(), context_instance=RequestContext(request))
...@@ -235,7 +235,7 @@ def Login(request): ...@@ -235,7 +235,7 @@ def Login(request):
request.session['role_id'] = 1 request.session['role_id'] = 1
else: else:
request.session['role_id'] = 0 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('username', username, expires=604800)
# response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800) # response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800)
# return response # return response
...@@ -268,7 +268,7 @@ def setting(request): ...@@ -268,7 +268,7 @@ def setting(request):
if '' in [username, port] and ('' in password or '' in private_key): if '' in [username, port] and ('' in password or '' in private_key):
return HttpResponse('所填内容不能为空, 且密码和私钥填一个') return HttpResponse('所填内容不能为空, 且密码和私钥填一个')
else: 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: if private_key:
with open(private_key_path, 'w') as f: with open(private_key_path, 'w') as f:
f.write(private_key) f.write(private_key)
......
...@@ -123,27 +123,27 @@ def db_del_user(username): ...@@ -123,27 +123,27 @@ def db_del_user(username):
def gen_ssh_key(username, password='', def gen_ssh_key(username, password='',
key_dir=os.path.join(KEY_DIR, 'user'), key_dir=os.path.join(KEY_DIR, 'user'),
authorized_keys=True, home="/home", length=2048): authorized_keys=True, home="/home", length=2048):
""" """
generate a user ssh key in a property dir generate a user ssh key in a property dir
生成一个用户ssh密钥对 生成一个用户ssh密钥对
""" """
logger.debug('生成ssh key, 并设置authorized_keys')
private_key_file = os.path.join(key_dir, username) private_key_file = os.path.join(key_dir, username)
mkdir(private_key_file, username) mkdir(key_dir, mode=777)
if os.path.isfile(private_key_file): if os.path.isfile(private_key_file):
os.unlink(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)) ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
if authorized_keys: if authorized_keys:
auth_key_dir = os.path.join(home, username, '.ssh') 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') authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys')
with open(private_key_file+'.pub') as pub_f: with open(private_key_file+'.pub') as pub_f:
with open(authorized_key_file, 'w') as auth_f: with open(authorized_key_file, 'w') as auth_f:
auth_f.write(pub_f.read()) auth_f.write(pub_f.read())
os.chmod(authorized_key_file, 0600) os.chmod(authorized_key_file, 0600)
bash('chown %s:%s %s' % (username, username, authorized_key_file)) chown(authorized_key_file, username)
def server_add_user(username, password, ssh_key_pwd, ssh_key_login_need): def server_add_user(username, password, ssh_key_pwd, ssh_key_login_need):
......
...@@ -96,36 +96,37 @@ def group_edit(request): ...@@ -96,36 +96,37 @@ def group_edit(request):
if request.method == 'GET': if request.method == 'GET':
group_id = request.GET.get('id', '') group_id = request.GET.get('id', '')
user_group = get_object(UserGroup, id=group_id) # user_group = get_object(UserGroup, id=group_id)
if user_group: user_group = UserGroup.objects.get(id=group_id)
users_selected = User.objects.filter(group=user_group)
users_remain = User.objects.filter(~Q(group=user_group))
users_all = User.objects.all() users_all = User.objects.all()
users_selected = user_group.user_set.all()
users_remain = [user for user in users_all if user not in users_selected]
else: elif request.method == 'POST':
group_id = request.POST.get('group_id', '') group_id = request.POST.get('group_id', '')
group_name = request.POST.get('group_name', '') group_name = request.POST.get('group_name', '')
comment = request.POST.get('comment', '') comment = request.POST.get('comment', '')
users_selected = request.POST.getlist('users_selected') users_selected = request.POST.getlist('users_selected')
users = []
try: try:
if '' in [group_id, group_name]: if '' in [group_id, group_name]:
raise ServerError('组名不能为空') raise ServerError('组名不能为空')
user_group = get_object(UserGroup, id=group_id) if len(UserGroup.objects.filter(name=group_name)) > 1:
other_group = get_object(UserGroup, name=group_name)
if other_group and other_group.id != int(group_id):
raise ServerError(u'%s 用户组已存在' % group_name) raise ServerError(u'%s 用户组已存在' % group_name)
# add user group
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)
for user_id in users_selected:
users.extend(User.objects.filter(id=user_id))
if user_group:
user_group.update(name=group_name, comment=comment)
user_group.user_set.clear()
user_group.user_set = users
except ServerError, e: except ServerError, e:
error = e error = e
...@@ -133,8 +134,8 @@ def group_edit(request): ...@@ -133,8 +134,8 @@ def group_edit(request):
return HttpResponseRedirect('/juser/group_list/') return HttpResponseRedirect('/juser/group_list/')
else: else:
users_all = User.objects.all() users_all = User.objects.all()
users_selected = user_group.user_set.all() users_selected = User.objects.filter(group=user_group)
users_remain = [user for user in users_all if user not in users_selected] users_remain = User.objects.filter(~Q(group=user_group))
return my_render('juser/group_edit.html', locals(), request) return my_render('juser/group_edit.html', locals(), request)
......
看山是山,看水是水
看山不是山,看水不是水
看山是山,看水是水
永远年轻,永远热泪盈眶
- 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 ]
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="/juser/user_list/">{{ users.count}}</a></h1> <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> <small>All user</small>
</div> </div>
</div> </div>
...@@ -27,7 +26,6 @@ ...@@ -27,7 +26,6 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="/jasset/host_list/">{{ hosts.count }}</a></h1> <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> <small>All host</small>
</div> </div>
</div> </div>
...@@ -37,7 +35,7 @@ ...@@ -37,7 +35,7 @@
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-primary pull-right">Online</span> <span class="label label-primary pull-right">Online</span>
<h5>实时在线用户</h5> <h5>在线用户</h5>
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_users">{{ online_user | length }}</span></a></h1> <h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_users">{{ online_user | length }}</span></a></h1>
...@@ -55,7 +53,6 @@ ...@@ -55,7 +53,6 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_hosts">{{ online_host | length }}</span></a></h1> <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> <small>Connected host</small>
</div> </div>
</div> </div>
...@@ -169,7 +166,7 @@ ...@@ -169,7 +166,7 @@
</div> </div>
</div> </div>
<div class="ibox-content ibox-heading"> <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> <small><i class="fa fa-map-marker"></i> 登录次数及最近一次登录记录. </small>
</div> </div>
<div class="ibox-content inspinia-timeline"> <div class="ibox-content inspinia-timeline">
...@@ -309,14 +306,7 @@ ...@@ -309,14 +306,7 @@
</div> </div>
</div> </div>
</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 %} {% endblock %}
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
{{ af.ip|bootstrap_horizontal }} {{ af.ip|bootstrap_horizontal }}
<p class="col-sm-offset-2">Tips: 如果IP地址不填写, IP默认会设置与主机名一致</p> <p class="col-sm-offset-2">Tips: 如果IP地址不填写, IP默认会设置与主机名一致</p>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="j_group" class="col-sm-2 control-label">管理账号<span class="red-fonts"> *</span></label> <label for="j_group" class="col-sm-2 control-label">管理账号<span class="red-fonts"> *</span></label>
......
...@@ -54,17 +54,29 @@ ...@@ -54,17 +54,29 @@
<div class="col-sm-2"> <div class="col-sm-2">
<div class="radio i-checks"> <div class="radio i-checks">
<label> <label>
<<<<<<< HEAD
<input type="radio" checked="" value="no_action" id="no" name="use_default_auth" class="auth"><span> 不修改 </span>
=======
<input type="radio" checked="" value="" id="no" name="use_default_auth" class="auth"><span> 不修改 </span> <input type="radio" checked="" value="" id="no" name="use_default_auth" class="auth"><span> 不修改 </span>
>>>>>>> cmdb
</label> </label>
</div> </div>
<div class="radio i-checks"> <div class="radio i-checks">
<label> <label>
<<<<<<< HEAD
<input type="radio" id="default" name="use_default_auth" class="auth"><span> 使用默认 </span>
=======
<input type="radio" id="default" name="use_default_auth" class="auth" value="default"><span> 使用默认 </span> <input type="radio" id="default" name="use_default_auth" class="auth" value="default"><span> 使用默认 </span>
>>>>>>> cmdb
</label> </label>
</div> </div>
<div class="radio i-checks"> <div class="radio i-checks">
<label> <label>
<<<<<<< HEAD
<input type="radio" id="pass" name="use_default_auth" class="auth"><span> 用户名密码 </span>
=======
<input type="radio" id="pass" name="use_default_auth" class="auth" value="user_passwd"><span> 用户名密码 </span> <input type="radio" id="pass" name="use_default_auth" class="auth" value="user_passwd"><span> 用户名密码 </span>
>>>>>>> cmdb
</label> </label>
</div> </div>
</div> </div>
...@@ -126,6 +138,21 @@ ...@@ -126,6 +138,21 @@
</div> </div>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
<<<<<<< HEAD
$('#host_edit').click(function () {
var args = {};
var match = null;
var uuid = decodeURIComponent(location.search.substring(1));
var reg = /(?:([^&amp;]+)=([^&amp;]+))/g;
while((match = reg.exec(uuid))!==null){
args[match[1]] = match[2];
}
var ids = args['uuid'];
$('#uuid').val(ids)
});
=======
>>>>>>> cmdb
$('.auth').click(function(){ $('.auth').click(function(){
if ($(this).attr('id') == 'pass'){ if ($(this).attr('id') == 'pass'){
$('#admin_account').css('display', 'block') $('#admin_account').css('display', 'block')
......
...@@ -40,6 +40,13 @@ ...@@ -40,6 +40,13 @@
</div> </div>
</div> </div>
<div class="hr-line-dashed"></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"> <div class="form-group">
<label for="role_comment" class="col-sm-2 control-label">备注</label> <label for="role_comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8"> <div class="col-sm-8">
......
...@@ -7,6 +7,14 @@ ...@@ -7,6 +7,14 @@
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-lg-10">
<div class="ibox float-e-margins"> <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"> <div class="ibox-title">
<h5> 所有系统角色</h5> <h5> 所有系统角色</h5>
<div class="ibox-tools"> <div class="ibox-tools">
......
...@@ -67,16 +67,6 @@ ...@@ -67,16 +67,6 @@
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="row"> <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"> <div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label> <label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1"> <div class="col-sm-1">
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
</div> </div>
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<form method="post" id="userForm" class="form-horizontal" action=""> <form method="post" id="ruleForm" class="form-horizontal" action="">
{% if error %} {% if error %}
<div class="alert alert-warning text-center">{{ error }}</div> <div class="alert alert-warning text-center">{{ error }}</div>
{% endif %} {% endif %}
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<div class="alert alert-success text-center">{{ msg }}</div> <div class="alert alert-success text-center">{{ msg }}</div>
{% endif %} {% endif %}
<div class="form-group"> <div class="form-group">
<label for="username" class="col-sm-2 control-label">授权名称<span class="red-fonts">*</span></label> <label for="rulename" class="col-sm-2 control-label">授权名称<span class="red-fonts">*</span></label>
<div class="col-sm-8"> <div class="col-sm-8">
<input id="rulename" name="rulename" placeholder="Rule Name" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}> <input id="rulename" name="rulename" placeholder="Rule Name" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
</div> </div>
...@@ -48,11 +48,11 @@ ...@@ -48,11 +48,11 @@
<option value="{{ user.name }}">{{ user.name }}</option> <option value="{{ user.name }}">{{ user.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
<span class="help-block m-b-none">用户和用户组必选一个</span>
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="usergroup" class="col-sm-2 control-label">用户组<span class="red-fonts">*</span></label> <label for="usergroup" class="col-sm-2 control-label">用户组</label>
<div class="col-sm-8"> <div class="col-sm-8">
<select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user_group in user_groups %} {% for user_group in user_groups %}
...@@ -70,11 +70,11 @@ ...@@ -70,11 +70,11 @@
<option value="{{ asset.ip }}">{{ asset.ip }}</option> <option value="{{ asset.ip }}">{{ asset.ip }}</option>
{% endfor %} {% endfor %}
</select> </select>
<span class="help-block m-b-none">资产和资产组必选一个</span>
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="assetgroup" class="col-sm-2 control-label">资产组<span class="red-fonts">*</span></label> <label for="assetgroup" class="col-sm-2 control-label">资产组</label>
<div class="col-sm-8"> <div class="col-sm-8">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %} {% for asset_group in asset_groups %}
...@@ -95,51 +95,11 @@ ...@@ -95,51 +95,11 @@
</div> </div>
</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="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label> <label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8"> <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> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
...@@ -158,6 +118,37 @@ ...@@ -158,6 +118,37 @@
{% endblock %} {% endblock %}
{% block self_footer_js %} {% block self_footer_js %}
<script> <script>
$('#ruleForm').submit(function() {
var result = {};
var data = $(this).serializeArray();
$.each(data, function (i, field) {
result[field.name] = field.value;
});
if (result['user'] || result['usergroup'] || result['asset'] || result['assetgroup'] || result['rulename'] || result['role']) {
if (result['rulename'] === '') {
alert("请添加授权名称");
return false
}
if (!result['user'] && !result['usergroup']) {
alert("用户和用户组必选1个");
return false
}
if (!result['asset'] && !result['assetgroup']) {
alert("资产和资产组必选1个");
return false
}
if (!result['role']) {
alert("请填写角色");
return false
}
return true
} else {
alert("请填必选项");
return false;
}
});
$(document).ready(function(){ $(document).ready(function(){
$("input.role").click(function(){ $("input.role").click(function(){
if($("input.role[value=GA]").is( ":checked" )){ if($("input.role[value=GA]").is( ":checked" )){
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user in users %} {% 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 %} {% endfor %}
</select> </select>
</div> </div>
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user_group in user_groups %} {% 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 %} {% endfor %}
</select> </select>
</div> </div>
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %} {% 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 %} {% endfor %}
</select> </select>
</div> </div>
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %} {% 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 %} {% endfor %}
</select> </select>
</div> </div>
...@@ -89,57 +89,17 @@ ...@@ -89,57 +89,17 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
{% for role in roles %} {% 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 %} {% endfor %}
</select> </select>
</div> </div>
</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="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label> <label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8"> <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> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
......
...@@ -3,10 +3,20 @@ ...@@ -3,10 +3,20 @@
{% block content %} {% block content %}
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-lg-10">
<div class="ibox float-e-margins"> <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"> <div class="ibox-title">
<h5> 所有规则</h5> <h5> 所有规则</h5>
<div class="ibox-tools"> <div class="ibox-tools">
...@@ -55,19 +65,19 @@ ...@@ -55,19 +65,19 @@
<tr class="gradeX" id={{ rule.id }}> <tr class="gradeX" id={{ rule.id }}>
<td class="text-center"> {{ rule.name }} </td> <td class="text-center"> {{ rule.name }} </td>
<td class="text-center"> <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>
<td class="text-center"> <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>
<td class="text-center"> <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>
<td class="text-center"> <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>
<td class="text-center"> <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>
<td class="text-center"> <td class="text-center">
<a href="/jperm/perm_rule_detail/?id={{ rule.id }}" class="btn btn-xs btn-primary">详情</a> <a href="/jperm/perm_rule_detail/?id={{ rule.id }}" class="btn btn-xs btn-primary">详情</a>
......
...@@ -93,6 +93,7 @@ type="checkbox" name="selected" value="{{ group.id }}"> ...@@ -93,6 +93,7 @@ type="checkbox" name="selected" value="{{ group.id }}">
$(document).ready(function(){ $(document).ready(function(){
$('.del').click(function(){ $('.del').click(function(){
var row = $(this).closest('tr'); var row = $(this).closest('tr');
if (confirm("确定删除")) {
$.get( $.get(
$(this).attr('value'), $(this).attr('value'),
{}, {},
...@@ -101,7 +102,7 @@ type="checkbox" name="selected" value="{{ group.id }}"> ...@@ -101,7 +102,7 @@ type="checkbox" name="selected" value="{{ group.id }}">
alert(data); alert(data);
} }
) )}
}); });
$('#del_btn').click(function(){ $('#del_btn').click(function(){
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<input id="password" name="password" placeholder="Password" type="password" class="form-control"> <input id="password" name="password" placeholder="Password" type="password" class="form-control">
<span class="help-block m-b-none"> <span class="help-block m-b-none">
登陆web的密码 登陆web的密码(如不修改请留空)
</span> </span>
</div> </div>
</div> </div>
......
...@@ -64,7 +64,13 @@ ...@@ -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" 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.id | get_role }}</td>
<td class="text-center">{{ user.is_active | bool2str }}</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"> <td class="text-center">
<a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a> <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> <a href="../user_edit/?id={{ user.id }}" class="btn btn-xs btn-info">编辑</a>
......
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
<ul class="nav" id="side-menu"> <ul class="nav" id="side-menu">
{% include 'nav_li_profile.html' %} {% include 'nav_li_profile.html' %}
<li id="index"> <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>
<li id="juser"> <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"> <ul class="nav nav-second-level">
<li class="group_list group_edit"><a href="/juser/group_list/">查看用户组</a></li> <li class="group_list group_edit"><a href="/juser/group_list/">查看用户组</a></li>
<li class="group_add"><a href="/juser/group_add/">添加用户组</a></li> <li class="group_add"><a href="/juser/group_add/">添加用户组</a></li>
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</ul> </ul>
</li> </li>
<li id="jasset"> <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"> <ul class="nav nav-second-level">
<li class="group_add"><a href="/jasset/group_add/">添加资产组</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> <li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看资产组</a></li>
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
<li id="jperm"> <li id="jperm">
<a href="#"><i class="fa fa-edit"></i> <span class="nav-label">授权管理</span><span class="fa arrow"></span></a> <a href="#"><i class="fa fa-edit"></i> <span class="nav-label">授权管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li class="dept_perm_list dept_perm_edit"> <li class="rule ">
<a href="/jperm/rule/">授权规则</a> <a href="/jperm/rule/">授权规则</a>
</li> </li>
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail"> <li class="role">
<a href="/jperm/role/">系统角色</a> <a href="/jperm/role/">系统角色</a>
</li> </li>
<li class="apply_show online"><a href="/jperm/apply_show/online/">权限审批</a></li> <li class="apply_show online"><a href="/jperm/apply_show/online/">权限审批</a></li>
...@@ -44,7 +44,7 @@ ...@@ -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> <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>
<li id="setting"> <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>
<li class="special_link"> <li class="special_link">
<a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i> <span class="nav-label">访问官网</span></a> <a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i> <span class="nav-label">访问官网</span></a>
......
1.1
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment