角色key问题修复

pull/26/head
ibuler 2015-11-25 14:59:57 +08:00
parent a7db713b1e
commit 6fe6342ca4
8 changed files with 175 additions and 156 deletions

View File

@ -6,6 +6,7 @@ import os.path
from paramiko.rsakey import RSAKey
from jumpserver.api import mkdir
from uuid import uuid4
from jumpserver.api import CRYPTOR
from jumpserver.settings import KEY_DIR
@ -14,18 +15,7 @@ def get_rand_pass():
"""
get a reandom password.
"""
lower = [chr(i) for i in range(97,123)]
upper = [chr(i).upper() for i in range(97,123)]
digit = [str(i) for i in range(10)]
password_pool = []
password_pool.extend(lower)
password_pool.extend(upper)
password_pool.extend(digit)
pass_list = [random.choice(password_pool) for i in range(1,14)]
pass_list.insert(random.choice(range(1,14)), '@')
pass_list.insert(random.choice(range(1,14)), random.choice(digit))
password = ''.join(pass_list)
return password
CRYPTOR.gen_rand_pass(20)
def updates_dict(*args):
@ -38,7 +28,7 @@ def updates_dict(*args):
return result
def gen_keys():
def gen_keys(gen=True):
"""
在KEY_DIR下创建一个 uuid命名的目录
并且在该目录下 生产一对秘钥
@ -47,6 +37,8 @@ def gen_keys():
key_basename = "key-" + uuid4().hex
key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
mkdir(key_path_dir, mode=0755)
if not gen:
return key_path_dir
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')

View File

@ -255,36 +255,41 @@ def perm_role_add(request):
# 渲染数据
header_title, path1, path2 = "系统角色", "角色管理", "添加角色"
if request.method == "GET":
default_password = get_rand_pass()
return my_render('jperm/perm_role_add.html', locals(), request)
elif request.method == "POST":
if request.method == "POST":
# 获取参数: name, comment
name = request.POST.get("role_name")
comment = request.POST.get("role_comment")
password = request.POST.get("role_password")
encrypt_pass = CRYPTOR.encrypt(password)
# 生成随机密码,生成秘钥对
name = request.POST.get("role_name", "")
comment = request.POST.get("role_comment", "")
password = request.POST.get("role_password", "")
key_content = request.POST.get("role_key", "")
try:
if get_object(PermRole, name=name):
raise ServerError('已经存在该用户 %s' % name)
key_path = gen_keys()
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
role.save()
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)
if '' == password and '' == key_content:
raise ServerError('账号和密码必填一项')
if password:
encrypt_pass = CRYPTOR.encrypt(password)
else:
encrypt_pass = CRYPTOR.encrypt(CRYPTOR.gen_rand_pass(20))
# 生成随机密码,生成秘钥对
if key_content:
key_path = gen_keys(gen=False)
with open(os.path.join(key_path, 'id_rsa'), 'w') as f:
f.write(key_content)
else:
key_path = gen_keys()
logger.debug('generate role key: %s' % key_path)
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
role.save()
msg = u"添加角色: %s" % name
return HttpResponseRedirect('/perm/role/')
except ServerError, e:
error = e
else:
return HttpResponse(u"不支持该操作")
return my_render('jperm/perm_role_add.html', locals(), request)
@require_role('admin')
def perm_role_delete(request):
@ -346,36 +351,37 @@ def perm_role_edit(request):
# 渲染数据
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)
role = get_object(PermRole, id=role_id)
if request.method == "POST":
# 获取 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")
key_content = request.POST.get("role_key", "")
try:
if not role:
raise ServerError('角色用户不能存在')
# 写入数据库
role.name = role_name
role.password = encrypt_role_pass
role.comment = role_comment
if role_password:
encrypt_pass = CRYPTOR.encrypt(role_password)
role.password = encrypt_pass
# 生成随机密码,生成秘钥对
if key_content:
with open(os.path.join(role.key_path, 'id_rsa'), 'w') as f:
f.write(key_content)
logger.debug('Recreate role key: %s' % role.key_path)
# 写入数据库
role.name = role_name
role.comment = role_comment
role.save()
msg = u"更新系统角色: %s" % role.name
role.save()
msg = u"更新系统角色: %s" % role.name
return HttpResponseRedirect('/jperm/role/')
except ServerError, e:
error = e
# 渲染 刷新数据
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)
return my_render('jperm/perm_role_edit.html', locals(), request)
@require_role('admin')

View File

@ -48,6 +48,9 @@ def set_log(level):
def get_asset_info(asset):
"""
获取资产的相关账号端口信息
"""
default = get_object(Setting, name='default')
info = {'hostname': asset.hostname, 'ip': asset.ip}
if asset.use_default_auth:
@ -68,6 +71,9 @@ def get_asset_info(asset):
def get_role(user, asset):
"""
获取用户在这个资产上的授权角色列表
"""
roles = []
rules = PermRule.objects.filter(user=user, asset=asset)
for rule in rules:
@ -77,20 +83,19 @@ def get_role(user, asset):
def get_role_key(user, role):
"""
由于role的key的权限是所有人可以读的 ansible要求为600所以拷贝一份到特殊目录
由于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)
mkdir(user_role_key_dir, mode=0777)
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
logger.debug("创建新的用户角色key %s" % user_role_key_path)
chown(user_role_key_path, user.username)
os.chmod(user_role_key_path, 0600)
return user_role_key_path

View File

@ -4566,4 +4566,6 @@ body.skin-3 {
.form-group.required .control-label:after {
content: " *";
color: red;
}
}
.n-invalid {border: 1px solid #f00;}

View File

@ -26,7 +26,7 @@
</div>
</div>
<div class="ibox-content">
<form method="post" id="userForm" class="form-horizontal" action="">
<form method="post" id="roleForm" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
@ -41,9 +41,18 @@
</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>
<label for="role_password" class="col-sm-2 control-label">角色密码</label>
<div class="col-sm-8">
<input id="role_password" name="role_password" type="password" class="form-control" value="{{ default_password }}">
<input id="role_password" name="role_password" placeholder="Role Password" type="password" class="form-control">
<span class="help-block m-b-none">如果不添加密码,会自动生成</span>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="role_key" class="col-sm-2 control-label">角色密钥</label>
<div class="col-sm-8">
<textarea class="form-control" name="role_key" placeholder="请复制粘贴私钥" rows="10" style="font-size: 9px;"></textarea>
<span class="help-block m-b-none">如果不添加密钥,会自动生成, 密码密钥必填一项</span>
</div>
</div>
<div class="hr-line-dashed"></div>
@ -69,52 +78,34 @@
{% 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');
$('#roleForm').validator({
timely: 2,
theme: "yellow_right_effect",
rules: {
check_name: [/^\w{2,20}$/, '大小写字母数字和下划线,2-20位'],
either: function(){
return $('#role_password').val() == ''
}
else {
},
$("#admin_groups").css("display", 'block');
fields: {
"role_name": {
rule: "required;check_name",
tip: "输入角色名称",
ok: "",
msg: {required: "角色名称必填"}
},
"role_key": {
rule: "required(either)",
tip: "输入密钥",
ok: "",
msg: {required: "密码和密钥必填一个!"}
}
});
$('#use_password').click(function(){
if ($(this).is(':checked')){
$('#admin_account_password').css('display', 'block')
},
valid: function(form) {
form.submit();
}
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

@ -26,7 +26,7 @@
</div>
</div>
<div class="ibox-content">
<form method="post" id="userForm" class="form-horizontal" action="">
<form method="post" id="roleForm" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
@ -41,9 +41,18 @@
</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>
<label for="role_password" class="col-sm-2 control-label">角色密码</label>
<div class="col-sm-8">
<input id="role_password" name="role_password" type="password" class="form-control" value="{{ role_pass }}">
<input id="role_password" name="role_password" type="password" class="form-control">
<span class="help-block m-b-none">不修改请留空</span>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="role_key" class="col-sm-2 control-label">角色密钥</label>
<div class="col-sm-8">
<textarea class="form-control" name="role_key" placeholder="请复制粘贴私钥" rows="10" style="font-size: 9px;"></textarea>
<span class="help-block m-b-none">不修改请留空</span>
</div>
</div>
<div class="hr-line-dashed"></div>
@ -69,49 +78,25 @@
{% 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');
$('#roleForm').validator({
timely: 2,
theme: "yellow_right_effect",
rules: {
check_name: [/^\w{2,20}$/, '大小写字母数字和下划线,2-20位']
},
fields: {
"role_name": {
rule: "required;check_name",
tip: "输入角色名称",
ok: "",
msg: {required: "角色名称必填"}
}
else {
$("#admin_groups").css("display", 'block');
},
valid: function(form) {
form.submit();
}
});
$('#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>

View File

@ -34,7 +34,6 @@
<div class="">
<a href="/jperm/role/perm_role_add/" class="btn btn-sm btn-primary "> 添加角色 </a>
<a href="/jperm/role/perm_role_push/" 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">

View File

@ -37,7 +37,7 @@
<div class="panel-body">
<div class="tab-content">
<div id="tab-default" class="tab-pane active">
<form method="post" id="userForm" class="form-horizontal" action="">
<form method="post" id="settingForm" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
@ -71,7 +71,7 @@
<label for="key" class="col-sm-2 control-label">默认密钥</label>
<div class="col-sm-8">
<textarea class="form-control" name="key" placeholder="请复制粘贴私钥" rows="10" style="font-size: 9px;"></textarea>
<span class="help-block m-b-none">如果不修改密钥,请留空</span>
<span class="help-block m-b-none">如果不修改密钥,请留空, 密钥密码必填一项</span>
</div>
</div>
<div class="hr-line-dashed"></div>
@ -101,4 +101,43 @@
</div>
</div>
</div>
{% endblock %}
{% block self_footer_js %}
<script>
$('#settingForm').validator({
timely: 2,
theme: "yellow_right_effect",
rules: {
check_name: [/^\w{2,20}$/, '大小写字母数字和下划线,2-20位'],
check_port: [/^\d{1,5}$/, '端口号不正确'],
either: function(){
return $('#password').val() == ''
}
},
fields: {
"username": {
rule: "required;check_name",
tip: "输入用户名",
ok: "",
msg: {required: "用户名称必填"}
},
"port": {
rule: "required;check_port",
tip: "输入端口号",
ok: "",
msg: {required: "端口号必填"}
},
"key": {
rule: "required(either)",
tip: "输入密钥",
ok: "",
msg: {required: "密码和密钥必填一个!"}
}
},
valid: function(form) {
form.submit();
}
})
</script>
{% endblock %}