mirror of https://github.com/jumpserver/jumpserver
use map
parent
79e81340dc
commit
72a18d6abf
|
@ -11,3 +11,11 @@ class PermLog(models.Model):
|
|||
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='')
|
||||
|
||||
|
||||
|
|
|
@ -76,8 +76,8 @@ def perm_user_api(perm_info):
|
|||
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 if isinstance(user, User)]
|
||||
del_username = [user.username for user in del_users if isinstance(user, User)]
|
||||
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传入参数类型错误")
|
||||
|
||||
|
@ -90,7 +90,7 @@ def perm_user_api(perm_info):
|
|||
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,
|
||||
'the_pub_key': '/tmp/id_rsa.pub'})
|
||||
'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')})
|
||||
|
||||
print playbook, inventory
|
||||
|
||||
|
@ -264,6 +264,22 @@ def _public_perm_api(info):
|
|||
return results
|
||||
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
results = perm_user_api(perm_info)
|
||||
return results
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,34 +2,13 @@ from django.conf.urls import patterns, include, url
|
|||
from jperm.views import *
|
||||
|
||||
urlpatterns = patterns('jperm.views',
|
||||
# Examples:
|
||||
(r'^user/$', perm_user_list),
|
||||
(r'^perm_user_edit/$', perm_user_edit),
|
||||
(r'^group/$', perm_group_list),
|
||||
(r'^perm_group_edit/$', perm_group_edit),
|
||||
(r'log/$', log),
|
||||
# (r'^dept_perm_edit/$', 'dept_perm_edit'),
|
||||
# (r'^perm_list/$', view_splitter, {'su': perm_list, 'adm': perm_list_adm}),
|
||||
# (r'^dept_perm_list/$', 'dept_perm_list'),
|
||||
# (r'^perm_user_detail/$', 'perm_user_detail'),
|
||||
# (r'^perm_detail/$', 'perm_detail'),
|
||||
# (r'^perm_del/$', 'perm_del'),
|
||||
# (r'^perm_asset_detail/$', 'perm_asset_detail'),
|
||||
# (r'^sudo_list/$', view_splitter, {'su': sudo_list, 'adm': sudo_list_adm}),
|
||||
# (r'^sudo_del/$', 'sudo_del'),
|
||||
# (r'^sudo_edit/$', view_splitter, {'su': sudo_edit, 'adm': sudo_edit_adm}),
|
||||
# (r'^sudo_refresh/$', 'sudo_refresh'),
|
||||
# (r'^sudo_detail/$', 'sudo_detail'),
|
||||
# (r'^cmd_add/$', view_splitter, {'su': cmd_add, 'adm': cmd_add_adm}),
|
||||
# (r'^cmd_list/$', 'cmd_list'),
|
||||
# (r'^cmd_del/$', 'cmd_del'),
|
||||
# (r'^cmd_edit/$', 'cmd_edit'),
|
||||
# (r'^cmd_detail/$', 'cmd_detail'),
|
||||
# (r'^apply/$', 'perm_apply'),
|
||||
# (r'^apply_show/(\w+)/$', 'perm_apply_log'),
|
||||
# (r'^apply_exec/$', 'perm_apply_exec'),
|
||||
# (r'^apply_info/$', 'perm_apply_info'),
|
||||
# (r'^apply_del/$', 'perm_apply_del'),
|
||||
# (r'^apply_search/$', 'perm_apply_search'),
|
||||
|
||||
(r'^log/$', log),
|
||||
(r'^sys_user_add/$', sys_user_add),
|
||||
(r'^sys_user_list/$', sys_user_list),
|
||||
(r'^sys_user_del/$', sys_user_del),
|
||||
(r'^sys_user_edit/$', sys_user_edit),
|
||||
)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -32,6 +32,7 @@ def playbook_run(inventory, playbook, default_user=None, default_port=None, defa
|
|||
become=True,
|
||||
become_user='root')
|
||||
results = playbook.run()
|
||||
print results
|
||||
results_r = {'unreachable': [], 'failures': [], 'success': []}
|
||||
for hostname, result in results.items():
|
||||
if result.get('unreachable', 2):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# coding: utf-8
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from subprocess import call
|
||||
|
||||
from juser.models import AdminGroup
|
||||
from jumpserver.api import *
|
||||
|
@ -115,30 +116,27 @@ def db_del_user(username):
|
|||
user.delete()
|
||||
|
||||
|
||||
def gen_ssh_key(username, password=None, length=2048):
|
||||
def gen_ssh_key(username, password='',
|
||||
key_dir=os.path.join(BASE_DIR, 'keys/user/'),
|
||||
authorized_keys=True, home="/home", length=2048):
|
||||
"""
|
||||
generate a user ssh key in a property dir
|
||||
生成一个用户ssh密钥对
|
||||
"""
|
||||
print "gen_ssh_key" + str(time.time())
|
||||
private_key_dir = os.path.join(BASE_DIR, 'keys/jumpserver/')
|
||||
private_key_file = os.path.join(private_key_dir, username+".pem")
|
||||
public_key_dir = '/home/%s/.ssh/' % username
|
||||
public_key_file = os.path.join(public_key_dir, 'authorized_keys')
|
||||
is_dir(private_key_dir)
|
||||
is_dir(public_key_dir, username, mode=0700)
|
||||
private_key_file = os.path.join(key_dir, username)
|
||||
if os.path.isfile(private_key_file):
|
||||
os.unlink(private_key_file)
|
||||
ret = bash('ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
|
||||
|
||||
key = RSA.generate(length)
|
||||
with open(private_key_file, 'w') as pri_f:
|
||||
pri_f.write(key.exportKey('PEM', password))
|
||||
os.chmod(private_key_file, 0600)
|
||||
print "gen_ssh_pub_key" + str(time.time())
|
||||
pub_key = key.publickey()
|
||||
with open(public_key_file, 'w') as pub_f:
|
||||
pub_f.write(pub_key.exportKey('OpenSSH'))
|
||||
os.chmod(public_key_file, 0600)
|
||||
bash('chown %s:%s %s' % (username, username, public_key_file))
|
||||
print "gen_ssh_key_end" + str(time.time())
|
||||
if authorized_keys:
|
||||
auth_key_dir = os.path.join(home, username, '.ssh')
|
||||
is_dir(auth_key_dir, username, 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))
|
||||
|
||||
|
||||
def server_add_user(username, password, ssh_key_pwd, ssh_key_login_need):
|
||||
|
|
|
@ -13,5 +13,5 @@
|
|||
file: name=/home/{{ item }}/.ssh mode=700 owner={{ item }} group={{ item }} state=directory
|
||||
with_items: [ the_new_users ]
|
||||
- name: set authorizied_file
|
||||
copy: src=the_pub_key dest=/home/{{ item }}/.ssh/authorizied_keys owner={{ item }} group={{ item }} mode=600
|
||||
copy: src=KEY_DIR/{{ item }}.pub dest=/home/{{ item }}/.ssh/authorizied_keys owner={{ item }} group={{ item }} mode=600
|
||||
with_items: [ the_new_users ]
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
{% 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 class="panel blank-panel">
|
||||
<div class="panel-heading">
|
||||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li id="tab1" class=""><a href="/jperm/sys_user_list/" >查看系统用户</a></li>
|
||||
<li id="tab2" class="active"><a href="/jperm/sys_user_add/">添加系统用户</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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="">
|
||||
{% 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="username" class="col-sm-2 control-label">用户名<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="username" name="username" placeholder="Username" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">密码<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="password" name="password" placeholder="Password" type="password" class="form-control" {% if error %}value="{{ password }}" {% endif %} >
|
||||
<span class="help-block m-b-none">通常在其它硬件上使用,服务器会使用自动生成的key</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="" class="col-sm-2 control-label">推送资产组<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-4">
|
||||
<div>
|
||||
<select id="asset_groups" name="asset_groups" class="form-control" size="12" multiple>
|
||||
{% for asset_group in asset_group_all %}
|
||||
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<span class="help-block m-b-none">将在以上资产组服务器新建系统用户</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-1">
|
||||
<div class="btn-group" style="margin-top: 42px;">
|
||||
<button type="button" class="btn btn-white" onclick="move('asset_groups', 'asset_groups_select')"><i class="fa fa-chevron-right"></i></button>
|
||||
<button type="button" class="btn btn-white" onclick="move('asset_groups_select', 'asset_groups')"><i class="fa fa-chevron-left"></i> </button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3">
|
||||
<div>
|
||||
<select id="asset_groups_select" name="asset_groups_select" class="form-control m-b" size="12" multiple>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="comment" class="col-sm-2 control-label">备注<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="comment" name="comment" placeholder="Comment" type="text" class="form-control" {% if error %}value="{{ comment }}" {% endif %} >
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block self_footer_js %}
|
||||
|
||||
<script>
|
||||
$('#userForm').validator({
|
||||
timely: 2,
|
||||
theme: "yellow_right_effect",
|
||||
rules: {
|
||||
check_username: [/^\w{3,20}$/, '大小写字母数字和下划线'],
|
||||
type_m: function(element){
|
||||
return $("#M").is(":checked");
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
"username": {
|
||||
rule: "required;check_username",
|
||||
tip: "输入用户名",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"password": {
|
||||
rule: "required;length[6~50]",
|
||||
tip: "输入密码",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
}
|
||||
},
|
||||
valid: function(form) {
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,102 @@
|
|||
{% 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-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="panel blank-panel">
|
||||
<div class="panel-heading">
|
||||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li id="tab1" class="active"><a href="/jperm/sys_user_list/" >查看系统用户</a></li>
|
||||
<li id="tab2" class=""><a href="/jperm/sys_user_add/">添加系统用户</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="tab-content">
|
||||
<div id="tab-default" class="tab-pane active">
|
||||
<div class="ibox-content">
|
||||
<table class="table table-striped table-bordered table-hover " id="editable" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
<input type="checkbox" name="select_all" onclick="selectAll()">
|
||||
</th>
|
||||
<th class="text-center">用户名</th>
|
||||
<th class="text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users.object_list %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center">
|
||||
<input type="checkbox" name="selected" value="{{ user.id }}">
|
||||
</td>
|
||||
<td class="text-center"> {{ user.username }} </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>
|
||||
<a value="../user_del/?id={{ user.id }}" class="btn btn-xs btn-danger del {% if user.username == 'admin' %} disabled {% endif %}">删除</a>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block self_head_css_js %}
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('.del').click(function(){
|
||||
var row = $(this).closest('tr');
|
||||
$.get(
|
||||
$(this).attr('value'),
|
||||
{},
|
||||
function(data){
|
||||
row.remove();
|
||||
alert(data);
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
$('#del_btn').click(function(){
|
||||
var check_array = [];
|
||||
if (confirm("确定删除")) {
|
||||
$(".gradeX input:checked").each(function() {
|
||||
check_array.push($(this).attr("value"))
|
||||
});
|
||||
$.post("/juser/user_del/",
|
||||
{id: check_array.join(",")},
|
||||
function(data){
|
||||
$(".gradeX input:checked").closest("tr").remove();
|
||||
alert(data);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -36,7 +36,7 @@
|
|||
</li>
|
||||
|
||||
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail">
|
||||
<a href="/jperm/sudo_list/">命令授权</a>
|
||||
<a href="/jperm/sys_user_list/">系统用户</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>
|
||||
|
|
Loading…
Reference in New Issue