fix push role bug

pull/26/head
ibuler 2015-12-05 12:03:18 +08:00
parent 2829a7ad31
commit 34ccaeb10f
6 changed files with 218 additions and 185 deletions

View File

@ -7,7 +7,7 @@ from jumpserver.models import Setting
from jasset.forms import AssetForm, IdcForm
from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS
from jperm.perm_api import get_group_asset_perm
from jperm.ansible_api import Tasks, MyRunner
from jperm.ansible_api import MyRunner
from jperm.perm_api import gen_resource

View File

@ -119,8 +119,8 @@ class MyRunner(MyInventory):
super(MyRunner, self).__init__(*args, **kwargs)
self.results_raw = {}
def run(self, module_name='shell', module_args='', timeout=10, forks=10, pattern='',
sudo=False, sudo_user='root', sudo_pass=''):
def run(self, module_name='shell', module_args='', timeout=10, forks=10, pattern='*',
become=False, become_method='sudo', become_user='root', become_pass=''):
"""
run module from andible ad-hoc.
module_name: ansible module_name
@ -132,10 +132,10 @@ class MyRunner(MyInventory):
inventory=self.inventory,
pattern=pattern,
forks=forks,
become=sudo,
become_method='sudo',
become_user=sudo_user,
become_pass=sudo_pass
become=become,
become_method=become_method,
become_user=become_user,
become_pass=become_pass
)
self.results_raw = hoc.run()
return self.results_raw
@ -156,7 +156,7 @@ class MyRunner(MyInventory):
for host, info in contacted.items():
if info.get('failed'):
result['failed'][host] = info.get('msg') + info.get('stderr', '')
elif info.get('stderr'):
elif info.get('stderr') and info.get('module_name') in ['shell', 'command', 'raw']:
result['failed'][host] = info.get('stderr') + str(info.get('warnings'))
else:
result['ok'][host] = info.get('stdout')
@ -265,60 +265,21 @@ class Command(MyInventory):
return self.results_raw.get("dark")
class Tasks(Command):
class MyTask(MyRunner):
"""
this is a tasks object for include the common 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='*',
):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如
'uname -a'
"""
hoc = Runner(module_name=module_name,
module_args=module_args,
timeout=timeout,
inventory=self.inventory,
subset=group,
pattern=pattern,
forks=forks,
become=False,
)
self.results = hoc.run()
return {"msg": self.msg, "result": self.results}
@property
def msg(self):
"""
get the contacted and dark msg
"""
msg = {}
for result in ["contacted", "dark"]:
all = self.results.get(result)
for key, value in all.iteritems():
if value.get("msg"):
msg[key] = value.get("msg")
return msg
super(MyTask, self).__init__(*args, **kwargs)
def push_key(self, user, key_path):
"""
push the ssh authorized key to target.
"""
module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state=present' % (user, key_path)
self.__run(module_args, "authorized_key")
self.run("authorized_key", module_args, become=True)
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
return self.results
def push_multi_key(self, **user_info):
"""
@ -345,9 +306,9 @@ class Tasks(Command):
push the ssh authorized key to target.
"""
module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state="absent"' % (user, key_path)
self.__run(module_args, "authorized_key")
self.run("authorized_key", module_args, become=True)
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
return self.results
def add_user(self, username, password=''):
"""
@ -358,9 +319,9 @@ class Tasks(Command):
module_args = 'name=%s shell=/bin/bash password=%s' % (username, encrypt_pass)
else:
module_args = 'name=%s shell=/bin/bash' % username
self.__run(module_args, "user")
self.run("user", module_args, become=True)
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
return self.results
def add_multi_user(self, **user_info):
"""
@ -387,85 +348,10 @@ 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",)
module_args = 'name=%s state=absent remove=yes move_home=yes force=yes' % username
self.run("user", module_args, become=True)
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
def add_init_users(self):
"""
add initail users: SA, DBA, DEV
"""
results = {}
action = results["action_info"] = {}
users = {"SA": get_rand_pass(), "DBA": get_rand_pass(), "DEV": get_rand_pass()}
for user, password in users.iteritems():
ret = self.add_user(user, password)
action[user] = ret
results["user_info"] = users
return results
def del_init_users(self):
"""
delete initail users: SA, DBA, DEV
"""
results = {}
action = results["action_info"] = {}
for user in ["SA", "DBA", "DEV"]:
ret = self.del_user(user)
action[user] = ret
return results
def get_host_info(self):
"""
use the setup module get host informations
:return:
all_ip is list
processor_count is int
system_dist_version is string
system_type is string
disk is dict (device_name: device_size}
system_dist is string
processor_type is string
default_ip is string
hostname is string
product_sn is string
memory_total is int (MB)
default_mac is string
product_name is string
"""
self.__run('', 'setup')
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
setup =value.get("ansible_facts")
# get disk informations
disk_all = setup.get("ansible_devices")
disk_need = {}
for disk_name, disk_info in disk_all.iteritems():
if disk_name.startswith('sd') or disk_name.startswith('hd'):
disk_need[disk_name] = disk_info.get("size")
result[key] = {
"all_ip": setup.get("ansible_all_ipv4_addresses"),
"hostname" : setup.get("ansible_hostname"),
"default_ip": setup.get("ansible_default_ipv4").get("address"),
"default_mac": setup.get("ansible_default_ipv4").get("macaddress"),
"product_name": setup.get("ansible_product_name"),
"processor_type": ' '.join(setup.get("ansible_processor")),
"processor_count": setup.get("ansible_processor_count"),
"memory_total": setup.get("ansible_memtotal_mb"),
"disk": disk_need,
"system_type": setup.get("ansible_system"),
"system_dist": setup.get("ansible_distribution"),
"system_dist_verion": setup.get("ansible_distribution_major_version"),
"product_sn": setup.get("ansible_product_serial")
}
return {"failed": self.msg, "ok": result}
return self.results
def push_sudo_file(self, file_path):
"""
@ -473,8 +359,9 @@ class Tasks(Command):
:return:
"""
module_args1 = file_path
ret = self.__run(module_args1, "script")
return ret
self.run("script", module_args1, become=True)
print self.results_raw
return self.results
class CustomAggregateStats(callbacks.AggregateStats):

View File

@ -302,20 +302,6 @@ def get_role_push_host(role):
return asset_pushed, asset_no_push
@require_role('user')
def perm_role_get(request):
asset_id = request.GET.get('id', 0)
if asset_id:
asset = get_object(Asset, id=asset_id)
if asset:
role = user_have_perm(request.user, asset=asset)
return HttpResponse(','.join([i.name for i in role]))
else:
roles = get_group_user_perm(request.user).get('role').keys()
return HttpResponse(','.join(i.name for i in roles))
return HttpResponse('error')
if __name__ == "__main__":
print get_role_info(1)

View File

@ -11,9 +11,8 @@ from jperm.models import PermRole, PermRule, PermSudo, PermPush
from jumpserver.models import Setting
from jperm.utils import updates_dict, gen_keys, get_rand_pass, get_add_sudo_script
from jperm.ansible_api import Tasks
from jperm.ansible_api import MyTask
from jperm.perm_api import get_role_info, get_role_push_host
from jumpserver.api import my_render, get_object, CRYPTOR
@ -211,8 +210,6 @@ def perm_rule_delete(request):
# 根据rule_id 取得rule对象
rule_id = request.POST.get("id")
rule_obj = PermRule.objects.get(id=rule_id)
print rule_id, rule_obj
print rule_obj.name
rule_obj.delete()
return HttpResponse(u"删除授权规则:%s" % rule_obj.name)
else:
@ -423,25 +420,18 @@ def perm_role_push(request):
# 调用Ansible API 进行推送
password_push = True if request.POST.get("use_password") else False
key_push = True if request.POST.get("use_publicKey") else False
task = Tasks(push_resource)
task = MyTask(push_resource)
ret = {}
ret_failed = {}
# 因为要先建立用户所以password 是必选项而push key是在 password也完成的情况下的 可选项
# 1. 以password 方式推送角色
if password_push:
ret["password_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password))
if ret["password_push"].get("status") != "success":
ret_failed = ret["password_push"].get('msg')
# 2. 以秘钥 方式推送角色
# 1. 以秘钥 方式推送角色
if key_push:
ret["password_push"] = task.add_user(role.name)
if ret["password_push"].get("status") != "ok":
ret_failed = ret["password_push"].get('msg')
ret["pass_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password))
ret["key_push"] = task.push_key(role.name, os.path.join(role.key_path, 'id_rsa.pub'))
if ret["key_push"].get("status") != "ok":
ret_failed = ret["key_push"].get('msg')
# 2. 推送账号密码
elif password_push:
ret["pass_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password))
# 3. 推送sudo配置文件
if password_push or key_push:
@ -451,16 +441,32 @@ def perm_role_push(request):
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)
if ret['sudo'].get('msg'):
ret_failed = ret['sudo'].get('msg')
os.remove(add_sudo_script)
logger.debug('推送role结果: %s' % ret)
logger.debug('推送role错误: %s' % ret_failed)
success_asset = {}
failed_asset = {}
logger.debug(ret)
for push_type, result in ret.items():
if result.get('failed'):
for hostname, info in result.get('failed').items():
if hostname in failed_asset.keys():
if info in failed_asset.get(hostname):
failed_asset[hostname] += info
else:
failed_asset[hostname] = info
for push_type, result in ret.items():
if result.get('ok'):
for hostname, info in result.get('ok').items():
if hostname in failed_asset.keys():
continue
elif hostname in success_asset.keys():
if str(info) in success_asset.get(hostname, ''):
success_asset[hostname] += str(info)
else:
success_asset[hostname] = str(info)
success_asset = []
failed_asset = []
# 推送成功 回写push表
for asset in calc_assets:
push_check = PermPush.objects.filter(role=role, asset=asset)
@ -470,20 +476,18 @@ def perm_role_push(request):
def func(**kwargs):
PermPush(**kwargs).save()
if ret_failed.get(asset.hostname):
failed_asset.append(asset)
if failed_asset.get(asset.hostname):
func(is_password=password_push, is_public_key=key_push, role=role, asset=asset, success=False,
result=ret_failed.get(asset.hostname))
result=failed_asset.get(asset.hostname))
else:
success_asset.append(asset)
func(is_password=password_push, is_public_key=key_push, role=role, asset=asset, success=True)
if not failed_asset:
msg = u'角色 %s 推送成功[ %s ]' % (role.name, ','.join([asset.hostname for asset in success_asset]))
msg = u'角色 %s 推送成功[ %s ]' % (role.name, ','.join(success_asset.keys()))
else:
error = u'角色 %s 推送失败 [ %s ], 推送成功 [ %s ]' % (role.name,
','.join([asset.hostname for asset in failed_asset]),
','.join([asset.hostname for asset in success_asset]))
','.join(failed_asset.keys()),
','.join(success_asset.keys()))
return my_render('jperm/perm_role_push.html', locals(), request)
@ -586,11 +590,29 @@ def perm_sudo_delete(request):
def perm_role_recycle(request):
role_id = request.GET.get('role_id')
asset_ids = request.GET.get('asset_id').split(',')
assets = []
for asset_id in asset_ids:
asset = get_object(Asset, id=asset_id)
assets.append(asset)
role = get_object(PermRole, id=role_id)
PermPush.objects.filter(asset=asset, role=role).delete()
res = gen_resource(assets)
task = MyTask(res)
return HttpResponse('删除成功')
@require_role('user')
def perm_role_get(request):
asset_id = request.GET.get('id', 0)
if asset_id:
asset = get_object(Asset, id=asset_id)
if asset:
role = user_have_perm(request.user, asset=asset)
return HttpResponse(','.join([i.name for i in role]))
else:
roles = get_group_user_perm(request.user).get('role').keys()
return HttpResponse(','.join(i.name for i in roles))
return HttpResponse('error')

View File

@ -302,8 +302,6 @@ def upload(request):
illegal_asset = set(asset_select).issubset(set(assets))
return HttpResponse('没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset]))
for upload_file in upload_files:
file_path = '%s/%s' % (upload_dir, upload_file.name)
with open(file_path, 'w') as f:
@ -320,11 +318,11 @@ def upload(request):
filename=' '.join([f.name for f in upload_files]), type='upload', remote_ip=remote_ip,
result=ret).save()
if ret.get('failed'):
error = '上传目录: %s <br> 上传失败: [ %s ] <br>上传成功 [ %s ]' % (upload_dir,
error = u'上传目录: %s <br> 上传失败: [ %s ] <br>上传成功 [ %s ]' % (upload_dir,
', '.join(ret.get('failed').keys()),
', '.join(ret.get('ok').keys()))
return HttpResponse(error, status=500)
msg = '上传目录: %s <br> 传送成功 [ %s ]' % (upload_dir, ', '.join(ret.get('ok')).keys())
msg = u'上传目录: %s <br> 传送成功 [ %s ]' % (upload_dir, ', '.join(ret.get('ok').keys()))
return HttpResponse(msg)
return my_render('upload.html', locals(), request)
@ -345,7 +343,7 @@ def download(request):
if not set(asset_select).issubset(set(assets)):
illegal_asset = set(asset_select).issubset(set(assets))
return HttpResponse('没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset]))
return HttpResponse(u'没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset]))
res = gen_resource({'user': user, 'asset': asset_select})
runner = MyRunner(res)

View File

@ -0,0 +1,140 @@
{% 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-sm-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label label-primary"><b>{{ log.id }}</b></span>
<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>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div>
<div class="text-left">
<table class="table">
<tr>
<td class="text-navy">ID</td>
<td>{{ log.id }}</td>
</tr>
<tr>
<td class="text-navy">用户名</td>
<td>{{ log.user }}</td>
</tr>
<tr>
<td class="text-navy">来源IP</td>
<td>{{ log.remote_ip }}</td>
</tr>
<tr>
<td class="text-navy">类型</td>
<td>{{ log.type }}</td>
</tr>
<tr>
<td class="text-navy">日期</td>
<td>{{ log.datetime|date:"Y-m-d H:i:s" }}</td>
</tr>
<tr>
<td class="text-navy">文件</td>
<td>
<table class="table">
{% for file_name in file_list %}
{% if file_name %}
<tr>
<td>{{ file_name }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
</td>
</tr>
<tr>
<td class="text-navy">主机</td>
<td>
<table class="table">
{% for asset_name in assets_hostname %}
{% if asset_name %}
<tr>
<td>{{ asset_name }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-8">
<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>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content inspinia-timeline">
<div>
<div class="text-left">
<table class="table">
{% for result, info in result.items %}
{% for host, msg in info.items %}
{% ifequal result 'failed' %}
<tr>
<td class="text-navy" style="color: #ed5565">{{ host }}</td>
<td>{{ msg }}</td>
</tr>
{% else %}
<tr>
<td class="text-navy">{{ host }}</td>
<td>{{ msg }}</td>
</tr>
{% endifequal %}
{% endfor %}
{% endfor %}
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#show').click(function(){
$('#last').css('display', 'none');
$('#all').css('display', 'block');
})
})
</script>
{% endblock %}