diff --git a/jperm/ansible_api.py b/jperm/ansible_api.py index e0585c9dc..d452a6028 100644 --- a/jperm/ansible_api.py +++ b/jperm/ansible_api.py @@ -285,10 +285,10 @@ class Tasks(Command): """ push the ssh authorized key to target. """ - module_args = 'user="%s" key="{{ lookup("file", "%s") }}"' % (user, key_path) + module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state=present' % (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 push_multi_key(self, **user_info): """ @@ -319,13 +319,17 @@ class Tasks(Command): return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"} - def add_user(self, username, password): + def add_user(self, username, password=''): """ add a host user. """ - encrypt_pass = sha512_crypt.encrypt(password) - module_args = 'name=%s shell=/bin/bash password=%s' % (username, encrypt_pass) - self.__run(module_args, "user", become=True) + + if password: + encrypt_pass = sha512_crypt.encrypt(password) + 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") return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"} @@ -440,8 +444,21 @@ class Tasks(Command): :return: """ module_args1 = file_path - result = self.__run(module_args1, "script") - print result + ret1 = self.__run(module_args1, "script") + module_args2 = 'visudo -c | grep "parsed OK" &> /dev/null && echo "ok" || echo "failed"' + ret2 = self.__run(module_args2, "shell") + ret2_status = [host_value.get("stdout") for host_value in ret2["result"]["contacted"].values()] + + result = {} + if not ret1["msg"]: + result["step1"] = "ok" + else: + result["msg"] = ret1["msg"] + + if not ret2["msg"] and "failed" not in ret2_status: + result["step2"] = "ok" + else: + result["msg"] = ret1["msg"] return result diff --git a/jperm/models.py b/jperm/models.py index 09cdab7de..3a280762e 100644 --- a/jperm/models.py +++ b/jperm/models.py @@ -13,16 +13,9 @@ class PermLog(models.Model): 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='') - - class PermSudo(models.Model): name = models.CharField(max_length=100, unique=True) date_added = models.DateTimeField(auto_now=True) - runas = models.CharField(max_length=200, default='root') commands = models.TextField() comment = models.CharField(max_length=100, null=True, blank=True, default='') @@ -57,10 +50,11 @@ class PermRule(models.Model): class PermPush(models.Model): - date_added = models.DateTimeField(auto_now=True) - asset = models.ManyToManyField(Asset, related_name='perm_push') - asset_group = models.ManyToManyField(AssetGroup, related_name='perm_push') - role = models.ManyToManyField(PermRole, related_name='perm_push') + asset = models.ForeignKey(Asset, related_name='perm_push') + role = models.ForeignKey(PermRole, related_name='perm_push') is_public_key = models.BooleanField(default=False) is_password = models.BooleanField(default=False) + success = models.BooleanField(default=False) + result = models.TextField() + date_added = models.DateTimeField(auto_now=True) diff --git a/jperm/perm_api.py b/jperm/perm_api.py index f2f6e903e..080f1cb39 100644 --- a/jperm/perm_api.py +++ b/jperm/perm_api.py @@ -6,8 +6,7 @@ import uuid import re from jumpserver.models import Setting -from jperm.models import PermRole -from jperm.models import PermRule +from jperm.models import PermRole, PermPush, PermRule def get_group_user_perm(ob): @@ -268,37 +267,19 @@ def get_role_info(role_id, type="all"): def get_role_push_host(role): """ - get the role push host - :return: the asset object + asset_pushed: {'success': push.success, 'key': push.is_public_key, 'password': push.is_password, + 'result': push.result} + asset_no_push: set(asset1, asset2) """ # 计算该role 所有push记录 总共推送的主机 - assets = [] - asset_groups = [] - for push in role.perm_push.all(): - assets.extend(push.asset.all()) - asset_groups.extend(push.asset_group.all()) - group_assets = [] - for asset_group in asset_groups: - group_assets.extend(asset_group.asset_set.all()) - cacl_assets = set(assets) | set(group_assets) - - # 计算所有主机 在push记录里面的 使用密码和使用秘钥状况 - result = [] - for asset in cacl_assets: - all_push = asset.perm_push.all() - if True in [push.is_password for push in all_push if role in push.role.all()]: - is_password = u"是" - else: - is_password = u"否" - if True in [push.is_public_key for push in all_push if role in push.role.all()]: - is_public_key = u"是" - else: - is_public_key = u"否" - result.append({"ip": asset.ip, - "group": ','.join([group.name for group in asset.group.all()]), - "password": is_password, - "pubkey": is_public_key}) - return result + pushs = PermPush.objects.filter(role=role) + asset_all = Asset.objects.all() + asset_pushed = {} + for push in pushs: + asset_pushed[push.asset] = {'success': push.success, 'key': push.is_public_key, 'password': push.is_password, + 'result': push.result} + asset_no_push = set(asset_all) - set(asset_pushed.keys()) + return asset_pushed, asset_no_push if __name__ == "__main__": print get_role_info(1) diff --git a/jperm/urls.py b/jperm/urls.py index 4d84ed325..1e2ccf4cd 100644 --- a/jperm/urls.py +++ b/jperm/urls.py @@ -12,7 +12,7 @@ urlpatterns = patterns('jperm.views', (r'^role/perm_role_delete/$', perm_role_delete), (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'^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), diff --git a/jperm/views.py b/jperm/views.py index 62d1c1ad0..38a003859 100644 --- a/jperm/views.py +++ b/jperm/views.py @@ -94,8 +94,8 @@ def perm_rule_add(request): # 获取需要授权的主机列表 assets_obj = [Asset.objects.get(id=asset_id) for asset_id in assets_select] asset_groups_obj = [AssetGroup.objects.get(id=group_id) for group_id in asset_groups_select] - # group_assets_obj = [asset for asset in [group.asset_set.all() for group in asset_groups_obj]] - # calc_assets = set(group_assets_obj) | set(assets_obj) + group_assets_obj = [asset for asset in [group.asset_set.all() for group in asset_groups_obj]] + calc_assets = set(group_assets_obj) | set(assets_obj) # 获取需要授权的用户列表 users_obj = [User.objects.get(id=user_id) for user_id in users_select] @@ -105,6 +105,13 @@ def perm_rule_add(request): # 获取授予的角色列表 roles_obj = [PermRole.objects.get(id=role_id) for role_id in roles_select] + need_push_asset = set() + for role in roles_obj: + asset_no_push = get_role_push_host(role=role)[1] + need_push_asset.update(set(calc_assets) - set(asset_no_push)) + if need_push_asset: + raise ServerError(u'没有推送角色 %s 的主机 %s' + % (role.name, ','.join([asset.hostname for asset in need_push_asset]))) # 仅授权成功的,写回数据库(授权规则,用户,用户组,资产,资产组,用户角色) rule = PermRule(name=rule_name, comment=rule_comment) @@ -117,7 +124,6 @@ def perm_rule_add(request): rule.save() msg = u"添加授权规则:%s" % rule.name - # 渲染数据 return HttpResponseRedirect('/jperm/rule/') except ServerError, e: error = e @@ -251,6 +257,8 @@ def perm_role_add(request): try: if get_object(PermRole, name=name): raise ServerError('已经存在该用户 %s' % name) + default = get_object(Setting, name='default') + if password: encrypt_pass = CRYPTOR.encrypt(password) else: @@ -319,7 +327,7 @@ def perm_role_detail(request): asset_groups = role_info.get("asset_groups") users = role_info.get("users") user_groups = role_info.get("user_groups") - push_info = get_role_push_host(PermRole.objects.get(id=role_id)) + pushed_asset, need_push_asset = get_role_push_host(get_object(PermRole, id=role_id)) return my_render('jperm/perm_role_detail.html', locals(), request) @@ -386,15 +394,13 @@ def perm_role_push(request): """ # 渲染数据 header_title, path1, path2 = "系统角色", "角色管理", "角色推送" - - roles = PermRole.objects.all() + role_id = request.GET.get('id') + role = get_object(PermRole, id=role_id) assets = Asset.objects.all() asset_groups = AssetGroup.objects.all() if request.method == "POST": # 获取推荐角色的名称列表 - role_ids = request.POST.getlist("roles") - # 计算出需要推送的资产列表 asset_ids = request.POST.getlist("assets") asset_group_ids = request.POST.getlist("asset_groups") @@ -422,17 +428,11 @@ def perm_role_push(request): # "password": password}) push_resource = gen_resource(calc_assets) - # 获取角色的推送方式,以及推送需要的信息 - roles_obj = [PermRole.objects.get(id=role_id) for role_id in role_ids] - role_pass = {} - role_key = {} - for role in roles_obj: - role_pass[role.name] = role.password - role_key[role.name] = os.path.join(role.key_path, 'id_rsa.pub') + logger.debug('推送role res: %s' % push_resource) # 调用Ansible API 进行推送 - password_push = request.POST.get("use_password") - key_push = request.POST.get("use_publicKey") + 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) ret = {} ret_failed = {} @@ -440,48 +440,59 @@ def perm_role_push(request): # 因为要先建立用户,所以password 是必选项,而push key是在 password也完成的情况下的 可选项 # 1. 以password 方式推送角色 if password_push: - ret["password_push"] = task.add_multi_user(**role_pass) + ret["password_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password)) if ret["password_push"].get("status") != "success": - ret_failed["step1"] == "failed" + ret_failed = ret["password_push"].get('msg') # 2. 以秘钥 方式推送角色 if key_push: - ret["password_push"] = task.add_multi_user(**role_pass) - if ret["password_push"].get("status") != "success": - ret_failed["step2-1"] = "failed" - ret["key_push"] = task.push_multi_key(**role_key) - if ret["key_push"].get("status") != "success": - ret_failed["step2-2"] = "failed" + ret["password_push"] = task.add_user(role.name) + if ret["password_push"].get("status") != "ok": + ret_failed = ret["password_push"].get('msg') + 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') # 3. 推送sudo配置文件 - role_chosen_aliase = {} # {'dev': [sudo1, sudo2], 'sa': [sudo2, sudo3]} - sudo_alias = set() # set(sudo1, sudo2, sudo3) - for role in roles_obj: - sudos = set([sudo for sudo in role.sudo.all()]) - sudo_alias.update(sudos) - role_chosen_aliase[role.name] = sudos - add_sudo_script = get_add_sudo_script(role_chosen_aliase, sudo_alias) - ret_sudo = task.push_sudo_file(add_sudo_script) + if password_push or key_push: + role_chosen_aliase = {} # {'dev': 'NETWORKING, SHUTDOWN'} + sudo_alias = set([sudo for sudo in role.sudo.all()]) # set(sudo1, sudo2, sudo3) + role_chosen_aliase[role.name] = ','.join(sudo.name for sudo in sudo_alias) + add_sudo_script = get_add_sudo_script(role_chosen_aliase, sudo_alias) + ret['sudo'] = task.push_sudo_file(add_sudo_script) - print add_sudo_script - # os.remove(add_sudo_script) + if ret['sudo'].get('msg'): + ret_failed = ret['sudo'].get('msg') + os.remove(add_sudo_script) - print ret + logger.debug('推送role结果: %s' % ret) + logger.debug('推送role错误: %s' % ret_failed) - # 结果汇总统计 - if ret_failed: - # 推送失败 - error = u"推送失败, 原因: %s 失败" % ','.join(ret_failed.keys()) + success_asset = [] + failed_asset = [] + # 推送成功 回写push表 + for asset in calc_assets: + push_check = PermPush.objects.filter(role=role, asset=asset) + if push_check: + func = push_check.update + else: + def func(**kwargs): + PermPush(**kwargs).save() + + if ret_failed.get(asset.hostname): + failed_asset.append(asset) + func(is_password=password_push, is_public_key=key_push, role=role, asset=asset, success=False, + result=ret_failed.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])) else: - # 推送成功 回写push表 - msg = u"推送系统角色: %s" % ','.join(role_chosen_aliase.keys()) - push = PermPush(is_public_key=bool(key_push), is_password=bool(password_push)) - push.save() - push.asset_group = asset_groups_obj - push.asset = calc_assets - push.role = roles_obj - push.save() - + error = u'角色 %s 推送失败 [ %s ], 推送成功 [ %s ]' % (role.name, + ','.join([asset.hostname for asset in failed_asset]), + ','.join([asset.hostname for asset in success_asset])) return my_render('jperm/perm_role_push.html', locals(), request) @@ -521,14 +532,13 @@ def perm_sudo_add(request): if request.method == "POST": # 获取参数: name, comment name = request.POST.get("sudo_name").strip() - runas = request.POST.get('sudo_runas', 'root').strip() comment = request.POST.get("sudo_comment").strip() commands = request.POST.get("sudo_commands").strip() if get_object(PermSudo, name=name): error = 'Sudo别名 %s已经存在' % name else: - sudo = PermSudo(name=name.strip(), runas=runas, comment=comment, commands=commands.strip()) + sudo = PermSudo(name=name.strip(), comment=comment, commands=commands.strip()) sudo.save() msg = u"添加Sudo命令别名: %s" % name # 渲染数据 @@ -552,11 +562,9 @@ def perm_sudo_edit(request): if request.method == "POST": name = request.POST.get("sudo_name") commands = request.POST.get("sudo_commands") - runas = request.POST.get('sudo_runas', 'root') comment = request.POST.get("sudo_comment") sudo.name = name.strip() sudo.commands = commands.strip() - sudo.runas = runas.strip() sudo.comment = comment sudo.save() @@ -583,5 +591,3 @@ def perm_sudo_delete(request): return HttpResponse(u"不支持该操作") - - diff --git a/jumpserver.conf b/jumpserver.conf index ac9506672..6297ab00a 100644 --- a/jumpserver.conf +++ b/jumpserver.conf @@ -9,7 +9,7 @@ log = debug host = 127.0.0.1 port = 3306 user = jumpserver -password = mysql1234 +password = mysql234 database = jumpserver [websocket] diff --git a/jumpserver/templatetags/mytags.py b/jumpserver/templatetags/mytags.py index 8adfb724a..2adb62deb 100644 --- a/jumpserver/templatetags/mytags.py +++ b/jumpserver/templatetags/mytags.py @@ -5,7 +5,7 @@ import ast import time from django import template -# from jperm.models import CmdGroup +from jperm.models import PermPush from jumpserver.api import * from jasset.models import AssetAlias @@ -259,3 +259,16 @@ def role_contain_which_sudos(role): sudo_names = [sudo.name for sudo in role.sudo.all()] return ','.join(sudo_names) + +@register.filter(name='get_push_info') +def get_push_info(push_id, arg): + push = get_object(PermPush, id=push_id) + if push and arg: + if arg == 'asset': + return [asset.hostname for asset in push.asset.all()] + if arg == 'asset_group': + return [asset_group.name for asset_group in push.asset_group.all()] + if arg == 'role': + return [role.name for role in push.role.all()] + else: + return [] diff --git a/juser/views.py b/juser/views.py index dc02487a7..f204a53c5 100644 --- a/juser/views.py +++ b/juser/views.py @@ -146,7 +146,7 @@ def user_add(request): error = '' msg = '' header_title, path1, path2 = '添加用户', '用户管理', '添加用户' - user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} + user_role = {'SU': u'超级管理员', 'CU': u'普通用户'} group_all = UserGroup.objects.all() if request.method == 'POST': @@ -349,7 +349,7 @@ def user_edit(request): if not user_id: return HttpResponseRedirect('/') - user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} + user_role = {'SU': u'超级管理员', 'CU': u'普通用户'} user = get_object(User, id=user_id) group_all = UserGroup.objects.all() if user: diff --git a/templates/index.html b/templates/index.html index 0d8baf9f9..0468ecbde 100644 --- a/templates/index.html +++ b/templates/index.html @@ -104,50 +104,48 @@
-
-
-
权限申请
- -
-
-

权限申请记录

- 最近十条权限申请记录信息. -
-
-
- {% if perm_apply_10 %} - {% for perm in perm_apply_10 %} -
-
- {% ifequal perm.status 0 %} - {{ perm.date_add|naturaltime }} - {% else %} - {{ perm.date_add|naturaltime }} - {% endifequal %} - {{ perm.applyer }} -{#
申请 {{ perm.bisgroup|ast_to_list }} 主机组权限
#} -{#
申请 {{ perm.asset|ast_to_list }} 主机权限
#} - {{ perm.date_add }} -
-
- {% endfor %} - {% else %} -

(暂无)

- {% endif %} -
-
-
+{#
#} +{#
#} +{#
权限申请
#} +{#
#} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{#
#} +{#
#} +{#
#} +{#

权限申请记录

#} +{# 最近十条权限申请记录信息.#} +{#
#} +{#
#} +{#
#} +{# {% if perm_apply_10 %}#} +{# {% for perm in perm_apply_10 %}#} +{#
#} +{#
#} +{# {% ifequal perm.status 0 %}#} +{# {{ perm.date_add|naturaltime }}#} +{# {% else %}#} +{# {{ perm.date_add|naturaltime }}#} +{# {% endifequal %}#} +{# {{ perm.applyer }}#} +{# {{ perm.date_add }}#} +{#
#} +{#
#} +{# {% endfor %}#} +{# {% else %}#} +{#

(暂无)

#} +{# {% endif %}#} +{#
#} +{#
#} +{#
#}
@@ -306,7 +304,7 @@
-
+{# #} {% endblock %} diff --git a/templates/jasset/asset_add.html b/templates/jasset/asset_add.html index 210d583d4..d2761a3b0 100644 --- a/templates/jasset/asset_add.html +++ b/templates/jasset/asset_add.html @@ -48,7 +48,6 @@ {{ af.ip|bootstrap_horizontal }}

Tips: 如果IP地址不填写, IP默认会设置与主机名一致

-
@@ -60,7 +59,7 @@
- +

Tips: 管理用户为root或用户拥有NOPASSWD:ALL sudo权限的用户