mirror of https://github.com/jumpserver/jumpserver
bug fix
parent
bd2a3e6119
commit
e408414631
|
@ -563,7 +563,7 @@ class Nav(object):
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
print ' %s' % asset.hostname
|
print ' %s' % asset.hostname
|
||||||
print
|
print
|
||||||
print "请输入主机名、IP或ansile支持的pattern, q退出"
|
print "请输入主机名、IP或ansile支持的pattern, 多个主机:分隔, q退出"
|
||||||
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
||||||
if pattern == 'q':
|
if pattern == 'q':
|
||||||
break
|
break
|
||||||
|
@ -606,7 +606,7 @@ class Nav(object):
|
||||||
self.user_perm = get_group_user_perm(self.user)
|
self.user_perm = get_group_user_perm(self.user)
|
||||||
try:
|
try:
|
||||||
print "进入批量上传模式"
|
print "进入批量上传模式"
|
||||||
print "请输入主机名、IP或ansile支持的pattern, q退出"
|
print "请输入主机名、IP或ansile支持的pattern, 多个主机:分隔 q退出"
|
||||||
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
||||||
if pattern == 'q':
|
if pattern == 'q':
|
||||||
break
|
break
|
||||||
|
@ -659,7 +659,7 @@ class Nav(object):
|
||||||
self.user_perm = get_group_user_perm(self.user)
|
self.user_perm = get_group_user_perm(self.user)
|
||||||
try:
|
try:
|
||||||
print "进入批量下载模式"
|
print "进入批量下载模式"
|
||||||
print "请输入主机名、IP或ansile支持的pattern, q退出"
|
print "请输入主机名、IP或ansile支持的pattern, 多个主机:分隔,q退出"
|
||||||
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
||||||
if pattern == 'q':
|
if pattern == 'q':
|
||||||
break
|
break
|
||||||
|
|
|
@ -12,7 +12,11 @@ from ansible import utils
|
||||||
from passlib.hash import sha512_crypt
|
from passlib.hash import sha512_crypt
|
||||||
|
|
||||||
from utils import get_rand_pass
|
from utils import get_rand_pass
|
||||||
|
from jumpserver.api import logger
|
||||||
|
|
||||||
|
from tempfile import NamedTemporaryFile
|
||||||
|
from django.template.loader import get_template
|
||||||
|
from django.template import Context
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
@ -138,6 +142,7 @@ class MyRunner(MyInventory):
|
||||||
become_pass=become_pass
|
become_pass=become_pass
|
||||||
)
|
)
|
||||||
self.results_raw = hoc.run()
|
self.results_raw = hoc.run()
|
||||||
|
logger.debug(self.results_raw)
|
||||||
return self.results_raw
|
return self.results_raw
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -353,14 +358,33 @@ class MyTask(MyRunner):
|
||||||
|
|
||||||
return self.results
|
return self.results
|
||||||
|
|
||||||
def push_sudo_file(self, file_path):
|
@staticmethod
|
||||||
|
def gen_sudo_script(role_list, sudo_list):
|
||||||
|
# receive role_list = [role1, role2] sudo_list = [sudo1, sudo2]
|
||||||
|
# return sudo_alias={'NETWORK': '/sbin/ifconfig, /ls'} sudo_user={'user1': ['NETWORK', 'SYSTEM']}
|
||||||
|
sudo_alias = {}
|
||||||
|
sudo_user = {}
|
||||||
|
for sudo in sudo_list:
|
||||||
|
sudo_alias[sudo.name] = sudo.commands
|
||||||
|
|
||||||
|
for role in role_list:
|
||||||
|
sudo_user[role.name] = ','.join(sudo_alias.keys())
|
||||||
|
print sudo_alias, sudo_user
|
||||||
|
|
||||||
|
sudo_j2 = get_template('jperm/role_sudo.j2')
|
||||||
|
sudo_content = sudo_j2.render(Context({"sudo_alias": sudo_alias, "sudo_user": sudo_user}))
|
||||||
|
sudo_file = NamedTemporaryFile(delete=False)
|
||||||
|
sudo_file.write(sudo_content)
|
||||||
|
sudo_file.close()
|
||||||
|
return sudo_file.name
|
||||||
|
|
||||||
|
def push_sudo_file(self, role_list, sudo_list):
|
||||||
"""
|
"""
|
||||||
use template to render pushed sudoers file
|
use template to render pushed sudoers file
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
module_args1 = file_path
|
module_args1 = self.gen_sudo_script(role_list, sudo_list)
|
||||||
self.run("script", module_args1, become=True)
|
self.run("script", module_args1, become=True)
|
||||||
print self.results_raw
|
|
||||||
return self.results
|
return self.results
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,8 @@ from uuid import uuid4
|
||||||
from jumpserver.api import CRYPTOR
|
from jumpserver.api import CRYPTOR
|
||||||
from os import makedirs
|
from os import makedirs
|
||||||
|
|
||||||
from django.template.loader import get_template
|
|
||||||
from django.template import Context
|
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
|
|
||||||
|
|
||||||
from jumpserver.settings import KEY_DIR
|
from jumpserver.settings import KEY_DIR
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,45 +69,6 @@ def gen_keys(key="", key_path_dir=""):
|
||||||
return key_path_dir
|
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
|
|
||||||
|
|
||||||
|
|
||||||
def get_add_sudo_script(role_chosen_aliase, sudo_alias):
|
|
||||||
"""
|
|
||||||
get the sudo file
|
|
||||||
:param kwargs:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
sudo_j2 = get_template('jperm/role_sudo.j2')
|
|
||||||
sudo_content = sudo_j2.render(Context({"role_chosen_aliase": role_chosen_aliase,
|
|
||||||
"sudo_alias": sudo_alias}))
|
|
||||||
sudo_file = NamedTemporaryFile(delete=False)
|
|
||||||
sudo_file.write(sudo_content)
|
|
||||||
sudo_file.close()
|
|
||||||
print(sudo_file.name)
|
|
||||||
return sudo_file.name
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print gen_keys()
|
print gen_keys()
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ from jasset.models import Asset, AssetGroup
|
||||||
from jperm.models import PermRole, PermRule, PermSudo, PermPush
|
from jperm.models import PermRole, PermRule, PermSudo, PermPush
|
||||||
from jumpserver.models import Setting
|
from jumpserver.models import Setting
|
||||||
|
|
||||||
from jperm.utils import updates_dict, gen_keys, get_rand_pass, get_add_sudo_script
|
from jperm.utils import updates_dict, gen_keys, get_rand_pass
|
||||||
from jperm.ansible_api import MyTask
|
from jperm.ansible_api import MyTask
|
||||||
from jperm.perm_api import get_role_info, get_role_push_host
|
from jperm.perm_api import get_role_info, get_role_push_host
|
||||||
from jumpserver.api import my_render, get_object, CRYPTOR
|
from jumpserver.api import my_render, get_object, CRYPTOR
|
||||||
|
@ -440,13 +440,8 @@ def perm_role_push(request):
|
||||||
|
|
||||||
# 3. 推送sudo配置文件
|
# 3. 推送sudo配置文件
|
||||||
if password_push or key_push:
|
if password_push or key_push:
|
||||||
role_chosen_aliase = {} # {'dev': 'NETWORKING, SHUTDOWN'}
|
sudo_list = set([sudo for sudo in role.sudo.all()]) # set(sudo1, sudo2, sudo3)
|
||||||
sudo_alias = set([sudo for sudo in role.sudo.all()]) # set(sudo1, sudo2, sudo3)
|
ret['sudo'] = task.push_sudo_file([role], sudo_list)
|
||||||
if sudo_alias:
|
|
||||||
role_chosen_aliase[role.name] = ','.join(sudo.name for sudo in sudo_alias if sudo.name)
|
|
||||||
add_sudo_script = get_add_sudo_script(role_chosen_aliase, sudo_alias)
|
|
||||||
ret['sudo'] = task.push_sudo_file(add_sudo_script)
|
|
||||||
os.remove(add_sudo_script)
|
|
||||||
|
|
||||||
logger.debug('推送role结果: %s' % ret)
|
logger.debug('推送role结果: %s' % ret)
|
||||||
success_asset = {}
|
success_asset = {}
|
||||||
|
|
|
@ -88,8 +88,8 @@ def group_edit(request):
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
group_id = request.GET.get('id', '')
|
group_id = request.GET.get('id', '')
|
||||||
# user_group = get_object(UserGroup, id=group_id)
|
user_group = get_object(UserGroup, id=group_id)
|
||||||
user_group = UserGroup.objects.get(id=group_id)
|
# user_group = UserGroup.objects.get(id=group_id)
|
||||||
users_selected = User.objects.filter(group=user_group)
|
users_selected = User.objects.filter(group=user_group)
|
||||||
users_remain = User.objects.filter(~Q(group=user_group))
|
users_remain = User.objects.filter(~Q(group=user_group))
|
||||||
users_all = User.objects.all()
|
users_all = User.objects.all()
|
||||||
|
@ -118,7 +118,9 @@ def group_edit(request):
|
||||||
if g == user_group:
|
if g == user_group:
|
||||||
continue
|
continue
|
||||||
user.group.add(g)
|
user.group.add(g)
|
||||||
|
user_group.name = group_name
|
||||||
|
user_group.comment = comment
|
||||||
|
user_group.save()
|
||||||
except ServerError, e:
|
except ServerError, e:
|
||||||
error = e
|
error = e
|
||||||
if not error:
|
if not error:
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<form method="post" id="userForm" class="form-horizontal" action="">
|
<form method="post" id="ruleForm" class="form-horizontal" action="">
|
||||||
{% if error %}
|
{% if error %}
|
||||||
<div class="alert alert-warning text-center">{{ error }}</div>
|
<div class="alert alert-warning text-center">{{ error }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -34,27 +34,27 @@
|
||||||
<div class="alert alert-success text-center">{{ msg }}</div>
|
<div class="alert alert-success text-center">{{ msg }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username_lab" class="col-sm-2 control-label">授权名称<span class="red-fonts">*</span></label>
|
<label for="rulename" class="col-sm-2 control-label">授权名称<span class="red-fonts">*</span></label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input id="rule_name" name="rule_name" placeholder="RuleName" type="text" class="form-control" value="{{ rule.name }}">
|
<input id="rulename" name="rulename" placeholder="Rule Name" type="text" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="user" class="col-sm-2 control-label">用户<span class="red-fonts">*</span></label>
|
<label for="user" class="col-sm-2 control-label">用户</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
|
<select name="user" id="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||||
{% for user in users %}
|
{% for user in users %}
|
||||||
<option value="{{ user.id }}" {% if user in users_select %} selected {% endif %}>{{ user.name }}</option>
|
<option value="{{ user.id }}" {% if user in users_select %} selected {% endif %}>{{ user.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
<span class="help-block m-b-none">用户和用户组必选一个</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="usergroup" class="col-sm-2 control-label">用户组<span class="red-fonts">*</span></label>
|
<label for="usergroup" class="col-sm-2 control-label">用户组</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
|
<select name="usergroup" id="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||||
{% for user_group in user_groups %}
|
{% for user_group in user_groups %}
|
||||||
<option value="{{ user_group.id }}"{% if user_group in user_groups_select %} selected {% endif %}>{{ user_group.name }}</option>
|
<option value="{{ user_group.id }}"{% if user_group in user_groups_select %} selected {% endif %}>{{ user_group.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -63,18 +63,18 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="asset" class="col-sm-2 control-label">资产<span class="red-fonts">*</span></label>
|
<label for="asset" class="col-sm-2 control-label">资产</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
|
<select name="asset" id="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||||
{% for asset in assets %}
|
{% for asset in assets %}
|
||||||
<option value="{{ asset.id }}"{% if asset in assets_select %} selected {% endif %}>{{ asset.ip }}</option>
|
<option value="{{ asset.id }}"{% if asset in assets_select %} selected {% endif %}>{{ asset.ip }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
<span class="help-block m-b-none">资产和资产组必选一个</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="assetgroup" class="col-sm-2 control-label">资产组<span class="red-fonts">*</span></label>
|
<label for="assetgroup" id="assetgroup" class="col-sm-2 control-label">资产组</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
|
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||||
{% for asset_group in asset_groups %}
|
{% for asset_group in asset_groups %}
|
||||||
|
@ -86,9 +86,9 @@
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="role" class="col-sm-2 control-label">角色<span class="red-fonts">*</span></label>
|
<label for="role" class="col-sm-2 control-label">角色<span class="red-fonts">*</span></label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8" id="role_name">
|
||||||
<select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
|
<select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||||
{% for role in roles %}
|
{% for role in roles %}
|
||||||
<option value="{{ role.id }}"{% if role in roles_select %} selected {% endif %}>{{ role.name }}</option>
|
<option value="{{ role.id }}"{% if role in roles_select %} selected {% endif %}>{{ role.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="comment" class="col-sm-2 control-label">备注</label>
|
<label for="comment" class="col-sm-2 control-label">备注</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input id="role_comment" name="role_comment" placeholder="Rule Comment" type="text" class="form-control" value="{{ rule_comment }}">
|
<input id="rule_comment" name="rule_comment" placeholder="Rule Comment" type="text" class="form-control" value="{{ rule_comment }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
|
@ -118,6 +118,46 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block self_footer_js %}
|
{% block self_footer_js %}
|
||||||
<script>
|
<script>
|
||||||
|
$('#ruleForm').validator({
|
||||||
|
timely: 2,
|
||||||
|
theme: "yellow_right_effect",
|
||||||
|
rules: {
|
||||||
|
check_name: [/^\w{2,20}$/, '大小写字母数字和下划线,2-20位'],
|
||||||
|
check_user: function(){
|
||||||
|
return $('#user').val() == null
|
||||||
|
},
|
||||||
|
check_asset: function(){
|
||||||
|
return $('#asset').val() == null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fields: {
|
||||||
|
"rulename": {
|
||||||
|
rule: "required;check_name",
|
||||||
|
tip: "输入规则名称",
|
||||||
|
msg: {required: "规则名称必填"}
|
||||||
|
},
|
||||||
|
"usergroup": {
|
||||||
|
rule: "required(check_user)",
|
||||||
|
tip: "请选择用户组",
|
||||||
|
msg: {required: "用户和用户组必选一个!"}
|
||||||
|
},
|
||||||
|
"assetgroup": {
|
||||||
|
rule: "required(check_asset)",
|
||||||
|
tip: "输入资产组",
|
||||||
|
msg: {required: "资产和资产组必选一个!"}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
rule: "required",
|
||||||
|
tip: "请选择角色",
|
||||||
|
msg: {required: "必须选择角色"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valid: function(form) {
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
'.chosen-select' : {},
|
'.chosen-select' : {},
|
||||||
|
|
|
@ -7,11 +7,11 @@ tmp_file=$(mktemp /tmp/XXXXXXX)
|
||||||
# Add Command Aliases
|
# Add Command Aliases
|
||||||
add_cmd_alias() {
|
add_cmd_alias() {
|
||||||
sudo_file=$1
|
sudo_file=$1
|
||||||
{% for sudo in sudo_alias %}
|
{% for sudo_name, sudo_cmd in sudo_alias.items %}
|
||||||
if $(grep '^Cmnd_Alias {{ sudo.name }}' ${sudo_file} &> /dev/null); then
|
if $(grep '^Cmnd_Alias {{ sudo_name }}' ${sudo_file} &> /dev/null); then
|
||||||
sed -i 's@^Cmnd_Alias.*{{ sudo.name }}.*@Cmnd_Alias {{ sudo.name }} = {{ sudo.commands }}@g' ${sudo_file}
|
sed -i 's@^Cmnd_Alias.*{{ sudo_name }}.*@Cmnd_Alias {{ sudo_name }} = {{ sudo_cmd }}@g' ${sudo_file}
|
||||||
else
|
else
|
||||||
echo "Cmnd_Alias {{ sudo.name }} = {{ sudo.commands }}" >> ${sudo_file}
|
echo "Cmnd_Alias {{ sudo_name }} = {{ sudo_cmd }}" >> ${sudo_file}
|
||||||
fi
|
fi
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ add_cmd_alias() {
|
||||||
|
|
||||||
add_role_chosen() {
|
add_role_chosen() {
|
||||||
sudo_file=$1
|
sudo_file=$1
|
||||||
{% for role, alias in role_chosen_aliase.items %}
|
{% for user, alias in sudo_user.items %}
|
||||||
if $(grep '^{{ role }}.*' ${sudo_file} &> /dev/null); then
|
if $(grep '^{{ user }}.*' ${sudo_file} &> /dev/null); then
|
||||||
sed -i 's@^{{ role }}.*@{{ role }} ALL = NOPASSWD: {{ alias }}@g' ${sudo_file}
|
sed -i 's@^{{ user }}.*@{{ user }} ALL = (root) NOPASSWD: {{ alias }}@g' ${sudo_file}
|
||||||
else
|
else
|
||||||
echo "{{ role }} ALL = NOPASSWD: {{ alias }}" >> ${sudo_file}
|
echo "{{ user }} ALL = (root) NOPASSWD: {{ alias }}" >> ${sudo_file}
|
||||||
fi
|
fi
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue