mirror of https://github.com/jumpserver/jumpserver
1. 新增 PermSudo表, 用于记录 sudo别名
2. 实现Sudo表对应的 添加,显示,更新,删除页面 3. 添加角色时,需要选择对应的 sudo别名pull/26/head
parent
e57c6a9d2e
commit
1a0c9cd4e6
|
@ -20,7 +20,6 @@ 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),
|
||||
|
@ -44,7 +43,7 @@ class CommandValueError(AnsibleError):
|
|||
super(CommandValueError, self).__init__('value:invalid', field, message)
|
||||
|
||||
|
||||
class MyInventory(object):
|
||||
class MyInventory(Inventory):
|
||||
"""
|
||||
this is my ansible inventory object.
|
||||
"""
|
||||
|
@ -65,7 +64,7 @@ class MyInventory(object):
|
|||
self.inventory = Inventory(host_list=[])
|
||||
self.gen_inventory()
|
||||
|
||||
def add_group(self, hosts, groupname, groupvars=None):
|
||||
def my_add_group(self, hosts, groupname, groupvars=None):
|
||||
"""
|
||||
add hosts to a group
|
||||
"""
|
||||
|
@ -83,11 +82,13 @@ class MyInventory(object):
|
|||
hostport = host.get("port")
|
||||
username = host.get("username")
|
||||
password = host.get("password")
|
||||
sudo_password = host.get("sudo_password")
|
||||
my_host = Host(name=hostname, port=hostport)
|
||||
my_host.set_variable('ansible_ssh_host', hostname)
|
||||
my_host.set_variable('ansible_ssh_port', hostport)
|
||||
my_host.set_variable('ansible_ssh_user', username)
|
||||
my_host.set_variable('ansible_ssh_pass', password)
|
||||
|
||||
# set other variables
|
||||
for key, value in host.iteritems():
|
||||
if key not in ["hostname", "port", "username", "password"]:
|
||||
|
@ -102,10 +103,10 @@ class MyInventory(object):
|
|||
add hosts to inventory.
|
||||
"""
|
||||
if isinstance(self.resource, list):
|
||||
self.add_group(self.resource, 'default_group')
|
||||
self.my_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"))
|
||||
self.my_add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
|
||||
|
||||
|
||||
class Command(MyInventory):
|
||||
|
@ -125,7 +126,7 @@ class Command(MyInventory):
|
|||
|
||||
if module_name not in ["raw", "command", "shell"]:
|
||||
raise CommandValueError("module_name",
|
||||
"module_name must be of the 'raw, command, shell'")
|
||||
"module_name must be of the 'raw, command, shell'")
|
||||
hoc = Runner(module_name=module_name,
|
||||
module_args=command,
|
||||
timeout=timeout,
|
||||
|
@ -136,15 +137,17 @@ class Command(MyInventory):
|
|||
)
|
||||
self.results = hoc.run()
|
||||
|
||||
ret = {}
|
||||
if self.stdout:
|
||||
return {"ok": self.stdout}
|
||||
ret["ok"] = self.stdout
|
||||
else:
|
||||
msg = []
|
||||
if self.stderr:
|
||||
msg.append(self.stderr)
|
||||
if self.dark:
|
||||
msg.append(self.dark)
|
||||
return {"failed": msg}
|
||||
ret["failed"] = msg
|
||||
return ret
|
||||
|
||||
@property
|
||||
def raw_results(self):
|
||||
|
@ -206,7 +209,14 @@ 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='default_group', pattern='*'):
|
||||
def __run(self,
|
||||
module_args,
|
||||
module_name="command",
|
||||
timeout=5,
|
||||
forks=10,
|
||||
group='default_group',
|
||||
pattern='*',
|
||||
):
|
||||
"""
|
||||
run command from andible ad-hoc.
|
||||
command : 必须是一个需要执行的命令字符串, 比如
|
||||
|
@ -219,6 +229,7 @@ class Tasks(Command):
|
|||
subset=group,
|
||||
pattern=pattern,
|
||||
forks=forks,
|
||||
become=False,
|
||||
)
|
||||
|
||||
self.results = hoc.run()
|
||||
|
@ -272,7 +283,7 @@ class Tasks(Command):
|
|||
module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state="absent"' % (user, key_path)
|
||||
self.__run(module_args, "authorized_key")
|
||||
|
||||
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
|
||||
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
|
||||
|
||||
def add_user(self, username, password):
|
||||
"""
|
||||
|
@ -310,7 +321,8 @@ class Tasks(Command):
|
|||
delete a host user.
|
||||
"""
|
||||
module_args = 'name=%s state=absent remove=yes move_home=yes force=yes' % (username)
|
||||
self.__run(module_args, "user")
|
||||
self.__run(module_args,
|
||||
"user",)
|
||||
|
||||
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
|
||||
|
||||
|
@ -386,9 +398,15 @@ class Tasks(Command):
|
|||
"product_sn": setup.get("ansible_product_serial")
|
||||
}
|
||||
|
||||
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result}
|
||||
|
||||
return {"failed": self.msg, "ok": result}
|
||||
|
||||
def push_sudo(self, role_custo, role_name, role_chosen):
|
||||
"""
|
||||
use template to render pushed sudoers file
|
||||
:return:
|
||||
"""
|
||||
module_args = 'src=%s dest=%s owner=root group=root mode=0440' % (username, encrypt_pass)
|
||||
self.__run(module_args, "template")
|
||||
|
||||
|
||||
class CustomAggregateStats(callbacks.AggregateStats):
|
||||
|
@ -440,12 +458,12 @@ class MyPlaybook(MyInventory):
|
|||
playbook_path = os.path.join(ANSIBLE_DIR, playbook_relational_path)
|
||||
|
||||
pb = PlayBook(
|
||||
playbook = playbook_path,
|
||||
stats = stats,
|
||||
callbacks = playbook_cb,
|
||||
runner_callbacks = runner_cb,
|
||||
inventory = self.inventory,
|
||||
extra_vars = extra_vars,
|
||||
playbook=playbook_path,
|
||||
stats=stats,
|
||||
callbacks=playbook_cb,
|
||||
runner_callbacks=runner_cb,
|
||||
inventory=self.inventory,
|
||||
extra_vars=extra_vars,
|
||||
check=False)
|
||||
|
||||
self.results = pb.run()
|
||||
|
@ -475,9 +493,14 @@ if __name__ == "__main__":
|
|||
# },
|
||||
# }
|
||||
|
||||
resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902"}]
|
||||
command = Command(resource)
|
||||
print command.run("who")
|
||||
resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902",
|
||||
# "ansible_become": "yes",
|
||||
# "ansible_become_method": "sudo",
|
||||
# # "ansible_become_user": "root",
|
||||
# "ansible_become_pass": "yusky0902",
|
||||
}]
|
||||
cmd = Command(resource)
|
||||
print cmd.run('ls')
|
||||
|
||||
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
|
||||
# task = Tasks(resource)
|
||||
|
|
|
@ -19,12 +19,23 @@ class SysUser(models.Model):
|
|||
comment = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
|
||||
|
||||
class PermSudo(models.Model):
|
||||
name = models.CharField(max_length=100, unique=True)
|
||||
date_added = models.DateTimeField(auto_now=True)
|
||||
commands = models.TextField()
|
||||
comment = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class PermRole(models.Model):
|
||||
name = models.CharField(max_length=100, unique=True)
|
||||
comment = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
password = models.CharField(max_length=100)
|
||||
key_path = models.CharField(max_length=100)
|
||||
date_added = models.DateTimeField(auto_now=True)
|
||||
sudo = models.ManyToManyField(PermSudo, related_name='perm_role')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
@ -41,4 +52,8 @@ class PermRule(models.Model):
|
|||
role = models.ManyToManyField(PermRole, related_name='perm_rule')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
return self.name
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,10 @@ 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'^sudo/$', perm_sudo_list),
|
||||
(r'^sudo/perm_sudo_add/$', perm_sudo_add),
|
||||
(r'^sudo/perm_sudo_delete/$', perm_sudo_delete),
|
||||
(r'^sudo/perm_sudo_edit/$', perm_sudo_edit),
|
||||
|
||||
(r'^log/$', log),
|
||||
(r'^sys_user_add/$', sys_user_add),
|
||||
|
|
|
@ -6,6 +6,8 @@ import os.path
|
|||
from paramiko.rsakey import RSAKey
|
||||
from os import chmod, makedirs
|
||||
from uuid import uuid4
|
||||
from django.template.loader import get_template
|
||||
from django.template import Context
|
||||
|
||||
from jumpserver.settings import KEY_DIR
|
||||
|
||||
|
@ -62,6 +64,29 @@ def gen_keys():
|
|||
return key_path_dir
|
||||
|
||||
|
||||
def gen_sudo(role_custom, role_name, role_chosen):
|
||||
"""
|
||||
生成sudo file, 仅测试了cenos7
|
||||
role_custom: 自定义支持的sudo 命令 格式: 'CMD1, CMD2, CMD3, ...'
|
||||
role_name: role name
|
||||
role_chosen: 选择那些sudo的命令别名:
|
||||
NETWORKING, SOFTWARE, SERVICES, STORAGE,
|
||||
DELEGATING, PROCESSES, LOCATE, DRIVERS
|
||||
:return:
|
||||
"""
|
||||
sudo_file_basename = os.path.join(os.path.dirname(KEY_DIR), 'role_sudo_file')
|
||||
makedirs(sudo_file_basename)
|
||||
sudo_file_path = os.path.join(sudo_file_basename, role_name)
|
||||
|
||||
t = get_template('role_sudo.j2')
|
||||
content = t.render(Context({"role_custom": role_custom,
|
||||
"role_name": role_name,
|
||||
"role_chosen": role_chosen,
|
||||
}))
|
||||
with open(sudo_file_path, 'w') as f:
|
||||
f.write(content)
|
||||
return sudo_file_path
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
136
jperm/views.py
136
jperm/views.py
|
@ -9,7 +9,7 @@ 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 jperm.models import PermRole, PermRule, PermSudo
|
||||
from jumpserver.models import Setting
|
||||
|
||||
from jperm.utils import updates_dict, gen_keys, get_rand_pass
|
||||
|
@ -259,19 +259,24 @@ def perm_role_add(request):
|
|||
|
||||
if request.method == "GET":
|
||||
default_password = get_rand_pass()
|
||||
sudos = PermSudo.objects.all()
|
||||
return my_render('jperm/perm_role_add.html', locals(), request)
|
||||
|
||||
elif request.method == "POST":
|
||||
# 获取参数: name, comment
|
||||
# 获取参数: name, comment, sudo
|
||||
name = request.POST.get("role_name")
|
||||
comment = request.POST.get("role_comment")
|
||||
password = request.POST.get("role_password")
|
||||
sudos_name = request.POST.getlist("sudo_name")
|
||||
sudos_obj = [PermSudo.objects.get(name=sudo_name) for sudo_name in sudos_name]
|
||||
encrypt_pass = CRYPTOR.encrypt(password)
|
||||
# 生成随机密码,生成秘钥对
|
||||
|
||||
key_path = gen_keys()
|
||||
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
|
||||
role.save()
|
||||
role.sudo = sudos_obj
|
||||
role.save()
|
||||
|
||||
msg = u"添加角色: %s" % name
|
||||
# 渲染 刷新数据
|
||||
|
@ -350,6 +355,7 @@ def perm_role_edit(request):
|
|||
role_id = request.GET.get("id")
|
||||
role = PermRole.objects.get(id=role_id)
|
||||
role_pass = CRYPTOR.decrypt(role.password)
|
||||
role_sudos = role.sudo.all()
|
||||
if request.method == "GET":
|
||||
return my_render('jperm/perm_role_edit.html', locals(), request)
|
||||
|
||||
|
@ -359,11 +365,14 @@ def perm_role_edit(request):
|
|||
role_password = request.POST.get("role_password")
|
||||
encrypt_role_pass = CRYPTOR.encrypt(role_password)
|
||||
role_comment = request.POST.get("role_comment")
|
||||
role_sudo_names = request.POST.getlist("sudo_name")
|
||||
role_sudos = [PermSudo.objects.get(name=sudo_name) for sudo_name in role_sudo_names]
|
||||
|
||||
# 写入数据库
|
||||
role.name = role_name
|
||||
role.password = encrypt_role_pass
|
||||
role.comment = role_comment
|
||||
role.sudo = role_sudos
|
||||
|
||||
role.save()
|
||||
msg = u"更新系统角色: %s" % role.name
|
||||
|
@ -380,8 +389,6 @@ def perm_role_edit(request):
|
|||
return my_render('jperm/perm_role_list.html', locals(), request)
|
||||
|
||||
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_role_push(request):
|
||||
"""
|
||||
|
@ -461,6 +468,127 @@ def perm_role_push(request):
|
|||
return HttpResponse(u"推送系统角色: %s" % ','.join(role_names))
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_sudo_list(request):
|
||||
"""
|
||||
list sudo commands alias
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "查看别名"
|
||||
|
||||
# 获取所有sudo 命令别名
|
||||
sudos_list = PermSudo.objects.all()
|
||||
|
||||
# TODO: 搜索和分页
|
||||
keyword = request.GET.get('search', '')
|
||||
if keyword:
|
||||
sudos_list = sudos_list.filter(Q(name=keyword))
|
||||
|
||||
sudos_list, p, sudos, page_range, current_page, show_first, show_end = pages(sudos_list, request)
|
||||
|
||||
return my_render('jperm/perm_sudo_list.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_sudo_add(request):
|
||||
"""
|
||||
list sudo commands alias
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "添加别名"
|
||||
|
||||
if request.method == "GET":
|
||||
return my_render('jperm/perm_sudo_add.html', locals(), request)
|
||||
|
||||
elif request.method == "POST":
|
||||
# 获取参数: name, comment
|
||||
name = request.POST.get("sudo_name")
|
||||
comment = request.POST.get("sudo_comment")
|
||||
commands = request.POST.get("sudo_commands")
|
||||
|
||||
sudo = PermSudo(name=name, comment=comment, commands=commands)
|
||||
sudo.save()
|
||||
|
||||
msg = u"添加Sudo命令别名: %s" % name
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "查看别名"
|
||||
# 获取所有sudo 命令别名
|
||||
sudos_list = PermSudo.objects.all()
|
||||
|
||||
# TODO: 搜索和分页
|
||||
keyword = request.GET.get('search', '')
|
||||
if keyword:
|
||||
roles_list = sudos_list.filter(Q(name=keyword))
|
||||
|
||||
sudos_list, p, sudos, page_range, current_page, show_first, show_end = pages(sudos_list, request)
|
||||
|
||||
return my_render('jperm/perm_sudo_list.html', locals(), request)
|
||||
else:
|
||||
return HttpResponse(u"不支持该操作")
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_sudo_edit(request):
|
||||
"""
|
||||
list sudo commands alias
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "编辑别名"
|
||||
|
||||
sudo_id = request.GET.get("id")
|
||||
sudo = PermSudo.objects.get(id=sudo_id)
|
||||
if request.method == "GET":
|
||||
return my_render('jperm/perm_sudo_edit.html', locals(), request)
|
||||
|
||||
if request.method == "POST":
|
||||
name = request.POST.get("sudo_name")
|
||||
commands = request.POST.get("sudo_commands")
|
||||
comment = request.POST.get("sudo_comment")
|
||||
sudo.name = name
|
||||
sudo.commands = commands
|
||||
sudo.comment = comment
|
||||
sudo.save()
|
||||
|
||||
msg = u"更新命令别名: %s" % name
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "查看别名"
|
||||
# 获取所有sudo 命令别名
|
||||
sudos_list = PermSudo.objects.all()
|
||||
# TODO: 搜索和分页
|
||||
keyword = request.GET.get('search', '')
|
||||
if keyword:
|
||||
sudos_list = sudos_list.filter(Q(name=keyword))
|
||||
sudos_list, p, sudos, page_range, current_page, show_first, show_end = pages(sudos_list, request)
|
||||
return my_render('jperm/perm_sudo_list.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_sudo_delete(request):
|
||||
"""
|
||||
list sudo commands alias
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
if request.method == "POST":
|
||||
# 获取参数删除的role对象
|
||||
sudo_id = request.POST.get("id")
|
||||
sudo = PermSudo.objects.get(id=sudo_id)
|
||||
# 数据库里删除记录
|
||||
sudo.delete()
|
||||
return HttpResponse(u"删除角色: %s" % sudo.name)
|
||||
else:
|
||||
return HttpResponse(u"不支持该操作")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -226,3 +226,12 @@ def ip_str_to_list(ip_str):
|
|||
ip str to list
|
||||
"""
|
||||
return ip_str.split(',')
|
||||
|
||||
|
||||
@register.filter(name='role_contain_which_sudos')
|
||||
def role_contain_which_sudos(role):
|
||||
"""
|
||||
get role sudo commands
|
||||
"""
|
||||
sudo_names = [sudo.name for sudo in role.sudo.all()]
|
||||
return ','.join(sudo_names)
|
||||
|
|
|
@ -47,6 +47,17 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo" class="col-sm-2 control-label">角色Sudo命令<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8" id="sudo_name">
|
||||
<select name="sudo_name" data-placeholder="请选择Sudo别名" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||
{% for sudo in sudos %}
|
||||
<option >{{ sudo.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</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">
|
||||
|
|
|
@ -47,6 +47,17 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo" class="col-sm-2 control-label">角色Sudo命令<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8" id="sudo_name">
|
||||
<select name="sudo_name" data-placeholder="请选择Sudo别名" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||
{% for sudo in role_sudos %}
|
||||
<option selected >{{ sudo.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</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">
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
<th class="text-center">名称 </th>
|
||||
<th class="text-center">备注</th>
|
||||
<th class="text-center">创建时间</th>
|
||||
<th class="text-center">sudo别名</th>
|
||||
<th class="text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -62,6 +63,7 @@
|
|||
<td class="text-center"> {{ role.name }} </td>
|
||||
<td class="text-center"> {{ role.comment }} </td>
|
||||
<td class="text-center"> {{ role.date_added | date:"Y-m-d H:i:s"}} </td>
|
||||
<td class="text-center"> {{ role | role_contain_which_sudos }} </td>
|
||||
<td class="text-center">
|
||||
<a href="/jperm/role/perm_role_detail/?id={{ role.id }}" class="btn btn-xs btn-primary">详情</a>
|
||||
<a href="/jperm/role/perm_role_edit/?id={{ role.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
|
@ -99,6 +101,7 @@ function remove_role(role_id){
|
|||
del_row.remove()
|
||||
},
|
||||
error: function (msg) {
|
||||
console.log(msg)
|
||||
alert("失败: " + msg)
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block self_head_css_js %}
|
||||
<link href="/static/css/plugins/datapicker/datepicker3.css" rel="stylesheet">
|
||||
<link href="/static/css/plugins/chosen/chosen.css" rel="stylesheet">
|
||||
<script src="/static/js/plugins/chosen/chosen.jquery.js"></script>
|
||||
{% endblock %}
|
||||
{% load mytags %}
|
||||
{% 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 class="ibox-title">
|
||||
<h5>填写基本信息</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<form method="post" id="sudoForm" class="form-horizontal" action="">
|
||||
{% 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 class="form-group">
|
||||
<label for="sudo_name" class="col-sm-2 control-label">命令别名<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sudo_name" name="sudo_name" placeholder="Sudo Command Alias" type="text" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo_commands_label" class="col-sm-2 control-label">系统命令<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<textarea id="sudo_commands" name="sudo_commands" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo_comment" class="col-sm-2 control-label">备注</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sudo_comment" name="sudo_comment" placeholder="Sudo Comment" type="text" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-white" type="reset">取消</button>
|
||||
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("input.role").click(function(){
|
||||
if($("input.role[value=GA]").is( ":checked" )){
|
||||
$("#admin_groups").css("display", 'none');
|
||||
}
|
||||
else {
|
||||
|
||||
$("#admin_groups").css("display", 'block');
|
||||
}
|
||||
});
|
||||
|
||||
$('#use_password').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account_password').css('display', 'block')
|
||||
}
|
||||
else {
|
||||
|
||||
$('#admin_account_password').css('display', 'none')
|
||||
}
|
||||
});
|
||||
|
||||
$('#use_publicKey').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
|
||||
$('#admin_account_publicKey').css('display', 'block')
|
||||
}
|
||||
else {
|
||||
$('#admin_account_publicKey').css('display', 'none')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var config = {
|
||||
'.chosen-select' : {},
|
||||
'.chosen-select-deselect' : {allow_single_deselect:true},
|
||||
'.chosen-select-no-single' : {disable_search_threshold:10},
|
||||
'.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
|
||||
'.chosen-select-width' : {width:"95%"}
|
||||
};
|
||||
|
||||
for (var selector in config) {
|
||||
$(selector).chosen(config[selector]);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script src="/static/js/cropper/cropper.min.js"></script>
|
||||
<script src="/static/js/datapicker/bootstrap-datepicker.js"></script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block self_head_css_js %}
|
||||
<link href="/static/css/plugins/datapicker/datepicker3.css" rel="stylesheet">
|
||||
<link href="/static/css/plugins/chosen/chosen.css" rel="stylesheet">
|
||||
<script src="/static/js/plugins/chosen/chosen.jquery.js"></script>
|
||||
{% endblock %}
|
||||
{% load mytags %}
|
||||
{% 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 class="ibox-title">
|
||||
<h5>填写基本信息</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<form method="post" id="sudoForm" class="form-horizontal" action="">
|
||||
{% 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 class="form-group">
|
||||
<label for="sudo_name" class="col-sm-2 control-label">命令别名<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sudo_name" name="sudo_name" placeholder="Sudo Command Alias" type="text" class="form-control" value={{ sudo.name }}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo_commands_label" class="col-sm-2 control-label">系统命令<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<textarea id="sudo_commands" name="sudo_commands" class="form-control" rows="3">{{ sudo.commands }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo_comment" class="col-sm-2 control-label">备注</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sudo_comment" name="sudo_comment" placeholder="Sudo Comment" type="text" class="form-control" value={{ sudo.commnet }}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-white" type="reset">取消</button>
|
||||
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("input.role").click(function(){
|
||||
if($("input.role[value=GA]").is( ":checked" )){
|
||||
$("#admin_groups").css("display", 'none');
|
||||
}
|
||||
else {
|
||||
|
||||
$("#admin_groups").css("display", 'block');
|
||||
}
|
||||
});
|
||||
|
||||
$('#use_password').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account_password').css('display', 'block')
|
||||
}
|
||||
else {
|
||||
|
||||
$('#admin_account_password').css('display', 'none')
|
||||
}
|
||||
});
|
||||
|
||||
$('#use_publicKey').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
|
||||
$('#admin_account_publicKey').css('display', 'block')
|
||||
}
|
||||
else {
|
||||
$('#admin_account_publicKey').css('display', 'none')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var config = {
|
||||
'.chosen-select' : {},
|
||||
'.chosen-select-deselect' : {allow_single_deselect:true},
|
||||
'.chosen-select-no-single' : {disable_search_threshold:10},
|
||||
'.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
|
||||
'.chosen-select-width' : {width:"95%"}
|
||||
};
|
||||
|
||||
for (var selector in config) {
|
||||
$(selector).chosen(config[selector]);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script src="/static/js/cropper/cropper.min.js"></script>
|
||||
<script src="/static/js/datapicker/bootstrap-datepicker.js"></script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
{% 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> 所有Sudo命令别名</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
<div class="">
|
||||
<a href="/jperm/sudo/perm_sudo_add/" class="btn btn-sm btn-primary "> 添加别名 </a>
|
||||
<a id="del_btn" class="btn btn-sm btn-danger "> 删除所选 </a>
|
||||
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
|
||||
<div class="input-group-btn">
|
||||
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||
- 搜索 -
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-bordered table-hover " id="editable" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">命令别名 </th>
|
||||
<th class="text-center">系统命令</th>
|
||||
<th class="text-center">创建时间</th>
|
||||
<th class="text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="edittbody">
|
||||
{% for sudo in sudos %}
|
||||
<tr class="gradeX" id={{ sudo.id }}>
|
||||
<td class="text-center"> {{ sudo.name }} </td>
|
||||
<td class="text-center"> {{ sudo.commands }} </td>
|
||||
<td class="text-center"> {{ sudo.date_added | date:"Y-m-d H:i:s"}} </td>
|
||||
<td class="text-center">
|
||||
{# <a href="/jperm/sudo/perm_sudo_detail/?id={{ sudo.id }}" class="btn btn-xs btn-primary">详情</a>#}
|
||||
<a href="/jperm/sudo/perm_sudo_edit/?id={{ sudo.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<button onclick="remove_sudo({{ sudo.id }})" class="btn btn-xs btn-danger">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
|
||||
Showing {{ users.start_index }} to {{ users.end_index }} of {{ p.count }} entries
|
||||
</div>
|
||||
</div>
|
||||
{% include 'paginator.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
function remove_sudo(sudo_id){
|
||||
if (confirm("确认删除")) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/jperm/sudo/perm_sudo_delete/",
|
||||
data: "id=" + sudo_id,
|
||||
success: function(msg){
|
||||
alert( "成功: " + msg );
|
||||
var del_row = $('tbody#edittbody>tr#' + sudo_id);
|
||||
del_row.remove()
|
||||
},
|
||||
error: function (msg) {
|
||||
alert("失败: " + msg)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
## Sudoers allows particular users to run various commands as
|
||||
## the root user, without needing the root password.
|
||||
##
|
||||
## Examples are provided at the bottom of the file for collections
|
||||
## of related commands, which can then be delegated out to particular
|
||||
## users or groups.
|
||||
##
|
||||
## This file must be edited with the 'visudo' command.
|
||||
|
||||
## Host Aliases
|
||||
## Groups of machines. You may prefer to use hostnames (perhaps using
|
||||
## wildcards for entire domains) or IP addresses instead.
|
||||
# Host_Alias FILESERVERS = fs1, fs2
|
||||
# Host_Alias MAILSERVERS = smtp, smtp2
|
||||
|
||||
## User Aliases
|
||||
## These aren't often necessary, as you can use regular groups
|
||||
## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname
|
||||
## rather than USERALIAS
|
||||
# User_Alias ADMINS = jsmith, mikem
|
||||
|
||||
|
||||
## Command Aliases
|
||||
## These are groups of related commands...
|
||||
|
||||
## Networking
|
||||
Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, /usr/bin/net, /sbin/iptables, /usr/bin/rfcomm, /usr/bin/wvdial, /sbin/iwconfig, /sbin/mii-tool
|
||||
|
||||
## Installation and management of software
|
||||
Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum
|
||||
|
||||
## Services
|
||||
Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig
|
||||
|
||||
## Updating the locate database
|
||||
Cmnd_Alias LOCATE = /usr/bin/updatedb
|
||||
|
||||
## Storage
|
||||
Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount
|
||||
|
||||
## Delegating permissions
|
||||
Cmnd_Alias DELEGATING = /bin/chown, /bin/chmod, /bin/chgrp
|
||||
|
||||
## Processes
|
||||
Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall
|
||||
|
||||
## Drivers
|
||||
Cmnd_Alias DRIVERS = /sbin/modprobe
|
||||
|
||||
## Custom
|
||||
{% if {{ role_custom }} %}
|
||||
{% Cmnd_Alias CUSTOM = {{ role_custom }} %}
|
||||
{% endif %}
|
||||
|
||||
# Defaults specification
|
||||
|
||||
#
|
||||
# Disable "ssh hostname sudo <cmd>", because it will show the password in clear.
|
||||
# You have to run "ssh -t hostname sudo <cmd>".
|
||||
#
|
||||
Defaults requiretty
|
||||
|
||||
#
|
||||
# Refuse to run if unable to disable echo on the tty. This setting should also be
|
||||
# changed in order to be able to use sudo without a tty. See requiretty above.
|
||||
#
|
||||
Defaults !visiblepw
|
||||
|
||||
#
|
||||
# Preserving HOME has security implications since many programs
|
||||
# use it when searching for configuration files. Note that HOME
|
||||
# is already set when the the env_reset option is enabled, so
|
||||
# this option is only effective for configurations where either
|
||||
# env_reset is disabled or HOME is present in the env_keep list.
|
||||
#
|
||||
Defaults always_set_home
|
||||
|
||||
Defaults env_reset
|
||||
Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
|
||||
Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
|
||||
Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
|
||||
Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
|
||||
Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
|
||||
|
||||
#
|
||||
# Adding HOME to env_keep may enable a user to run unrestricted
|
||||
# commands via sudo.
|
||||
#
|
||||
# Defaults env_keep += "HOME"
|
||||
|
||||
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
## Next comes the main part: which users can run what software on
|
||||
## which machines (the sudoers file can be shared between multiple
|
||||
## systems).
|
||||
## Syntax:
|
||||
##
|
||||
## user MACHINE=COMMANDS
|
||||
##
|
||||
## The COMMANDS section may have other options added to it.
|
||||
##
|
||||
## Allow root to run any commands anywhere
|
||||
root ALL=(ALL) ALL
|
||||
|
||||
{{ role_name }} ALL = {{ role_chosen }}
|
||||
|
||||
|
||||
## Allows members of the 'sys' group to run networking, software,
|
||||
## service management apps and more.
|
||||
# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS
|
||||
|
||||
## Allows people in group wheel to run all commands
|
||||
%wheel ALL=(ALL) ALL
|
||||
|
||||
## Same thing without a password
|
||||
# %wheel ALL=(ALL) NOPASSWD: ALL
|
||||
|
||||
## Allows members of the users group to mount and unmount the
|
||||
## cdrom as root
|
||||
# %users ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom
|
||||
|
||||
## Allows members of the users group to shutdown this system
|
||||
# %users localhost=/sbin/shutdown -h now
|
||||
|
||||
## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)
|
||||
#includedir /etc/sudoers.d
|
|
@ -32,10 +32,12 @@
|
|||
<li class="dept_perm_list dept_perm_edit">
|
||||
<a href="/jperm/rule/">授权规则</a>
|
||||
</li>
|
||||
|
||||
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail">
|
||||
<a href="/jperm/role/">系统角色</a>
|
||||
</li>
|
||||
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail">
|
||||
<a href="/jperm/sudo/">Sudo命令</a>
|
||||
</li>
|
||||
<li class="apply_show online"><a href="/jperm/apply_show/online/">权限审批</a></li>
|
||||
<li class="apply_show online"><a href="/jperm/log/">授权记录</a></li>
|
||||
</ul>
|
||||
|
|
Loading…
Reference in New Issue