Commit b8cb6f42 authored by wangyong's avatar wangyong

Merge branch 'dev' into cmdb

parents d25e2362 a143797a
......@@ -37,6 +37,7 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject
*.log
logs/*
keys/*
jumpserver.conf
......
......@@ -19,10 +19,11 @@ import struct, fcntl, signal, socket, select
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
if django.get_version() != '1.6':
django.setup()
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object
from jumpserver.api import logger, mkdir, Log, TtyLog
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir, get_asset_info, get_role
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 jperm.ansible_api import Command
login_user = get_object(User, username=getpass.getuser())
VIM_FLAG = False
......@@ -68,23 +69,20 @@ def check_vim_status(command, ssh):
return False
class Tty(object):
"""
A virtual tty class
一个虚拟终端类,实现连接ssh和记录日志,基类
"""
def __init__(self, username, asset_name):
self.username = username
self.asset_name = asset_name
def __init__(self, user, asset, role):
self.username = user.username
self.asset_name = asset.hostname
self.ip = None
self.port = 22
self.channel = None
#self.asset = get_object(Asset, name=asset_name)
#self.user = get_object(User, username=username)
self.role = None
self.asset = asset
self.user = user
self.role = role
self.ssh = None
self.connect_info = None
self.login_type = 'ssh'
......@@ -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))
try:
mkdir(os.path.dirname(today_connect_log_dir), mode=0777)
mkdir(today_connect_log_dir, mode=0777)
except OSError:
logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir))
......@@ -289,7 +288,10 @@ class Tty(object):
# 2. get 映射用户
# 3. get 映射用户的账号,密码或者key
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''}
self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': '', 'role_key': '/root/.ssh/id_rsa.bak'}
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
def get_connection(self):
......@@ -303,17 +305,23 @@ class Tty(object):
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
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'),
port=connect_info.get('port'),
username=connect_info.get('role_name'),
password=connect_info.get('role_pass'),
key_filename=role_key,
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'),
port=connect_info.get('port'),
username=connect_info.get('role_name'),
key_filename=connect_info.get('role_key'),
password=connect_info.get('role_pass'),
look_for_keys=False)
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
......@@ -452,7 +460,7 @@ class SshTty(Tty):
#print 'ok'+tmp+'ok'
# SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
# SSH_TTY = ''
channel.send('clear\n')
# channel.send('clear\n')
# Make ssh interactive tunnel
self.posix_shell()
......@@ -460,29 +468,124 @@ class SshTty(Tty):
channel.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
打印提示导航
"""
msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m
1) Type \033[32mIP or Part IP, Host Alias or Comments \033[0m To Login.
2) Type \033[32mP/p\033[0m To Print The Servers You Available.
3) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
4) Type \033[32mG/g(1-N)\033[0m To Print The Server Group Hosts You Available.
5) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
6) Type \033[32mQ/q\033[0m To Quit.
msg = """\n\033[1;32m### Welcome To Use JumpServer, A Open Source System . ### \033[0m
1) Type \033[32mID\033[0m To Login.
2) Type \033[32m/\033[0m + \033[32mIP, Host Name, Host Alias or Comments \033[0mTo Search.
3) Type \033[32mP/p\033[0m To Print The Servers You Available.
4) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
5) Type \033[32mG/g\033[0m\033[0m + \033[32mGroup ID\033[0m To Print The Server Group You Available.
6) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
7) Type \033[32mQ/q\033[0m To Quit.
"""
msg = """\n\033[1;32m### 欢迎使用Jumpserver开源跳板机 ### \033[0m
1) 输入 \033[32mID\033[0m 直接登录.
2) 输入 \033[32m/\033[0m + \033[32mIP, 主机名, 主机别名 or 备注 \033[0m搜索.
3) 输入 \033[32mP/p\033[0m 显示您有权限的主机.
4) 输入 \033[32mG/g\033[0m 显示您有权限的主机组.
5) 输入 \033[32mG/g\033[0m\033[0m + \033[32m组ID\033[0m 显示该组下主机.
6) 输入 \033[32mE/e\033[0m 批量执行命令.
7) 输入 \033[32mQ/q\033[0m 退出.
"""
print textwrap.dedent(msg)
def search(self, str_r=''):
gid_pattern = re.compile(r'^g\d+$')
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():
"""
......@@ -492,38 +595,60 @@ def main():
if not login_user: # 判断用户是否存在
color_print(u'没有该用户,或许你是以root运行的 No that user.', exits=True)
print_prompt()
gid_pattern = re.compile(r'^g\d+$')
nav = Nav(login_user)
nav.print_nav()
try:
while True:
try:
option = raw_input("\033[1;32mOpt or IP>:\033[0m ")
option = raw_input("\033[1;32mOpt or ID>:\033[0m ").strip()
except EOFError:
print_prompt()
nav.print_nav()
continue
except KeyboardInterrupt:
sys.exit(0)
if option in ['P', 'p']:
login_user.get_asset_info(printable=True)
if option in ['P', 'p', '\n', '']:
nav.search()
continue
if option.startswith('/') or gid_pattern.match(option):
nav.search(option.lstrip('/'))
elif option in ['G', 'g']:
login_user.get_asset_group_info(printable=True)
continue
elif gid_pattern.match(option):
gid = option[1:].strip()
asset_group = get_object(AssetGroup, id=gid)
if asset_group and asset_group.is_permed(user=login_user):
asset_group.get_asset_info(printable=True)
nav.print_asset_group()
continue
elif option in ['E', 'e']:
# exec_cmd_servers(login_name)
pass
nav.exec_cmd()
continue
elif option in ['Q', 'q', 'exit']:
sys.exit()
else:
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:
color_print(e, 'red')
except IndexError:
......
sphinx-me==0.3
django==1.6
python-ldap==2.4.19
pycrypto==2.6.1
paramiko==1.15.2
ecdsa==0.13
......@@ -10,3 +9,8 @@ psutil==2.2.1
xlsxwriter==0.7.7
xlrd==0.9.4
django-bootstrap-form
tornado
ansible
pyinotify
passlib
argparse
\ No newline at end of file
......@@ -145,7 +145,7 @@ def asset_add(request):
asset_save = af_post.save(commit=False)
if not use_default_auth:
password = request.POST.get('password', '')
password_encode = CRYPTOR.encrypt(password)
password_encode = password
asset_save.password = password_encode
if not ip:
asset_save.ip = hostname
......
......@@ -15,11 +15,11 @@ from utils import get_rand_pass
import os.path
API_DIR = os.path.dirname(os.path.abspath(__file__))
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
class AnsibleError(StandardError):
"""
the base AnsibleError which contains error(required),
......@@ -61,7 +61,7 @@ class MyInventory(object):
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
"""
self.resource = resource
self.inventory = Inventory()
self.inventory = Inventory(host_list=[])
self.gen_inventory()
def add_group(self, hosts, groupname, groupvars=None):
......@@ -79,14 +79,17 @@ class MyInventory(object):
for host in hosts:
# set connection variables
hostname = host.get("hostname")
hostip = host.get('ip', hostname)
hostport = host.get("port")
username = host.get("username")
password = host.get("password")
ssh_key = host.get("ssh_key")
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_user', username)
my_host.set_variable('ansible_ssh_pass', password)
my_host.set_variable('ansible_ssh_private_key_file', ssh_key)
# set other variables
for key, value in host.iteritems():
if key not in ["hostname", "port", "username", "password"]:
......@@ -101,26 +104,58 @@ class MyInventory(object):
add hosts to inventory.
"""
if isinstance(self.resource, list):
self.add_group(self.resource, 'my_group')
self.add_group(self.resource, 'default_group')
elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.iteritems():
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
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):
"""
this is a command object for parallel execute command.
"""
def __init__(self, *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.
command : 必须是一个需要执行的命令字符串, 比如
'uname -a'
"""
data = {}
if module_name not in ["raw", "command", "shell"]:
raise CommandValueError("module_name",
"module_name must be of the 'raw, command, shell'")
......@@ -128,20 +163,19 @@ class Command(MyInventory):
module_args=command,
timeout=timeout,
inventory=self.inventory,
subset=group,
forks=forks
pattern=pattern,
forks=forks,
)
self.results = hoc.run()
if self.stdout:
return {"ok": self.stdout}
else:
msg = []
data['ok'] = self.stdout
if self.stderr:
msg.append(self.stderr)
data['err'] = self.stderr
if self.dark:
msg.append(self.dark)
return {"failed": msg}
data['dark'] = self.dark
return data
@property
def raw_results(self):
......@@ -183,6 +217,7 @@ class Command(MyInventory):
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
if value.get("stderr") or value.get("warnings"):
result[key] = {
"stderr": value.get("stderr"),
"warnings": value.get("warnings"),}
......@@ -203,7 +238,7 @@ class Tasks(Command):
def __init__(self, *args, **kwargs):
super(Tasks, self).__init__(*args, **kwargs)
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='my_group'):
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='default_group', pattern='*'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如
......@@ -214,7 +249,8 @@ class Tasks(Command):
timeout=timeout,
inventory=self.inventory,
subset=group,
forks=forks
pattern=pattern,
forks=forks,
)
self.results = hoc.run()
......@@ -368,7 +404,7 @@ class Tasks(Command):
result[key] = {
"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_mac": setup.get("ansible_default_ipv4").get("macaddress"),
"product_name": setup.get("ansible_product_name"),
......@@ -385,8 +421,6 @@ class Tasks(Command):
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result}
class CustomAggregateStats(callbacks.AggregateStats):
"""
Holds stats about per-host activity during playbook runs.
......@@ -405,7 +439,6 @@ class CustomAggregateStats(callbacks.AggregateStats):
self.results.append(runner_results)
def summarize(self, host):
"""
Return information about a particular host
......@@ -425,7 +458,6 @@ class MyPlaybook(MyInventory):
def __init__(self, *args, **kwargs):
super(MyPlaybook, self).__init__(*args, **kwargs)
def run(self, playbook_relational_path, extra_vars=None):
"""
run ansible playbook,
......@@ -464,7 +496,6 @@ class App(MyPlaybook):
if __name__ == "__main__":
pass
# resource = {
# "group1": {
......@@ -472,8 +503,10 @@ if __name__ == "__main__":
# "vars" : {"var1": "value1", "var2": "value2"},
# },
# }
# command = Command(resource)
# print command.run("who", group="group1")
resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902"}]
command = Command(resource)
print command.run("who")
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
# task = Tasks(resource)
......
......@@ -5,20 +5,6 @@ from jasset.models import Asset, AssetGroup
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):
name = models.CharField(max_length=100, unique=True)
comment = models.CharField(max_length=100, null=True, blank=True, default='')
......@@ -32,14 +18,13 @@ class PermRole(models.Model):
class PermRule(models.Model):
date_added = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
name = models.CharField(max_length=100, unique=True)
comment = models.CharField(max_length=100)
asset = models.ManyToManyField(Asset, related_name='perm_rule')
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule')
user = models.ManyToManyField(User, related_name='perm_rule')
user_group = models.ManyToManyField(UserGroup, related_name='perm_rule')
role = models.ManyToManyField(PermRole, related_name='perm_rule')
ssh_type = models.BooleanField()
def __unicode__(self):
return self.name
# coding: utf-8
from django.db.models.query import QuerySet
from jumpserver.api import *
import uuid
import re
from jumpserver.tasks import playbook_run
from jumpserver.models import Setting
from jperm.models import PermLog
from jperm.models import PermRole
from jperm.models import PermRule
def get_object_list(model, id_list):
"""根据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):
def get_group_user_perm(ob):
"""
用户授权api,通过调用ansible API完成用户新建等,传入参数必须如下,列表中可以是对象,也可以是用户名和ip
perm_info = {'del': {'users': [],
'assets': [],
},
'new': {'users': [],
'assets': []}}
ob为用户或用户组
获取用户、用户组授权的资产、资产组
return:
{’asset_group': {
asset_group1: {'asset': [], 'role': [role1, role2], 'rule': [rule1, rule2]},
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', ''))
try:
new_users = perm_info.get('new', {}).get('users', [])
new_assets = perm_info.get('new', {}).get('assets', [])
del_users = perm_info.get('del', {}).get('users', [])
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
perm = {}
if isinstance(ob, User):
rule_all = PermRule.objects.filter(user=ob)
elif isinstance(ob, UserGroup):
rule_all = PermRule.objects.filter(user_group=ob)
else:
is_success = False
log.results = results
log.is_finish = True
log.is_success = is_success
log.save()
return results
def user_group_permed(user_group):
assets = user_group.asset.all()
asset_groups = user_group.asset_group.all()
rule_all = []
perm['rule'] = rule_all
perm_asset_group = perm['asset_group'] = {}
perm_asset = perm['asset'] = {}
for rule in rule_all:
asset_groups = rule.asset_group.all()
assets = rule.asset.all()
# 获取一个规则用户授权的资产
for asset in assets:
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:
assets.extend(asset_group.asset.all())
return {'assets': assets, 'asset_groups': asset_groups}
def user_permed(user):
asset_groups = []
assets = []
user_groups = user.group.all()
asset_groups.extend(user.asset_group.all())
assets.extend(user.asset.all())
for user_group in user_groups:
asset_groups.extend(user_group_permed(user_group).get('assets', []))
assets.extend((user_group_permed(user_group).get('asset_groups', [])))
return {'assets': assets, 'asset_groups': asset_groups}
asset_group_assets = asset_group.asset_set.all()
if perm_asset_group.get(asset_group):
perm_asset_group[asset_group].get('role', set()).update(set(rule.role.all()))
perm_asset_group[asset_group].get('rule', set()).add(rule)
else:
perm_asset_group[asset_group] = {'role': set(rule.role.all()), 'rule': set([rule]),
'asset': asset_group_assets}
# 将资产组中的资产添加到资产授权中
for asset in asset_group_assets:
if perm_asset.get(asset):
perm_asset[asset].get('role', set()).update(perm_asset_group[asset_group].get('role', set()))
perm_asset[asset].get('rule', set()).update(perm_asset_group[asset_group].get('rule', set()))
else:
perm_asset[asset] = {'role': perm_asset_group[asset_group].get('role', set()),
'rule': perm_asset_group[asset_group].get('rule', set())}
return perm
def _public_perm_api(info):
def get_group_asset_perm(ob):
"""
公用的用户,用户组,主机,主机组编辑修改新建调用的api,用来完成授权
info like that:
{
'type': 'new_user',
'user': 'a',
'group': ['A', 'B']
ob为资产或资产组
获取资产,资产组授权的用户,用户组
return:
{’user_group': {
user_group1: {'user': [], 'role': [role1, role2], 'rule': [rule1, rule2]},
user_group2: {'user: [], 'role': [role1, role2], 'rule': [rule1, rule2]},
}
{
'type': 'edit_user',
'user': 'a',
'group': {'new': ['A'], 'del': []}
'user':{
user1: {'role': [role1, role2], 'rule': [rule1, rule2]},
user2: {'role': [role1, role2], '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']
]},
'rule':[rule1, rule2,]
}
"""
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:
new_assets.extend(user_group_permed(user_group).get('assets', []))
perm_info = {
'action': 'new user: ' + user.name,
'new': {'users': [user], 'assets': new_assets}
}
elif info.get('type') == 'edit_user':
new_assets = []
del_assets = []
user = info.get('user')
new_group = info.get('group').get('new')
del_group = info.get('group').get('del')
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}
}
user_group_users = user_group.user_set.all()
if perm_user_group.get(user_group):
perm_user_group[user_group].get('role', set()).update(set(rule.role.all()))
perm_user_group[user_group].get('rule', set()).add(rule)
else:
perm_user_group[user_group] = {'role': set(rule.role.all()), 'rule': set([rule]),
'user': user_group_users}
# 将用户组中的资产添加到用户授权中
for user in user_group_users:
if perm_user.get(user):
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()))
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:
results = perm_user_api(perm_info) # 通过API授权或回收
except ServerError, e:
return e
else:
return results
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, 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):
assets = []
if not user:
return {'error': '没有该用户'}
for group_id in asset_groups_id:
asset_group = get_object(AssetGroup, id=group_id)
if asset_group:
assets.extend(asset_group.asset_set.all())
perm_info = {
'action': 'Push user:' + user.username,
'new': {'users': [user], 'assets': assets}
}
def get_object_list(model, id_list):
"""根据id列表获取对象列表"""
object_list = []
for object_id in id_list:
if object_id:
object_list.extend(model.objects.filter(id=int(object_id)))
results = perm_user_api(perm_info)
return results
return object_list
def get_role_info(role_id, type="all"):
......
......@@ -13,11 +13,4 @@ urlpatterns = patterns('jperm.views',
(r'^role/perm_role_detail/$', perm_role_detail),
(r'^role/perm_role_edit/$', perm_role_edit),
(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
import os.path
from paramiko.rsakey import RSAKey
from os import chmod, mkdir
from jumpserver.api import mkdir
from uuid import uuid4
from jumpserver.settings import KEY_DIR
......@@ -45,13 +45,13 @@ def gen_keys():
:return: 返回目录名(uuid)
"""
key_basename = "key-" + uuid4().hex
key_path_dir = os.path.join(KEY_DIR, key_basename)
mkdir(key_path_dir, 0700)
key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
mkdir(key_path_dir, 0755)
key = RSAKey.generate(2048)
private_key = os.path.join(key_path_dir, 'id_rsa')
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
key.write_private_key_file(private_key)
os.chmod(private_key, 0644)
with open(public_key, 'w') as content_file:
for data in [key.get_name(),
......@@ -62,8 +62,6 @@ def gen_keys():
return key_path_dir
if __name__ == "__main__":
print gen_keys()
......
# -*- coding: utf-8 -*-
from django.db.models import Q
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.models import User, UserGroup
from jasset.models import Asset, AssetGroup
from jperm.models import PermRole, PermRule
from jumpserver.models import Setting
from jperm.utils import updates_dict, gen_keys, get_rand_pass
from jperm.ansible_api import Tasks
from jperm.perm_api import get_role_info
from jumpserver.api import my_render, get_object
from jumpserver.api import my_render, get_object, CRYPTOR
@require_role('admin')
......@@ -89,7 +87,8 @@ def perm_rule_add(request):
asset_groups_select = request.POST.getlist('assetgroup', [])
roles_select = request.POST.getlist('role', [])
rule_name = request.POST.get('rulename')
rule_comment = request.POST.get('comment')
rule_comment = request.POST.get('rule_comment')
rule_ssh_key = request.POST.get("use_publicKey")
# 获取需要授权的主机列表
assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
......@@ -115,7 +114,19 @@ def perm_rule_add(request):
rule.asset_group = asset_groups_obj
rule.role = roles_obj
rule.save()
return HttpResponse(u"添加授权规则:%s" % rule.name)
msg = u"添加授权规则:%s" % rule.name
# 渲染数据
header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
rules_list = PermRule.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
rules_list = rules_list.filter(Q(name=keyword))
rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin')
......@@ -131,17 +142,69 @@ def perm_rule_edit(request):
rule = PermRule.objects.get(id=rule_id)
if request.method == 'GET' and rule_id:
# 渲染数据, 获取所有的rule对象
users = rule.user.all()
user_groups = rule.user_group.all()
assets = rule.asset.all()
asset_groups = rule.asset_group.all()
roles = rule.role.all()
# 渲染数据, 获取所选的rule对象
rule_comment = rule.comment
users_select = rule.user.all()
user_groups_select = rule.user_group.all()
assets_select = rule.asset.all()
asset_groups_select = rule.asset_group.all()
roles_select = rule.role.all()
users = User.objects.all()
user_groups = UserGroup.objects.all()
assets = Asset.objects.all()
asset_groups = AssetGroup.objects.all()
roles = PermRole.objects.all()
return my_render('jperm/perm_rule_edit.html', locals(), request)
elif request.method == 'POST' and rule_id:
return HttpResponse("uncompleted")
# 获取用户选择的 用户,用户组,资产,资产组,用户角色
rule_name = request.POST.get('rule_name')
rule_comment = request.POST.get("rule_comment")
users_select = request.POST.getlist('user', [])
user_groups_select = request.POST.getlist('usergroup', [])
assets_select = request.POST.getlist('asset', [])
asset_groups_select = request.POST.getlist('assetgroup', [])
roles_select = request.POST.getlist('role', [])
# 获取需要授权的主机列表
assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
asset_groups_obj = [AssetGroup.objects.get(name=group) for group in asset_groups_select]
group_assets_obj = [asset for asset in [group.asset_set.all() for group in asset_groups_obj]]
calc_assets = set(group_assets_obj) | set(assets_obj)
# 获取需要授权的用户列表
users_obj = [User.objects.get(name=user) for user in users_select]
user_groups_obj = [UserGroup.objects.get(name=group) for group in user_groups_select]
group_users_obj = [user for user in [group.user_set.all() for group in user_groups_obj]]
calc_users = set(group_users_obj) | set(users_obj)
# 获取授予的角色列表
roles_obj = [PermRole.objects.get(name=role) for role in roles_select]
# 仅授权成功的,写回数据库(授权规则,用户,用户组,资产,资产组,用户角色)
rule.user = users_obj
rule.usergroup = user_groups_obj
rule.asset = assets_obj
rule.asset_group = asset_groups_obj
rule.role = roles_obj
rule.name = rule_name
rule.comment = rule.comment
rule.save()
msg = u"更新授权规则:%s" % rule.name
# 渲染数据
header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
rules_list = PermRule.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
rules_list = rules_list.filter(Q(name=keyword))
rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin')
......@@ -201,12 +264,24 @@ def perm_role_add(request):
name = request.POST.get("role_name")
comment = request.POST.get("role_comment")
password = request.POST.get("role_password")
encrypt_pass = CRYPTOR.encrypt(password)
# 生成随机密码,生成秘钥对
key_path = gen_keys()
role = PermRole(name=name, comment=comment, password=password, key_path=key_path)
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
role.save()
return HttpResponse(u"添加角色: %s" % name)
msg = u"添加角色: %s" % name
# 渲染 刷新数据
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
roles_list = PermRole.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
roles_list = roles_list.filter(Q(name=keyword))
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
return my_render('jperm/perm_role_list.html', locals(), request)
else:
return HttpResponse(u"不支持该操作")
......@@ -252,8 +327,12 @@ def perm_role_detail(request):
role_info = get_role_info(role_id)
# 渲染数据
for key, value in role_info.iteritems():
key = value
rules = role_info.get("rules")
assets = role_info.get("assets")
asset_groups = role_info.get("asset_groups")
users = role_info.get("users")
user_groups = role_info.get("user_groups")
return my_render('jperm/perm_role_detail.html', locals(), request)
......@@ -265,15 +344,38 @@ def perm_role_edit(request):
# 渲染数据
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_pass = CRYPTOR.decrypt(role.password)
if request.method == "GET":
return my_render('jperm/perm_role_edit.html', locals(), request)
if request.method == "POST":
return HttpResponse(u"未实现")
# 获取 POST 数据
role_name = request.POST.get("role_name")
role_password = request.POST.get("role_password")
encrypt_role_pass = CRYPTOR.encrypt(role_password)
role_comment = request.POST.get("role_comment")
# 写入数据库
role.name = role_name
role.password = encrypt_role_pass
role.comment = role_comment
role.save()
msg = u"更新系统角色: %s" % role.name
# 渲染 刷新数据
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
roles_list = PermRole.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
roles_list = roles_list.filter(Q(name=keyword))
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
return my_render('jperm/perm_role_list.html', locals(), request)
@require_role('admin')
......@@ -307,10 +409,20 @@ def perm_role_push(request):
calc_assets = set(assets_obj) | set(group_assets_obj)
# 生成Inventory
push_resource = [{"hostname": asset.ip,
"port": asset.port,
"username": asset.username,
"password": asset.password} for asset in calc_assets]
push_resource = []
for asset in calc_assets:
if asset.use_default_auth:
username = Setting.default_user
password = Setting.default_password
port = Setting.default_port
else:
username = asset.username
password = asset.password
port = asset.port
push_resource.append({"hostname": asset.ip,
"port": port,
"username": username,
"password": password})
# 获取角色的推送方式,以及推送需要的信息
roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names]
......@@ -326,10 +438,13 @@ def perm_role_push(request):
task = Tasks(push_resource)
ret = {}
ret_failed = []
if password_push:
# 因为要先建立用户,所以password 是必选项,
# 而push key是在 password也完成的情况下的 可选项
ret["password_push"] = task.add_multi_user(**role_pass)
if ret["password_push"].get("status") != "success":
ret_failed.append(1)
if key_push:
ret["key_push"] = task.push_multi_key(**role_key)
if ret["key_push"].get("status") != "success":
......@@ -341,108 +456,3 @@ def perm_role_push(request):
else:
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 @@
import os, sys, time, re
from Crypto.Cipher import AES
import crypt
import pwd
from binascii import b2a_hex, a2b_hex
import hashlib
import datetime
import random
import subprocess
from settings import *
import json
import logging
from settings import *
from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.http import HttpResponse, Http404
from django.template import RequestContext
from juser.models import User, UserGroup
from jasset.models import Asset, AssetGroup
# from jlog.models import Log
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.shortcuts import render_to_response
from django.core.mail import send_mail
import json
import logging
def set_log(level):
......@@ -30,11 +31,15 @@ def set_log(level):
return a log file object
根据提示设置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,
'critical': logging.CRITICAL}
logger_f = logging.getLogger('jumpserver')
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))
formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
......@@ -42,6 +47,63 @@ def set_log(level):
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):
"""
page
......@@ -159,8 +221,7 @@ class PyCrypt(object):
try:
plain_text = cryptor.decrypt(a2b_hex(text))
except TypeError:
# raise ServerError('Decrypt password error, TYpe error.')
pass
raise ServerError('Decrypt password error, TYpe error.')
return plain_text.rstrip('\0')
......@@ -197,9 +258,9 @@ def require_role(role='user'):
def _deco(func):
def __deco(request, *args, **kwargs):
request.session['pre_url'] = request.path
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
if role == 'admin':
# if request.session.get('role_id', 0) < 1:
if request.user.role == 'CU':
......@@ -388,15 +449,16 @@ def bash(cmd):
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
目录存在,如果不存在就建立,并且权限正确
"""
if not os.path.isdir(dir_name):
os.makedirs(dir_name)
bash("chown %s:%s '%s'" % (username, username, dir_name))
os.chmod(dir_name, mode)
if username:
chown(dir_name, username)
def http_success(request, msg):
......@@ -414,4 +476,3 @@ def my_render(template, data, request):
CRYPTOR = PyCrypt(KEY)
logger = set_log(LOG_LEVEL)
KEY_DIR = os.path.join(BASE_DIR, 'keys')
......@@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser()
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
config.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
KEY_DIR = os.path.join(BASE_DIR, 'keys')
KEY_DIR = os.path.join(BASE_DIR, 'role_keys')
DB_HOST = config.get('db', 'host')
DB_PORT = config.getint('db', 'port')
......@@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5
# ======== Log ==========
LOG_DIR = os.path.join(BASE_DIR, 'logs')
SSH_KEY_DIR = os.path.join(BASE_DIR, 'role_keys')
SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys/role_keys')
KEY = config.get('base', 'key')
URL = config.get('base', 'url')
LOG_LEVEL = config.get('base', 'log')
......
......@@ -226,3 +226,14 @@ def ip_str_to_list(ip_str):
ip str to list
"""
return ip_str.split(',')
@register.filter(name='key_exist')
def key_exist(username):
"""
ssh key is exist or not
"""
if os.path.isfile(os.path.join(KEY_DIR, 'user', username)):
return True
else:
return False
......@@ -15,7 +15,6 @@ from jumpserver.api import *
from jumpserver.models import Setting
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from settings import BASE_DIR
from jlog.models import Log
......@@ -80,18 +79,19 @@ def index_cu(request):
# user = get_object(User, id=user_id)
login_types = {'L': 'LDAP', 'M': 'MAP'}
username = request.user.username
posts = Asset.object.all()
host_count = len(posts)
new_posts = []
post_five = []
for post in posts:
if len(post_five) < 5:
post_five.append(post)
else:
new_posts.append(post_five)
post_five = []
new_posts.append(post_five)
# TODO: need fix,liuzheng need Asset help
# posts = Asset.object.all()
# host_count = len(posts)
#
# new_posts = []
# post_five = []
# for post in posts:
# if len(post_five) < 5:
# post_five.append(post)
# else:
# new_posts.append(post_five)
# post_five = []
# new_posts.append(post_five)
return render_to_response('index_cu.html', locals(), context_instance=RequestContext(request))
......@@ -235,7 +235,7 @@ def Login(request):
request.session['role_id'] = 1
else:
request.session['role_id'] = 0
return HttpResponseRedirect(request.GET.get('next', '/'), )
return HttpResponseRedirect(request.session.get('pre_url', '/'))
# response.set_cookie('username', username, expires=604800)
# response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800)
# return response
......@@ -268,7 +268,7 @@ def setting(request):
if '' in [username, port] and ('' in password or '' in private_key):
return HttpResponse('所填内容不能为空, 且密码和私钥填一个')
else:
private_key_path = os.path.join(BASE_DIR, 'role_keys', 'default', 'default_private_key.pem')
private_key_path = os.path.join(BASE_DIR, 'keys/role_keys', 'default', 'default_private_key.pem')
if private_key:
with open(private_key_path, 'w') as f:
f.write(private_key)
......
......@@ -123,27 +123,27 @@ def db_del_user(username):
def gen_ssh_key(username, password='',
key_dir=os.path.join(KEY_DIR, 'user'),
authorized_keys=True, home="/home", length=2048):
"""
generate a user ssh key in a property dir
生成一个用户ssh密钥对
"""
logger.debug('生成ssh key, 并设置authorized_keys')
private_key_file = os.path.join(key_dir, username)
mkdir(private_key_file, username)
mkdir(key_dir, mode=777)
if os.path.isfile(private_key_file):
os.unlink(private_key_file)
ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
if authorized_keys:
auth_key_dir = os.path.join(home, username, '.ssh')
mkdir(auth_key_dir, username, mode=0700)
mkdir(auth_key_dir, mode=0700)
authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys')
with open(private_key_file+'.pub') as pub_f:
with open(authorized_key_file, 'w') as auth_f:
auth_f.write(pub_f.read())
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):
......
......@@ -96,36 +96,37 @@ def group_edit(request):
if request.method == 'GET':
group_id = request.GET.get('id', '')
user_group = get_object(UserGroup, id=group_id)
if user_group:
# user_group = get_object(UserGroup, id=group_id)
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_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_name = request.POST.get('group_name', '')
comment = request.POST.get('comment', '')
users_selected = request.POST.getlist('users_selected')
users = []
try:
if '' in [group_id, group_name]:
raise ServerError('组名不能为空')
user_group = get_object(UserGroup, id=group_id)
other_group = get_object(UserGroup, name=group_name)
if other_group and other_group.id != int(group_id):
if len(UserGroup.objects.filter(name=group_name)) > 1:
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:
error = e
......@@ -133,8 +134,8 @@ def group_edit(request):
return HttpResponseRedirect('/juser/group_list/')
else:
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]
users_selected = User.objects.filter(group=user_group)
users_remain = User.objects.filter(~Q(group=user_group))
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 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="/juser/user_list/">{{ users.count}}</a></h1>
{# <div class="stat-percent font-bold text-success">{{ percent_user }} <i class="fa fa-bolt"></i></div>#}
<small>All user</small>
</div>
</div>
......@@ -27,7 +26,6 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="/jasset/host_list/">{{ hosts.count }}</a></h1>
{# <div class="stat-percent font-bold text-info">{{ percent_host }} <i class="fa fa-level-up"></i></div>#}
<small>All host</small>
</div>
</div>
......@@ -37,7 +35,7 @@
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label label-primary pull-right">Online</span>
<h5>实时在线用户</h5>
<h5>在线用户</h5>
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_users">{{ online_user | length }}</span></a></h1>
......@@ -55,7 +53,6 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_hosts">{{ online_host | length }}</span></a></h1>
{# <div class="stat-percent font-bold text-danger">{{ percent_online_host }} <i class="fa fa-level-down"></i></div>#}
<small>Connected host</small>
</div>
</div>
......@@ -169,7 +166,7 @@
</div>
</div>
<div class="ibox-content ibox-heading">
<h3><i class="fa fa-user"></i> 一周Top10资产 </h3>
<h3><i class="fa fa-inbox"></i> 一周Top10资产 </h3>
<small><i class="fa fa-map-marker"></i> 登录次数及最近一次登录记录. </small>
</div>
<div class="ibox-content inspinia-timeline">
......@@ -309,14 +306,7 @@
</div>
</div>
</div>
<!--</div>-->
<!--<div class="col-xm-6" id="top10" style="width:50%;height:400px;"></div>-->
<!--<div class="col-xm-6" id="usertop10" style="width:50%;height:400px;"></div>-->
<!--<div class="row">-->
<!--<div class="col-lg-6" id="hosttop10" style="width:50%;height:400px; margin-top: 20px"></div>-->
<!--</div>-->
</div>
</div>
</div>
{% endblock %}
......
......@@ -48,6 +48,7 @@
{{ af.ip|bootstrap_horizontal }}
<p class="col-sm-offset-2">Tips: 如果IP地址不填写, IP默认会设置与主机名一致</p>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">管理账号<span class="red-fonts"> *</span></label>
......
......@@ -54,17 +54,29 @@
<div class="col-sm-2">
<div class="radio i-checks">
<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>
>>>>>>> cmdb
</label>
</div>
<div class="radio i-checks">
<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>
>>>>>>> cmdb
</label>
</div>
<div class="radio i-checks">
<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>
>>>>>>> cmdb
</label>
</div>
</div>
......@@ -126,6 +138,21 @@
</div>
<script>
$(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(){
if ($(this).attr('id') == 'pass'){
$('#admin_account').css('display', 'block')
......
......@@ -40,6 +40,13 @@
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="role_password_label" class="col-sm-2 control-label">角色密码<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="role_password" name="role_password" type="password" class="form-control" value="{{ role_pass }}">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="role_comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
......
......@@ -7,6 +7,14 @@
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<div class="ibox-title">
<h5> 所有系统角色</h5>
<div class="ibox-tools">
......
......@@ -67,16 +67,6 @@
</div>
<div class="hr-line-dashed"></div>
<div class="row">
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1">
......
......@@ -26,7 +26,7 @@
</div>
</div>
<div class="ibox-content">
<form method="post" id="userForm" class="form-horizontal" action="">
<form method="post" id="ruleForm" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
......@@ -34,7 +34,7 @@
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<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">
<input id="rulename" name="rulename" placeholder="Rule Name" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
</div>
......@@ -48,11 +48,11 @@
<option value="{{ user.name }}">{{ user.name }}</option>
{% endfor %}
</select>
<span class="help-block m-b-none">用户和用户组必选一个</span>
</div>
</div>
<div class="hr-line-dashed"></div>
<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">
<select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user_group in user_groups %}
......@@ -70,11 +70,11 @@
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
{% endfor %}
</select>
<span class="help-block m-b-none">资产和资产组必选一个</span>
</div>
</div>
<div class="hr-line-dashed"></div>
<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">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %}
......@@ -95,51 +95,11 @@
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="0" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_password" style="display: none">
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_publicKey" name="use_publicKey">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_publicKey" style="display: none">
<label class="col-sm-1 control-label"> 秘钥<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="Rule Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
<input id="rule_comment" name="rule_comment" placeholder="Rule Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
</div>
</div>
<div class="hr-line-dashed"></div>
......@@ -158,6 +118,37 @@
{% endblock %}
{% block self_footer_js %}
<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(){
$("input.role").click(function(){
if($("input.role[value=GA]").is( ":checked" )){
......
......@@ -45,7 +45,7 @@
<div class="col-sm-8">
<select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user in users %}
<option value="{{ user.name }}">{{ user.name }}</option>
<option value="{{ user.name }}" {% if user in users_select %} selected {% endif %}>{{ user.name }}</option>
{% endfor %}
</select>
</div>
......@@ -56,7 +56,7 @@
<div class="col-sm-8">
<select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user_group in user_groups %}
<option value="{{ user_group.name }}">{{ user_group.name }}</option>
<option value="{{ user_group.name }}"{% if user_group in users_groups_select %} selected {% endif %}>{{ user_group.name }}</option>
{% endfor %}
</select>
</div>
......@@ -67,7 +67,7 @@
<div class="col-sm-8">
<select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
<option value="{{ asset.ip }}"{% if asset in assets_select %} selected {% endif %}>{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
......@@ -78,7 +78,7 @@
<div class="col-sm-8">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %}
<option value="{{ asset_group.name }}">{{ asset_group.name }}</option>
<option value="{{ asset_group.name }}"{% if asset_group in asset_groups_select %} selected {% endif %}>{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
......@@ -89,57 +89,17 @@
<div class="col-sm-8">
<select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
{% for role in roles %}
<option value="{{ role.name }}">{{ role.name }}</option>
<option value="{{ role.name }}"{% if role in roles_select %} selected {% endif %}>{{ role.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="0" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_password" style="display: none">
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_publicKey" name="use_publicKey">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_publicKey" style="display: none">
<label class="col-sm-1 control-label"> 秘钥<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
<input id="role_comment" name="role_comment" placeholder="Rule Comment" type="text" class="form-control" value="{{ rule_comment }}">
</div>
</div>
<div class="hr-line-dashed"></div>
......
......@@ -3,10 +3,20 @@
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<div class="ibox-title">
<h5> 所有规则</h5>
<div class="ibox-tools">
......@@ -55,19 +65,19 @@
<tr class="gradeX" id={{ rule.id }}>
<td class="text-center"> {{ rule.name }} </td>
<td class="text-center">
<a href="/jasset/asset_list/?gid={{ user.id }}">{{ rule | rule_member_count:"user" }} </a>
{{ rule | rule_member_count:"user" }}
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"user_group" }}</a>
{{ rule | rule_member_count:"user_group" }}
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"asset" }}</a>
{{ rule | rule_member_count:"asset" }}
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"asset_group" }}</a>
{{ rule | rule_member_count:"asset_group" }}
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"role" }}</a>
{{ rule | rule_member_count:"role" }}
</td>
<td class="text-center">
<a href="/jperm/perm_rule_detail/?id={{ rule.id }}" class="btn btn-xs btn-primary">详情</a>
......
......@@ -93,6 +93,7 @@ type="checkbox" name="selected" value="{{ group.id }}">
$(document).ready(function(){
$('.del').click(function(){
var row = $(this).closest('tr');
if (confirm("确定删除")) {
$.get(
$(this).attr('value'),
{},
......@@ -101,7 +102,7 @@ type="checkbox" name="selected" value="{{ group.id }}">
alert(data);
}
)
)}
});
$('#del_btn').click(function(){
......
......@@ -42,7 +42,7 @@
<div class="col-sm-8">
<input id="password" name="password" placeholder="Password" type="password" class="form-control">
<span class="help-block m-b-none">
登陆web的密码
登陆web的密码(如不修改请留空)
</span>
</div>
</div>
......
......@@ -64,7 +64,13 @@
<td class="text-center" title="{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"> {{ user.group.all | groups2str }} </td>
<td class="text-center"> {{ user.id | get_role }}</td>
<td class="text-center">{{ user.is_active | bool2str }}</td>
<td class="text-center"><a href="/juser/down_key/?id={{ user.id }}">下载</a></td>
<td class="text-center">
{% if user.username|key_exist %}
<a href="/juser/down_key/?id={{ user.id }}" >下载</a>
{% else %}
<span style="color: #586b7d">下载</span>
{% endif %}
</td>
<td class="text-center">
<a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a>
<a href="../user_edit/?id={{ user.id }}" class="btn btn-xs btn-info">编辑</a>
......
......@@ -4,10 +4,10 @@
<ul class="nav" id="side-menu">
{% include 'nav_li_profile.html' %}
<li id="index">
<a href="/"><i class="fa fa-th-large"></i> <span class="nav-label">仪表盘</span><span class="label label-info pull-right"></span></a>
<a href="/"><i class="fa fa-dashboard"></i> <span class="nav-label">仪表盘</span><span class="label label-info pull-right"></span></a>
</li>
<li id="juser">
<a href="#"><i class="fa fa-rebel"></i> <span class="nav-label">用户管理</span><span class="fa arrow"></span></a>
<a href="#"><i class="fa fa-group"></i> <span class="nav-label">用户管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li class="group_list group_edit"><a href="/juser/group_list/">查看用户组</a></li>
<li class="group_add"><a href="/juser/group_add/">添加用户组</a></li>
......@@ -16,7 +16,7 @@
</ul>
</li>
<li id="jasset">
<a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<a><i class="fa fa-inbox"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li class="group_add"><a href="/jasset/group_add/">添加资产组</a></li>
<li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看资产组</a></li>
......@@ -29,11 +29,11 @@
<li id="jperm">
<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">
<li class="dept_perm_list dept_perm_edit">
<li class="rule ">
<a href="/jperm/rule/">授权规则</a>
</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>
</li>
<li class="apply_show online"><a href="/jperm/apply_show/online/">权限审批</a></li>
......@@ -44,7 +44,7 @@
<a href="/jlog/log_list/online/"><i class="fa fa-files-o"></i> <span class="nav-label">日志审计</span><span class="label label-info pull-right"></span></a>
</li>
<li id="setting">
<a href="/setting/"><i class="fa fa-files-o"></i> <span class="nav-label">设置</span><span class="label label-info pull-right"></span></a>
<a href="/setting/"><i class="fa fa-gears"></i> <span class="nav-label">设置</span><span class="label label-info pull-right"></span></a>
</li>
<li class="special_link">
<a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i> <span class="nav-label">访问官网</span></a>
......
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