1. 新增 PermSudo表, 用于记录 sudo别名

2. 实现Sudo表对应的 添加,显示,更新,删除页面
3. 添加角色时,需要选择对应的 sudo别名
pull/26/head
yumaojun 2015-11-24 22:03:58 +08:00
parent e57c6a9d2e
commit 1a0c9cd4e6
14 changed files with 737 additions and 29 deletions

View File

@ -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)

View File

@ -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

View File

@ -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),

View File

@ -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__":

View File

@ -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"不支持该操作")

View File

@ -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)

View File

@ -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">

View File

@ -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">

View File

@ -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)
}
});

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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

View File

@ -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>