diff --git a/jasset/views.py b/jasset/views.py index 8e639c3b3..57f88fdbe 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -96,7 +96,7 @@ def asset_add(request): username = request.POST.get('username') password = request.POST.get('password') port = request.POST.get('port') - password_encode = CRYPTOR.encrypt(password) + password_encode = password else: username = None port = None diff --git a/jperm/README.md b/jperm/README.md new file mode 100644 index 000000000..a5a7e026c --- /dev/null +++ b/jperm/README.md @@ -0,0 +1,12 @@ +# Jperm App + +--- + +### 模块 ansible_api + +> 使用说明 + ++ 依赖rpm安装包: ansible、 sshpass ++ 依赖pip安装包: passlib ++ 关于ansible配置: 需要启用配置文件(/etc/ansible/ansible.cfg)的 host_key_checking = False + diff --git a/jperm/ansible_api.py b/jperm/ansible_api.py new file mode 100644 index 000000000..4017cce16 --- /dev/null +++ b/jperm/ansible_api.py @@ -0,0 +1,474 @@ +# -*- coding: utf-8 -*- + + +from ansible.inventory.group import Group +from ansible.inventory.host import Host +from ansible.inventory import Inventory +from ansible.runner import Runner +from ansible.playbook import PlayBook + +from ansible import callbacks +from ansible import utils +from passlib.hash import sha512_crypt + +from utils import get_rand_pass + + +import os.path +API_DIR = os.path.dirname(os.path.abspath(__file__)) +ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks') + + + +class AnsibleError(StandardError): + """ + the base AnsibleError which contains error(required), + data(optional) and message(optional). + 存储所有Ansible 异常对象 + """ + def __init__(self, error, data='', message=''): + super(AnsibleError, self).__init__(message) + self.error = error + self.data = data + self.message = message + + +class CommandValueError(AnsibleError): + """ + indicate the input value has error or invalid. + the data specifies the error field of input form. + 输入不合法 异常对象 + """ + def __init__(self, field, message=''): + super(CommandValueError, self).__init__('value:invalid', field, message) + + +class MyInventory(object): + """ + this is my ansible inventory object. + """ + def __init__(self, resource): + """ + resource的数据格式是一个列表字典,比如 + { + "group1": { + "hosts": [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...], + "vars": {"var1": value1, "var2": value2, ...} + } + } + + 如果你只传入1个列表,这默认该列表内的所有主机属于my_group组,比如 + [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...] + """ + self.resource = resource + self.inventory = Inventory() + self.gen_inventory() + + def add_group(self, hosts, groupname, groupvars=None): + """ + add hosts to a group + """ + my_group = Group(name=groupname) + + # if group variables exists, add them to group + if groupvars: + for key, value in groupvars.iteritems(): + my_group.set_variable(key, value) + + # add hosts to group + for host in hosts: + # set connection variables + hostname = host.get("hostname") + hostport = host.get("port") + username = host.get("username") + password = host.get("password") + my_host = Host(name=hostname, port=hostport) + my_host.set_variable('ansible_ssh_host', hostname) + my_host.set_variable('ansible_ssh_port', hostport) + my_host.set_variable('ansible_ssh_user', username) + my_host.set_variable('ansible_ssh_pass', password) + # set other variables + for key, value in host.iteritems(): + if key not in ["hostname", "port", "username", "password"]: + my_host.set_variable(key, value) + # add to group + my_group.add_host(my_host) + + self.inventory.add_group(my_group) + + def gen_inventory(self): + """ + add hosts to inventory. + """ + if isinstance(self.resource, list): + self.add_group(self.resource, 'my_group') + elif isinstance(self.resource, dict): + for groupname, hosts_and_vars in self.resource.iteritems(): + self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) + + +class Command(MyInventory): + """ + this is a command object for parallel execute command. + """ + def __init__(self, *args, **kwargs): + super(Command, self).__init__(*args, **kwargs) + self.results = '' + + def run(self, command, module_name="command", timeout=5, forks=10, group='my_group'): + """ + run command from andible ad-hoc. + command : 必须是一个需要执行的命令字符串, 比如 + 'uname -a' + """ + if module_name not in ["raw", "command", "shell"]: + raise CommandValueError("module_name", + "module_name must be of the 'raw, command, shell'") + hoc = Runner(module_name=module_name, + module_args=command, + timeout=timeout, + inventory=self.inventory, + subset=group, + forks=forks + ) + self.results = hoc.run() + + if self.stdout: + return {"ok": self.stdout} + else: + msg = [] + if self.stderr: + msg.append(self.stderr) + if self.dark: + msg.append(self.dark) + return {"failed": msg} + + @property + def raw_results(self): + """ + get the ansible raw results. + """ + return self.results + + @property + def exec_time(self): + """ + get the command execute time. + """ + result = {} + all = self.results.get("contacted") + for key, value in all.iteritems(): + result[key] = { + "start": value.get("start"), + "end" : value.get("end"), + "delta": value.get("delta"),} + return result + + @property + def stdout(self): + """ + get the comamnd standard output. + """ + result = {} + all = self.results.get("contacted") + for key, value in all.iteritems(): + result[key] = value.get("stdout") + return result + + @property + def stderr(self): + """ + get the command standard error. + """ + result = {} + all = self.results.get("contacted") + for key, value in all.iteritems(): + result[key] = { + "stderr": value.get("stderr"), + "warnings": value.get("warnings"),} + return result + + @property + def dark(self): + """ + get the dark results. + """ + return self.results.get("dark") + + +class Tasks(Command): + """ + 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='my_group'): + """ + 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, + forks=forks + ) + + self.results = hoc.run() + + @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 + + def push_key(self, user, key_path): + """ + push the ssh authorized key to target. + """ + module_args = 'user="%s" key="{{ lookup("file", "%s") }}"' % (user, key_path) + self.__run(module_args, "authorized_key") + + return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"} + + def del_key(self, user, key_path): + """ + 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") + + return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"} + + 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") + + return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"} + + def add_multi_user(self, *args): + """ + add multi user + :param args: + user + :return: + """ + results = {} + users = {} + action = results["action_info"] = {} + for user in args: + users[user] = 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_user(self, username): + """ + delete a host user. + """ + module_args = 'name=%s state=absent remove=yes move_home=yes force=yes' % (username) + self.__run(module_args, "user") + + 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 {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result} + + + + +class CustomAggregateStats(callbacks.AggregateStats): + """ + Holds stats about per-host activity during playbook runs. + """ + def __init__(self): + super(CustomAggregateStats, self).__init__() + self.results = [] + + def compute(self, runner_results, setup=False, poll=False, + ignore_errors=False): + """ + Walk through all results and increment stats. + """ + super(CustomAggregateStats, self).compute(runner_results, setup, poll, + ignore_errors) + + self.results.append(runner_results) + + + def summarize(self, host): + """ + Return information about a particular host + """ + summarized_info = super(CustomAggregateStats, self).summarize(host) + + # Adding the info I need + summarized_info['result'] = self.results + + return summarized_info + + +class MyPlaybook(MyInventory): + """ + this is my playbook object for execute playbook. + """ + def __init__(self, *args, **kwargs): + super(MyPlaybook, self).__init__(*args, **kwargs) + + + def run(self, playbook_relational_path, extra_vars=None): + """ + run ansible playbook, + only surport relational path. + """ + stats = callbacks.AggregateStats() + playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) + runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) + playbook_path = os.path.join(ANSIBLE_DIR, playbook_relational_path) + + pb = PlayBook( + playbook = playbook_path, + stats = stats, + callbacks = playbook_cb, + runner_callbacks = runner_cb, + inventory = self.inventory, + extra_vars = extra_vars, + check=False) + + self.results = pb.run() + + @property + def raw_results(self): + """ + get the raw results after playbook run. + """ + return self.results + + +class App(MyPlaybook): + """ + this is a app object for inclue the common playbook. + """ + def __init__(self, *args, **kwargs): + super(App, self).__init__(*args, **kwargs) + + +if __name__ == "__main__": + pass + +# resource = { +# "group1": { +# "hosts": [{"hostname": "127.0.0.1", "port": "22", "username": "root", "password": "xxx"},], +# "vars" : {"var1": "value1", "var2": "value2"}, +# }, +# } +# command = Command(resource) +# print command.run("who", group="group1") + + # resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}] + # task = Tasks(resource) + # print task.get_host_info() + +# playbook = MyPlaybook(resource) +# playbook.run('test.yml') +# print playbook.raw_results + +# task = Tasks(resource) + # print task.add_user('test', 'mypass') +# print task.del_user('test') +# print task.push_key('root', '/root/.ssh/id_rsa.pub') +# print task.del_key('root', '/root/.ssh/id_rsa.pub') + +# task = Tasks(resource) +# print task.add_init_users() +# print task.del_init_users() + + diff --git a/jperm/models.py b/jperm/models.py index b86ddd433..2bcea14e3 100644 --- a/jperm/models.py +++ b/jperm/models.py @@ -1,8 +1,8 @@ import datetime from django.db import models -from juser.models import User, UserGroup from jasset.models import Asset, AssetGroup +from juser.models import User, UserGroup class PermLog(models.Model): @@ -19,3 +19,27 @@ class SysUser(models.Model): comment = models.CharField(max_length=100, null=True, blank=True, default='') +class PermRole(models.Model): + name = models.CharField(max_length=100, unique=True) + comment = models.CharField(max_length=100, null=True, blank=True, default='') + password = models.CharField(max_length=100) + key_path = models.CharField(max_length=100) + date_added = models.DateTimeField(auto_now=True) + + def __unicode__(self): + return self.name + + +class PermRule(models.Model): + date_added = models.DateTimeField(auto_now=True) + name = models.CharField(max_length=100) + comment = models.CharField(max_length=100) + asset = models.ManyToManyField(Asset, related_name='perm_rule') + asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule') + user = models.ManyToManyField(User, related_name='perm_rule') + user_group = models.ManyToManyField(UserGroup, related_name='perm_rule') + role = models.ManyToManyField(PermRole, related_name='perm_rule') + ssh_type = models.BooleanField() + + def __unicode__(self): + return self.name \ No newline at end of file diff --git a/jperm/perm_api.py b/jperm/perm_api.py index ccfcbb6b4..c04aeda52 100644 --- a/jperm/perm_api.py +++ b/jperm/perm_api.py @@ -1,6 +1,6 @@ # coding: utf-8 -from jasset.models import * + from jumpserver.api import * import uuid import re @@ -9,6 +9,8 @@ from jumpserver.tasks import playbook_run from jumpserver.models import Setting from jperm.models import PermLog +from jperm.models import PermRole + def get_object_list(model, id_list): """根据id列表获取对象列表""" @@ -281,8 +283,62 @@ def push_user(user, asset_groups_id): return results - - +def get_role_info(role_id, type="all"): + """ + 获取role对应的一些信息 + :return: 返回值 均为对象列表 + """ + # 获取role对应的授权规则 + role_obj = PermRole.objects.get(id=role_id) + rules_obj = role_obj.perm_rule.all() + # 获取role 对应的用户 和 用户组 + # 获取role 对应的主机 和主机组 + users_obj = [] + assets_obj = [] + user_groups_obj = [] + group_users_obj = [] + asset_groups_obj = [] + group_assets_obj = [] + for rule in rules_obj: + for user in rule.user.all(): + users_obj.append(user) + for asset in rule.asset.all(): + assets_obj.append(asset) + for user_group in rule.user_group.all(): + user_groups_obj.append(user_group) + for user in user_group.user_set.all(): + group_users_obj.append(user) + for asset_group in rule.asset_group.all(): + asset_groups_obj.append(asset_group) + for asset in asset_group.asset_set.all(): + group_assets_obj.append(asset) + + calc_users = set(users_obj) | set(group_users_obj) + calc_assets = set(assets_obj) | set(group_assets_obj) + + if type == "all": + return {"rules": rules_obj, + "users": list(calc_users), + "user_groups": user_groups_obj, + "assets": list(calc_assets), + "asset_groups": asset_groups_obj, + } + elif type == "rule": + return rules_obj + elif type == "user": + return calc_users + elif type == "user_group": + return user_groups_obj + elif type == "asset": + return calc_assets + elif type == "asset_group": + return asset_groups_obj + else: + return u"不支持的查询" + + +if __name__ == "__main__": + print get_role_info(1) diff --git a/jperm/playbooks/add_init_users/add_users.yml b/jperm/playbooks/add_init_users/add_users.yml new file mode 100644 index 000000000..c4ff86d4f --- /dev/null +++ b/jperm/playbooks/add_init_users/add_users.yml @@ -0,0 +1,12 @@ +--- + +- hosts: 'add_users_group' + gather_facts: no + tasks: + - name: add SA user + command: uname -a + + + + + diff --git a/jperm/playbooks/test.yml b/jperm/playbooks/test.yml new file mode 100644 index 000000000..1e448e445 --- /dev/null +++ b/jperm/playbooks/test.yml @@ -0,0 +1,9 @@ +--- + +- hosts: test + gather_facts: no + tasks: + - name: just for test + command: uname -a + + diff --git a/jperm/role_keys/keys-1703ab96bd964893b13d22fd3a8e8318/id_rsa b/jperm/role_keys/keys-1703ab96bd964893b13d22fd3a8e8318/id_rsa new file mode 100644 index 000000000..381d06d04 --- /dev/null +++ b/jperm/role_keys/keys-1703ab96bd964893b13d22fd3a8e8318/id_rsa @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/jperm/role_keys/keys-1703ab96bd964893b13d22fd3a8e8318/id_rsa.pub b/jperm/role_keys/keys-1703ab96bd964893b13d22fd3a8e8318/id_rsa.pub new file mode 100644 index 000000000..2bc15d96c --- /dev/null +++ b/jperm/role_keys/keys-1703ab96bd964893b13d22fd3a8e8318/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDXDRoQwHevjEVqM2JeVgkADM2aVxEm/yQHCpqYqREe0xGGrSSCykEZGp+O+q5FRZwFEgbZkCykJRrI3+3kEr6zB83N3P2oy/qd0pRTkA0tS50uctQA4aIp9kyOQOKLx8Uttmta0+nLwYKBSSPgJPL1xwC+sVMVvMwsIXyWGzgIWV0KZIrjNYjgEpxU0cQ7pJLXCrw5dM+fMdWvP9MDyMfX5iYZwIaYwnnTY1qO+fNewDbiFSDTo5AzcYnAUsNsRjOqWrNazMEB3o6ZoH8fANlJCJ5Jgeu/IV6UcRAYGYXq924I6AwTVENiDVf3o1lfBvAqTmNfIo25TgZCzewFGl0cuRdKVP6j0qps6N1ZBRVE8NtT4fmg8gP05OGHzz9j8rsPzCpsnQXByYJ927u7ypIm2+xCAhvqElsyJeR5yFs9J9SFa6ix9UzO2hEhO0ypU8ioNU99DbMEhZ4jXwRl63sK5AWUzf3akNGzUDLlttw86SIjV9dt6kOyhKpE8oVVB56DrmHx76uC0Dd75QojDyQQUnLX+pd9OngCCIu+VVWB175+LhDduDRBIrWsFsOciqzCS4LwB5rQFj/6dikfDDKt++M5qOzLeVnnKcMGucH8uHK8JVEB8yZMhsTkha4vxvrh1XsoTxwIqSs9JbUVI2ZjARSO+t8JU4meSV/HL+QeCQ== \ No newline at end of file diff --git a/jperm/role_keys/keys-730baf8ef88642c68e7372814d49b5ad/id_rsa b/jperm/role_keys/keys-730baf8ef88642c68e7372814d49b5ad/id_rsa new file mode 100644 index 000000000..04a1e569c --- /dev/null +++ b/jperm/role_keys/keys-730baf8ef88642c68e7372814d49b5ad/id_rsa @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/jperm/role_keys/keys-730baf8ef88642c68e7372814d49b5ad/id_rsa.pub b/jperm/role_keys/keys-730baf8ef88642c68e7372814d49b5ad/id_rsa.pub new file mode 100644 index 000000000..b776e95a4 --- /dev/null +++ b/jperm/role_keys/keys-730baf8ef88642c68e7372814d49b5ad/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5NOm3k5bZLzjsM1YhHskQUvNsk9tGwYTx7+UQ1o1HBJ00C05f+e6FwfyG0wWjVS+WRLVE95JrqLhOKzOFHmxBuA4eA+rSQewjljkJH35ZYhcuqUSpGTU7mSVgQaE7iSJxTfu0vnydsWYbP9IW04LmX5tg2OC69LL5M0NE+LFm07m7rAZTfXpTLs3p4zCKKIfu7jVXtnCwnd3dc5oJpbumuqci2MPKvl4vTIGBBJz3MUqYFxSvsTvBPDop4oV738mso6wuFQQNvVFvt+BCelBkws3Im3Ij0his6OVROAkzw8MLTty3VSPfVcmHM6IEuD/q2GacQafK+BSTADkpmIjyJEKf5U6vftjwW18/rLMJ/CrbFEYigSmNQMSwkY/uOwSzxAPHrW37WA7fxybR8T7o895ELisUd3EhS8al8W4A0QVmkZ+l09uaHW/BrxJ8TuJSPTTfU++vCPfmDb3HQ5A9KH+yO9k8IHuFY5OFwuRGURsUx0kMV8D4YpbsAjwA0xyGw+20zFHC49bgfZj26/tOV2GIPfW9JXR5GXeFgGR9j3QJc6QXJQXgPhLRDzrhtAlyV/iqOeXHOhyq/73lIRu3FWu4IuVuIoIcUQRQfW67ihifywQxIPjlRo6vgXND4J7ugVPZPwHJZ0mCimtMj3vOQ9E6XOFim3+v4dH8M0GZpQ== \ No newline at end of file diff --git a/jperm/role_keys/keys-c57f9962efc94388b783f25d1ebe8a5e/id_rsa b/jperm/role_keys/keys-c57f9962efc94388b783f25d1ebe8a5e/id_rsa new file mode 100644 index 000000000..affaf8328 --- /dev/null +++ b/jperm/role_keys/keys-c57f9962efc94388b783f25d1ebe8a5e/id_rsa @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/jperm/role_keys/keys-c57f9962efc94388b783f25d1ebe8a5e/id_rsa.pub b/jperm/role_keys/keys-c57f9962efc94388b783f25d1ebe8a5e/id_rsa.pub new file mode 100644 index 000000000..374e2205b --- /dev/null +++ b/jperm/role_keys/keys-c57f9962efc94388b783f25d1ebe8a5e/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDBlmj6CGfjmP+1pPxaH5otomnU6ShYLs0Oxo19FpzCsWnSstFZMHv7So3zH0l3qvyfqxQzG38T7rkOwu0Ksdp7I6E7Qqov6GxONpsdpOQQisYgdzMdWzpJ2M+fEru/68QCiKCdLs2PUP3T7JwgIf3S0Vqi+qBxGs/aKALL8m2bpjp8Nvo0TVKdEH6LtpYJ/L1gfrMRSIf/Crt9JEjo3GGeN/U94WCU4iBunZL37g/oQ6U+RlylxFiDrrITBYA1cdXGAEY8ts5lvypKGCU7JFHW3YLv6ZlBZud16y8C9J1RjxSTh9RZc6w1p1j4b1hjyNAWSgHLvlCQEo5TKVMMTGx/sR+yVGR1gL8Cr2cPNJoXeDJhKjqlKYCYIdNLFJHx68C+A5ONYrANeHZbCQwsIgZLqD5Zd5nUxC/5z+5y2RU29SuqNktVeGkDpeofn0cQNH2RYZAKdA+EWnMeebr+zgNloXyp9SgR0loPUMk3dXwiWg714DhUoM3HhE2JhJwhyamFKPd13t5mokpLSMzBIae+o84iFDy5MplFASf66k5ZhnQ4/M9QIB6DgyJmo20HN4PvNg8Wbsz06iPbJqYBP4LgaooKQh5QitrvvQg4KZ/mi8jXBsrbeONxcbVlCuFQ3DUZ3MghGx65k/aGDrDk0nuE8p9iDrl8FKf+wgwS4+fMpw== \ No newline at end of file diff --git a/jperm/role_keys/keys-c7ac2df748254fae992b6081d8351ec3/id_rsa b/jperm/role_keys/keys-c7ac2df748254fae992b6081d8351ec3/id_rsa new file mode 100644 index 000000000..2ac8750d4 --- /dev/null +++ b/jperm/role_keys/keys-c7ac2df748254fae992b6081d8351ec3/id_rsa @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/jperm/role_keys/keys-c7ac2df748254fae992b6081d8351ec3/id_rsa.pub b/jperm/role_keys/keys-c7ac2df748254fae992b6081d8351ec3/id_rsa.pub new file mode 100644 index 000000000..c28632239 --- /dev/null +++ b/jperm/role_keys/keys-c7ac2df748254fae992b6081d8351ec3/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCcN2e3DZBEWLZcw/20Mo39H8leTUhXshy7JAriAoJoDfiMAy2fqhE3RbvipD3xcKcYWzrX9lEfp6mw1PyStVbcy7NqJ0spMnnNSQpqA0T2K2ySeVzVOfMhUHQOsyraVG7HizvtTHNzFqBOvucxdfEaCYKw+NWDsRCOIn9VjBUjK4fnL2qxeOiWP9ZsiOYSNH0wkhJYPjx0vPxVLbbDnOl4fSU+Do/bIeq0TZ4jY7XP9ctCSxQVztZCvR70AZBei5PpB9kii/CbsiRgprj9r8wz/TrfjiWTt+J0cBjpschDvOpuVXNMqgD+WF0408XJgXsKatmwRl6eQc86TtpKMsvhj+R3cF3Fj2Q8fJFKGmoHHbG3V3Z2lc2KwvjcjDWwy2/tY8bT9uLDQZYLxEGV+Mjbux/qDytMC5vWXKXVm0J7FBrWy8RqhWb+lTAm7nH1gSfAkrlHZRyHz49bMUwkajDFS9QcBmd0kJ/MDIGsiNxg+MFQrJzXkSw8QHhXWRDDNHu4eh5rPbYwPVNobonkBy3Jf0WPB75qumE7JtoHLKcRyk2zWEDwSrVZ9Z8/faaFh9AMVkP++WCg5R+alovn906zcXZei0Nx91q7+nki2RMfP+uZsRWJllCiZz6GfNp6Ry8vHfJ2K58uKCH0OEluoN/14wVM+RaEER+F0Ceo0QyDaQ== \ No newline at end of file diff --git a/jperm/template_filter.py b/jperm/template_filter.py new file mode 100644 index 000000000..e69de29bb diff --git a/jperm/urls.py b/jperm/urls.py index 3892407c1..aa80f7f75 100644 --- a/jperm/urls.py +++ b/jperm/urls.py @@ -2,13 +2,22 @@ from django.conf.urls import patterns, include, url from jperm.views import * urlpatterns = patterns('jperm.views', - (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'^rule/$', perm_rule_list), + (r'^perm_rule_add/$', perm_rule_add), + (r'^perm_rule_detail/$', perm_rule_detail), + (r'^perm_rule_edit/$', perm_rule_edit), + (r'^perm_rule_delete/$', perm_rule_delete), + (r'^role/$', perm_role_list), + (r'^role/perm_role_add/$', perm_role_add), + (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'^log/$', log), (r'^sys_user_add/$', sys_user_add), - (r'^sys_user_list/$', sys_user_list), + (r'^perm_user_list/$', sys_user_list), (r'^sys_user_del/$', sys_user_del), (r'^sys_user_edit/$', sys_user_edit), ) diff --git a/jperm/utils.py b/jperm/utils.py new file mode 100644 index 000000000..e7826f59e --- /dev/null +++ b/jperm/utils.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- + +import random +import os.path + +from Crypto.PublicKey import RSA +from os import chmod, mkdir +from uuid import uuid4 + +PERM_DIR = os.path.dirname(os.path.abspath(__file__)) +KEY_DIR = os.path.join(PERM_DIR, 'role_keys') + + +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 + + +def updates_dict(*args): + """ + surport update multi dict + """ + result = {} + for d in args: + result.update(d) + return result + + +def gen_keys(): + """ + 在KEY_DIR下创建一个 uuid命名的目录, + 并且在该目录下 生产一对秘钥 + :return: 返回目录名(uuid) + """ + key_basename = "keys-" + uuid4().hex + key_path_dir = os.path.join(KEY_DIR, key_basename) + mkdir(key_path_dir, 0700) + + key = RSA.generate(4096) + private_key = os.path.join(key_path_dir, 'id_rsa') + public_key = os.path.join(key_path_dir, 'id_rsa.pub') + with open(private_key, 'w') as content_file: + content_file.write(key.exportKey('PEM')) + with open(public_key, 'w') as content_file: + content_file.write(key.publickey().exportKey('OpenSSH')) + + return key_path_dir + + + + +if __name__ == "__main__": + print gen_keys() + + diff --git a/jperm/views.py b/jperm/views.py index 2e910e025..a9df09790 100644 --- a/jperm/views.py +++ b/jperm/views.py @@ -1 +1,493 @@ -# # coding: utf-8 # import sysuser # # reload(sysuser) # sysuser.setdefaultencoding('utf8') # # from django.shortcuts import render_to_response # from django.template import RequestContext # from jperm.models import Perm, SudoPerm, CmdGroup, Apply from django.db.models import Q from jumpserver.api import * from jperm.perm_api import * from jperm.models import PermLog as Log from jperm.models import SysUser from juser.user_api import gen_ssh_key @require_role('admin') def perm_user_list(request): header_title, path1, path2 = '用户授权', '授权管理', '用户授权' keyword = request.GET.get('search', '') users_list = User.objects.all() # 获取所有用户 if keyword: users_list = users_list.filter(Q(name=keyword) | Q(username=keyword)) # 搜索 users_list, p, users, page_range, current_page, show_first, show_end = pages(users_list, request) # 分页 return my_render('jperm/perm_user_list.html', locals(), request) @require_role('admin') def perm_user_edit(request): header_title, path1, path2 = '用户授权', '授权管理', '授权更改' user_id = request.GET.get('id', '') user = get_object(User, id=user_id) asset_all = Asset.objects.all() # 获取所有资产 asset_group_all = AssetGroup.objects.all() # 获取所有资产组 asset_permed = user.asset.all() # 获取授权的资产对象列表 asset_group_permed = user.asset_group.all() # 获取授权的资产组对象列表 if request.method == 'GET' and user: assets = [asset for asset in asset_all if asset not in asset_permed] # 获取没有授权的资产对象列表 asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed] # 同理 return my_render('jperm/perm_user_edit.html', locals(), request) elif request.method == 'POST' and user: asset_id_select = request.POST.getlist('asset_select', []) # 获取选择的资产id列表 asset_group_id_select = request.POST.getlist('asset_groups_select', []) # 获取选择的资产组id列表 asset_select = get_object_list(Asset, asset_id_select) asset_group_select = get_object_list(AssetGroup, asset_group_id_select) asset_new = list(set(asset_select) - set(asset_permed)) # 计算的得到新授权的资产对象列表 asset_del = list(set(asset_permed) - set(asset_select)) # 计算得到回收权限的资产对象列表 asset_group_new = list(set(asset_group_select) - set(asset_group_permed)) # 新授权的资产组对象列表 asset_group_del = list(set(asset_group_permed) - set(asset_group_select)) # 回收的资产组对象列表 for asset_group in asset_group_new: asset_new.extend(asset_group.asset_set.all()) for asset_group in asset_group_del: asset_del.extend(asset_group.asset_set.all()) perm_info = { 'action': 'perm user edit: ' + user.name, 'del': {'users': [user], 'assets': asset_del}, 'new': {'users': [user], 'assets': asset_new} } print perm_info try: results = perm_user_api(perm_info) # 通过API授权或回收 except ServerError, e: return HttpResponse(e) unreachable_asset = [] failures_asset = [] for ip in results.get('unreachable'): unreachable_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) for ip in results.get('failures'): failures_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) failures_asset.extend(unreachable_asset) # 失败的授权要统计 for asset in failures_asset: if asset in asset_select: asset_select.remove(asset) else: asset_select.append(asset) user.asset = asset_select user.asset_group = asset_group_select user.save() # 保存到数据库 return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") else: return HttpResponse('输入错误') @require_role('admin') def perm_group_list(request): header_title, path1, path2 = '用户组授权', '授权管理', '用户组授权' keyword = request.GET.get('search', '') user_groups_list = UserGroup.objects.all() if keyword: request = user_groups_list.filter(Q(name=keyword) | Q(comment=keyword)) user_groups_list, p, user_groups, page_range, current_page, show_first, show_end = pages(user_groups_list, request) return my_render('jperm/perm_group_list.html', locals(), request) @require_role('admin') def perm_group_edit(request): header_title, path1, path2 = '用户组授权', '授权管理', '授权更改' user_group_id = request.GET.get('id', '') user_group = get_object(UserGroup, id=user_group_id) asset_all = Asset.objects.all() asset_group_all = AssetGroup.objects.all() asset_permed = user_group.asset.all() # 获取授权的资产对象列表 asset_group_permed = user_group.asset_group.all() # 获取授权的资产组对象列表 if request.method == 'GET' and user_group: assets = [asset for asset in asset_all if asset not in asset_permed] asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed] return my_render('jperm/perm_group_edit.html', locals(), request) elif request.method == 'POST' and user_group: asset_id_select = request.POST.getlist('asset_select', []) asset_group_id_select = request.POST.getlist('asset_groups_select', []) asset_select = get_object_list(Asset, asset_id_select) asset_group_select = get_object_list(AssetGroup, asset_group_id_select) asset_new = list(set(asset_select) - set(asset_permed)) # 计算的得到新授权的资产对象列表 asset_del = list(set(asset_permed) - set(asset_select)) # 计算得到回收权限的资产对象列表 asset_group_new = list(set(asset_group_select) - set(asset_group_permed)) # 新授权的资产组对象列表 asset_group_del = list(set(asset_group_permed) - set(asset_group_select)) # 回收的资产组对象列表 users = user_group.user_set.all() perm_info = { 'action': 'perm group edit: ' + user_group.name, 'del': {'users': users, 'assets': asset_del}, 'new': {'users': users, 'assets': asset_new} } results = perm_user_api(perm_info) unreachable_asset = [] failures_asset = [] for ip in results.get('unreachable'): unreachable_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) for ip in results.get('failures'): failures_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) failures_asset.extend(unreachable_asset) # 失败的授权要统计 for asset in failures_asset: if asset in asset_select: asset_select.remove(asset) else: asset_select.append(asset) user_group.asset = asset_select user_group.asset_group = asset_group_select user_group.save() # 保存到数据库 return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") else: return HttpResponse('输入错误') def log(request): header_title, path1, path2 = '授权记录', '授权管理', '授权记录' log_all = Log.objects.all().order_by('-datetime') log_all, p, logs, page_range, current_page, show_first, show_end = pages(log_all, request) return my_render('jperm/perm_log.html', locals(), request) def sys_user_add(request): asset_group_all = AssetGroup.objects.all() if request.method == 'POST': username = request.POST.get('username', '') password = request.POST.get('password', '') asset_groups_id = request.POST.getlist('asset_groups_select', []) comment = request.POST.get('comment') sys_user = SysUser(username=username, password=password, comment=comment) sys_user.save() gen_ssh_key(username, key_dir=os.path.join(SSH_KEY_DIR, 'sysuser'), authorized_keys=False) results = push_user(sys_user, asset_groups_id) return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") return my_render('jperm/sys_user_add.html', locals(), request) def sys_user_list(request): users_list = SysUser.objects.all() users_list, p, users, page_range, current_page, show_first, show_end = pages(users_list, request) return my_render('jperm/sys_user_list.html', locals(), request) def sys_user_edit(request): pass def sys_user_del(request): pass \ No newline at end of file +# -*- coding: utf-8 -*- + + +from django.db.models import Q +from jumpserver.api import * +from jperm.perm_api import * +from jperm.models import PermLog as Log +from jperm.models import SysUser +from juser.user_api import gen_ssh_key + + +from juser.models import User, UserGroup +from jasset.models import Asset, AssetGroup +from jperm.models import PermRole, PermRule + +from jperm.utils import updates_dict, gen_keys, get_rand_pass +from jperm.ansible_api import Tasks +from jperm.perm_api import get_role_info + +from jumpserver.api import my_render, get_object + + + +@require_role('admin') +def perm_rule_list(request): + """ + 用户授权视图: + 该视图的模板包含2部分: + 1. block 部分:{% block content %} + rander_content 为渲染数据 + 2. include 部分:{% include 'nav_cat_bar.html' %} + rander_nav 为渲染数据 + """ + data_nav = {"header_title": "授权规则", "path1": "规则管理", "path2": "查看规则"} + + # 获取所有规则 + rules_list = PermRule.objects.all() + + + # TODO: 搜索和分页 + keyword = request.GET.get('search', '') + if keyword: + rules_list = rules_list.filter(Q(name=keyword)) + + rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request) + data_content = {"rules": rules_list} + + render_data = updates_dict(data_nav, data_content) + + return my_render('jperm/perm_rule_list.html', render_data, request) + + +@require_role('admin') +def perm_rule_detail(request): + """ + 用户详情视图: + 该视图的模板包含2部分: + 1. block 部分:{% block content %} + rander_content 为渲染数据 + 2. include 部分:{% include 'nav_cat_bar.html' %} + rander_nav 为渲染数据 + """ + data_nav = {"header_title": "授权规则", "path1": "授权管理", "path2": "规则详情"} + + # 根据rule_id 取得rule对象 + rule_id = request.GET.get("id") + rule_obj = PermRule.objects.get(id=rule_id) + user_obj = rule_obj.user.all() + asset_obj = rule_obj.asset.all() + + roles_name = [role.name for role in rule_obj.role.all()] + data_content = {"roles_name": ','.join(roles_name), "rule": rule_obj, "users": user_obj, "assets": asset_obj} + + render_data = updates_dict(data_nav, data_content) + + return my_render('jperm/perm_rule_detail.html', render_data, request) + + +@require_role('admin') +def perm_rule_add(request): + """ + + :param request: + :return: + """ + data_nav = {"header_title": "授权规则", "path1": "授权管理", "path2": "添加规则"} + + if request.method == 'GET': + # 获取所有 用户,用户组,资产,资产组,用户角色, 用于添加授权规则 + users = User.objects.all() + user_groups = UserGroup.objects.all() + assets = Asset.objects.all() + asset_groups = AssetGroup.objects.all() + roles = PermRole.objects.all() + + data_content = {"users": users, "user_groups": user_groups, + "assets": assets, "asset_groups": asset_groups, + "roles": roles} + render_data = updates_dict(data_nav, data_content) + return my_render('jperm/perm_rule_add.html', render_data, request) + + elif request.method == 'POST': + # 获取用户选择的 用户,用户组,资产,资产组,用户角色 + users_select = request.POST.getlist('user', []) + user_groups_select = request.POST.getlist('usergroup', []) + assets_select = request.POST.getlist('asset', []) + asset_groups_select = request.POST.getlist('assetgroup', []) + roles_select = request.POST.getlist('role', []) + rule_name = request.POST.get('rulename') + rule_comment = request.POST.get('comment') + + # 获取需要授权的主机列表 + assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select] + asset_groups_obj = [AssetGroup.objects.get(name=group) for group 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) + + # 获取需要授权的用户列表 + users_obj = [User.objects.get(name=user) for user in users_select] + user_groups_obj = [UserGroup.objects.get(name=group) for group in user_groups_select] + group_users_obj = [user for user in [group.user_set.all() for group in user_groups_obj]] + calc_users = set(group_users_obj) | set(users_obj) + + # 获取授予的角色列表 + roles_obj = [PermRole.objects.get(name=role) for role in roles_select] + + # 调用Ansible API 执行授权 资源---Role---用户 + # 生成Inventory, 这里需要向CMDB 获取认证信息(1. password, 2, key) + hosts = [{"hostname": asset.ip, + "port": asset.port, + "username": asset.username, + "password": asset.password} for asset in calc_assets] + # 获取需要授权的角色名称 + roles = [role.name for role in roles_obj] + # 调用Ansible API 执行 password方式的授权 TODO: Surport sudo + tasks = Tasks(hosts) + ret = tasks.add_multi_user(*roles) + # TODO: 调用Ansible API 执行 key方式的授权 + + # 计算授权成功和授权失败的主机 TODO: 记录成功和失败 + perm_sucess = {} + perm_failed = {} + for role, status in ret.get('action_info').iteritems(): + if status['status'] == 'failed': + failed_ip = status['msg'].keys() + perm_sucess[role] = [asset for asset in calc_assets if asset.ip not in failed_ip] + perm_failed[role] = [asset for asset in calc_assets if asset.ip in failed_ip] + + if not perm_failed.values(): + # 仅授权成功的,写回数据库(授权规则,用户,用户组,资产,资产组,用户角色) + rule = PermRule(name=rule_name, comment=rule_comment) + rule.save() + rule.user = users_obj + rule.usergroup = user_groups_obj + rule.asset = assets_obj + rule.asset_group = asset_groups_obj + rule.role = roles_obj + rule.save() + return HttpResponse(ret) + else: + return HttpResponse("add rule failed") + + +@require_role('admin') +def perm_rule_edit(request): + """ + list rules + :param request: + :return: + """ + + data_nav = {"header_title": "授权规则", "path1": "授权管理", "path2": "编辑规则"} + # 根据rule_id 取得rule对象 + rule_id = request.GET.get("id") + rule_obj = PermRule.objects.get(id=rule_id) + + + if request.method == 'GET' and rule_id: + # 获取所有的rule对象 + users_obj = rule_obj.user.all() + user_groups_obj = rule_obj.user_group.all() + assets_obj = rule_obj.asset.all() + asset_groups_obj = rule_obj.asset_group.all() + roles_obj = rule_obj.role.all() + + data_content = {"users": users_obj, "user_groups": user_groups_obj, + "assets": assets_obj, "asset_groups": asset_groups_obj, + "roles": roles_obj, "rule": rule_obj} + render_data = updates_dict(data_nav, data_content) + return my_render('jperm/perm_rule_edit.html', render_data, request) + + elif request.method == 'POST' and rule_id: + return HttpResponse("uncompleted") + + +@require_role('admin') +def perm_rule_delete(request): + """ + use to delete rule + :param request: + :return: + """ + if request.method == 'POST': + # 根据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: + return HttpResponse(u"不支持该操作") + + +@require_role('admin') +def perm_role_list(request): + """ + 用户授权视图: + 该视图的模板包含2部分: + 1. block 部分:{% block content %} + rander_content 为渲染数据 + 2. include 部分:{% include 'nav_cat_bar.html' %} + rander_nav 为渲染数据 + """ + data_nav = {"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) + data_content = {"roles": roles_list} + + render_data = updates_dict(data_nav, data_content) + + return my_render('jperm/perm_role_list.html', render_data, request) + + +@require_role('admin') +def perm_role_add(request): + """ + 用户授权视图: + 该视图的模板包含2部分: + 1. block 部分:{% block content %} + rander_content 为渲染数据 + 2. include 部分:{% include 'nav_cat_bar.html' %} + rander_nav 为渲染数据 + """ + data_nav = {"header_title": "系统角色", "path1": "角色管理", "path2": "添加角色"} + + if request.method == "GET": + return my_render('jperm/perm_role_add.html', data_nav, request) + + elif request.method == "POST": + # 获取参数: name, comment + name = request.POST.get("role_name") + comment = request.POST.get("role_comment") + # 生成随机密码,生成秘钥对 + password = get_rand_pass() + key_path = gen_keys() + role = PermRole(name=name, comment=comment, password=password, key_path=key_path) + role.save() + return HttpResponse(u"添加角色: %s" % name) + else: + return HttpResponse(u"不支持该操作") + +@require_role('admin') +def perm_role_delete(request): + """ + 用户授权视图: + 该视图的模板包含2部分: + 1. block 部分:{% block content %} + rander_content 为渲染数据 + 2. include 部分:{% include 'nav_cat_bar.html' %} + rander_nav 为渲染数据 + """ + if request.method == "POST": + # 获取参数删除的role对象 + role_id = request.POST.get("id") + role = PermRole.objects.get(id=role_id) + role.delete() + return HttpResponse(u"删除角色: %s" % role.name) + else: + return HttpResponse(u"不支持该操作") + + +@require_role('admin') +def perm_role_detail(request): + """ + the role_info data like: + {'asset_groups': [], + 'assets': [], + 'rules': [], + 'user_groups': [], + 'users': []} + """ + data_nav = {"header_title": "系统角色", "path1": "角色管理", "path2": "角色详情"} + + if request.method == "GET": + role_id = request.GET.get("id") + role_info = get_role_info(role_id) + render_data = updates_dict(data_nav, role_info) + return my_render('jperm/perm_role_detail.html', render_data, request) + + +@require_role('admin') +def perm_role_edit(request): + """ + + :param request: + :return: + """ + data_nav = {"header_title": "系统角色", "path1": "角色管理", "path2": "角色编辑"} + + if request.method == "GET": + role_id = request.GET.get("id") + data_content = {"role": PermRole.objects.get(id=role_id)} + render_data = updates_dict(data_nav, data_content) + return my_render('jperm/perm_role_edit.html', render_data, request) + + if request.method == "POST": + return HttpResponse(u"未实现") + + +@require_role('admin') +def perm_role_push(request): + """ + + :param request: + :return: + """ + data_nav = {"header_title": "系统角色", "path1": "角色管理", "path2": "角色推送"} + + if request.method == "GET": + data_content = {"roles": PermRole.objects.all(), + "assets": Asset.objects.all(), + "asset_groups": AssetGroup.objects.all()} + render_data = updates_dict(data_nav, data_content) + return my_render('jperm/perm_role_push.html', render_data, request) + + if request.method == "POST": + # 获取推荐角色的名称列表 + role_names = request.POST.getlist("roles") + + # 计算出需要推送的资产列表 + asset_ips = request.POST.getlist("assets") + asset_group_names = request.POST.getlist("asset_groups") + assets_obj = [Asset.objects.get(ip=asset_ip) for asset_ip in asset_ips] + asset_groups_obj = [AssetGroup.objects.get(name=asset_group_name) for asset_group_name in asset_group_names] + group_assets_obj = [] + for asset_group in asset_groups_obj: + group_assets_obj.extend(asset_group.asset_set.all()) + calc_assets = set(assets_obj) | set(group_assets_obj) + + # 生成Inventory + hosts = [{"hostname": asset.ip, + "port": asset.port, + "username": asset.username, + "password": asset.password} for asset in calc_assets] + + # 获取角色的推送方式,以及推送需要的信息 + roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names] + roles_info = {} + for role in roles_obj: + roles_info[role.name] = {"password": role.password, "key": role.key_path} + + # 推送 + password_push = request.POST.get("use_password") + key_push = request.POST.get("use_publicKey") + if password_push: + pass + if key_push: + pass + + + + + # 调用Ansible API 执行 password方式的授权 TODO: Surport sudo + # tasks = Tasks(hosts) + # ret = tasks.add_multi_user(*role_names) + + return HttpResponse(u"未实现") + + + + + + + + + + +@require_role('admin') +def perm_group_list(request): + header_title, path1, path2 = '用户组授权', '授权管理', '用户组授权' + keyword = request.GET.get('search', '') + user_groups_list = UserGroup.objects.all() + if keyword: + request = user_groups_list.filter(Q(name=keyword) | Q(comment=keyword)) + user_groups_list, p, user_groups, page_range, current_page, show_first, show_end = pages(user_groups_list, request) + return my_render('jperm/perm_group_list.html', locals(), request) + + + +@require_role('admin') +def perm_group_edit(request): + header_title, path1, path2 = '用户组授权', '授权管理', '授权更改' + user_group_id = request.GET.get('id', '') + user_group = get_object(UserGroup, id=user_group_id) + asset_all = Asset.objects.all() + asset_group_all = AssetGroup.objects.all() + asset_permed = user_group.asset.all() # 获取授权的资产对象列表 + asset_group_permed = user_group.asset_group.all() # 获取授权的资产组对象列表 + if request.method == 'GET' and user_group: + assets = [asset for asset in asset_all if asset not in asset_permed] + asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed] + return my_render('jperm/perm_group_edit.html', locals(), request) + elif request.method == 'POST' and user_group: + asset_id_select = request.POST.getlist('asset_select', []) + asset_group_id_select = request.POST.getlist('asset_groups_select', []) + asset_select = get_object_list(Asset, asset_id_select) + asset_group_select = get_object_list(AssetGroup, asset_group_id_select) + asset_new = list(set(asset_select) - set(asset_permed)) # 计算的得到新授权的资产对象列表 + asset_del = list(set(asset_permed) - set(asset_select)) # 计算得到回收权限的资产对象列表 + asset_group_new = list(set(asset_group_select) - set(asset_group_permed)) # 新授权的资产组对象列表 + asset_group_del = list(set(asset_group_permed) - set(asset_group_select)) # 回收的资产组对象列表 + users = user_group.user_set.all() + perm_info = { + 'action': 'perm group edit: ' + user_group.name, + 'del': {'users': users, 'assets': asset_del}, + 'new': {'users': users, 'assets': asset_new} + } + results = perm_user_api(perm_info) + unreachable_asset = [] + failures_asset = [] + for ip in results.get('unreachable'): + unreachable_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) + for ip in results.get('failures'): + failures_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) + failures_asset.extend(unreachable_asset) # 失败的授权要统计 + for asset in failures_asset: + if asset in asset_select: + asset_select.remove(asset) + else: + asset_select.append(asset) + user_group.asset = asset_select + user_group.asset_group = asset_group_select + user_group.save() # 保存到数据库 + return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") + else: + return HttpResponse('输入错误') + + +def log(request): + header_title, path1, path2 = '授权记录', '授权管理', '授权记录' + log_all = Log.objects.all().order_by('-datetime') + log_all, p, logs, page_range, current_page, show_first, show_end = pages(log_all, request) + return my_render('jperm/perm_log.html', locals(), request) + + +def sys_user_add(request): + asset_group_all = AssetGroup.objects.all() + if request.method == 'POST': + username = request.POST.get('username', '') + password = request.POST.get('password', '') + asset_groups_id = request.POST.getlist('asset_groups_select', []) + comment = request.POST.get('comment') + sys_user = SysUser(username=username, password=password, comment=comment) + sys_user.save() + gen_ssh_key(username, key_dir=os.path.join(SSH_KEY_DIR, 'sysuser'), authorized_keys=False) + results = push_user(sys_user, asset_groups_id) + return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") + return my_render('jperm/sys_user_add.html', locals(), request) + + +def sys_user_list(request): + users_list = SysUser.objects.all() + users_list, p, users, page_range, current_page, show_first, show_end = pages(users_list, request) + return my_render('jperm/sys_user_list.html', locals(), request) + + +def sys_user_edit(request): + pass + + +def sys_user_del(request): + pass + diff --git a/jperm/views.py.back b/jperm/views.py.back new file mode 100644 index 000000000..2e910e025 --- /dev/null +++ b/jperm/views.py.back @@ -0,0 +1 @@ +# # coding: utf-8 # import sysuser # # reload(sysuser) # sysuser.setdefaultencoding('utf8') # # from django.shortcuts import render_to_response # from django.template import RequestContext # from jperm.models import Perm, SudoPerm, CmdGroup, Apply from django.db.models import Q from jumpserver.api import * from jperm.perm_api import * from jperm.models import PermLog as Log from jperm.models import SysUser from juser.user_api import gen_ssh_key @require_role('admin') def perm_user_list(request): header_title, path1, path2 = '用户授权', '授权管理', '用户授权' keyword = request.GET.get('search', '') users_list = User.objects.all() # 获取所有用户 if keyword: users_list = users_list.filter(Q(name=keyword) | Q(username=keyword)) # 搜索 users_list, p, users, page_range, current_page, show_first, show_end = pages(users_list, request) # 分页 return my_render('jperm/perm_user_list.html', locals(), request) @require_role('admin') def perm_user_edit(request): header_title, path1, path2 = '用户授权', '授权管理', '授权更改' user_id = request.GET.get('id', '') user = get_object(User, id=user_id) asset_all = Asset.objects.all() # 获取所有资产 asset_group_all = AssetGroup.objects.all() # 获取所有资产组 asset_permed = user.asset.all() # 获取授权的资产对象列表 asset_group_permed = user.asset_group.all() # 获取授权的资产组对象列表 if request.method == 'GET' and user: assets = [asset for asset in asset_all if asset not in asset_permed] # 获取没有授权的资产对象列表 asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed] # 同理 return my_render('jperm/perm_user_edit.html', locals(), request) elif request.method == 'POST' and user: asset_id_select = request.POST.getlist('asset_select', []) # 获取选择的资产id列表 asset_group_id_select = request.POST.getlist('asset_groups_select', []) # 获取选择的资产组id列表 asset_select = get_object_list(Asset, asset_id_select) asset_group_select = get_object_list(AssetGroup, asset_group_id_select) asset_new = list(set(asset_select) - set(asset_permed)) # 计算的得到新授权的资产对象列表 asset_del = list(set(asset_permed) - set(asset_select)) # 计算得到回收权限的资产对象列表 asset_group_new = list(set(asset_group_select) - set(asset_group_permed)) # 新授权的资产组对象列表 asset_group_del = list(set(asset_group_permed) - set(asset_group_select)) # 回收的资产组对象列表 for asset_group in asset_group_new: asset_new.extend(asset_group.asset_set.all()) for asset_group in asset_group_del: asset_del.extend(asset_group.asset_set.all()) perm_info = { 'action': 'perm user edit: ' + user.name, 'del': {'users': [user], 'assets': asset_del}, 'new': {'users': [user], 'assets': asset_new} } print perm_info try: results = perm_user_api(perm_info) # 通过API授权或回收 except ServerError, e: return HttpResponse(e) unreachable_asset = [] failures_asset = [] for ip in results.get('unreachable'): unreachable_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) for ip in results.get('failures'): failures_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) failures_asset.extend(unreachable_asset) # 失败的授权要统计 for asset in failures_asset: if asset in asset_select: asset_select.remove(asset) else: asset_select.append(asset) user.asset = asset_select user.asset_group = asset_group_select user.save() # 保存到数据库 return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") else: return HttpResponse('输入错误') @require_role('admin') def perm_group_list(request): header_title, path1, path2 = '用户组授权', '授权管理', '用户组授权' keyword = request.GET.get('search', '') user_groups_list = UserGroup.objects.all() if keyword: request = user_groups_list.filter(Q(name=keyword) | Q(comment=keyword)) user_groups_list, p, user_groups, page_range, current_page, show_first, show_end = pages(user_groups_list, request) return my_render('jperm/perm_group_list.html', locals(), request) @require_role('admin') def perm_group_edit(request): header_title, path1, path2 = '用户组授权', '授权管理', '授权更改' user_group_id = request.GET.get('id', '') user_group = get_object(UserGroup, id=user_group_id) asset_all = Asset.objects.all() asset_group_all = AssetGroup.objects.all() asset_permed = user_group.asset.all() # 获取授权的资产对象列表 asset_group_permed = user_group.asset_group.all() # 获取授权的资产组对象列表 if request.method == 'GET' and user_group: assets = [asset for asset in asset_all if asset not in asset_permed] asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed] return my_render('jperm/perm_group_edit.html', locals(), request) elif request.method == 'POST' and user_group: asset_id_select = request.POST.getlist('asset_select', []) asset_group_id_select = request.POST.getlist('asset_groups_select', []) asset_select = get_object_list(Asset, asset_id_select) asset_group_select = get_object_list(AssetGroup, asset_group_id_select) asset_new = list(set(asset_select) - set(asset_permed)) # 计算的得到新授权的资产对象列表 asset_del = list(set(asset_permed) - set(asset_select)) # 计算得到回收权限的资产对象列表 asset_group_new = list(set(asset_group_select) - set(asset_group_permed)) # 新授权的资产组对象列表 asset_group_del = list(set(asset_group_permed) - set(asset_group_select)) # 回收的资产组对象列表 users = user_group.user_set.all() perm_info = { 'action': 'perm group edit: ' + user_group.name, 'del': {'users': users, 'assets': asset_del}, 'new': {'users': users, 'assets': asset_new} } results = perm_user_api(perm_info) unreachable_asset = [] failures_asset = [] for ip in results.get('unreachable'): unreachable_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) for ip in results.get('failures'): failures_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) failures_asset.extend(unreachable_asset) # 失败的授权要统计 for asset in failures_asset: if asset in asset_select: asset_select.remove(asset) else: asset_select.append(asset) user_group.asset = asset_select user_group.asset_group = asset_group_select user_group.save() # 保存到数据库 return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") else: return HttpResponse('输入错误') def log(request): header_title, path1, path2 = '授权记录', '授权管理', '授权记录' log_all = Log.objects.all().order_by('-datetime') log_all, p, logs, page_range, current_page, show_first, show_end = pages(log_all, request) return my_render('jperm/perm_log.html', locals(), request) def sys_user_add(request): asset_group_all = AssetGroup.objects.all() if request.method == 'POST': username = request.POST.get('username', '') password = request.POST.get('password', '') asset_groups_id = request.POST.getlist('asset_groups_select', []) comment = request.POST.get('comment') sys_user = SysUser(username=username, password=password, comment=comment) sys_user.save() gen_ssh_key(username, key_dir=os.path.join(SSH_KEY_DIR, 'sysuser'), authorized_keys=False) results = push_user(sys_user, asset_groups_id) return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") return my_render('jperm/sys_user_add.html', locals(), request) def sys_user_list(request): users_list = SysUser.objects.all() users_list, p, users, page_range, current_page, show_first, show_end = pages(users_list, request) return my_render('jperm/sys_user_list.html', locals(), request) def sys_user_edit(request): pass def sys_user_del(request): pass \ No newline at end of file diff --git a/jumpserver.conf b/jumpserver.conf index fda6a681a..1a6a23fce 100644 --- a/jumpserver.conf +++ b/jumpserver.conf @@ -1,21 +1,20 @@ #coding: utf8 [base] -url = http://192.168.244.129 +url = http://127.0.0.1 key = 88aaaf7ffe3c6c04 log = debug - [db] host = 127.0.0.1 port = 3306 user = jumpserver -password = mysql234 +password =mysql1234 database = jumpserver - [websocket] -web_socket_host = 192.168.244.129:3000 +web_socket_host = 127.0.0.1:3000 + [mail] diff --git a/jumpserver/models.py b/jumpserver/models.py index 068ce110e..e8cb7ea2b 100644 --- a/jumpserver/models.py +++ b/jumpserver/models.py @@ -6,7 +6,7 @@ from django.db import models class Setting(models.Model): name = models.CharField(max_length=100) default_user = models.CharField(max_length=100, null=True, blank=True) - default_port = models.IntegerField(max_length=10, null=True, blank=True) + default_port = models.IntegerField(null=True, blank=True) default_password = models.CharField(max_length=100, null=True, blank=True) default_pri_key_path = models.CharField(max_length=100, null=True, blank=True) diff --git a/jumpserver/settings.py b/jumpserver/settings.py index 87785d0fb..942d6808f 100644 --- a/jumpserver/settings.py +++ b/jumpserver/settings.py @@ -18,6 +18,7 @@ config = ConfigParser.ConfigParser() BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) config.read(os.path.join(BASE_DIR, 'jumpserver.conf')) + DB_HOST = config.get('db', 'host') DB_PORT = config.getint('db', 'port') DB_USER = config.get('db', 'user') @@ -69,6 +70,7 @@ INSTALLED_APPS = ( 'jasset', 'jperm', 'jlog', + ) MIDDLEWARE_CLASSES = ( diff --git a/jumpserver/tasks.py b/jumpserver/tasks.py index 22fd514ef..41bad7316 100644 --- a/jumpserver/tasks.py +++ b/jumpserver/tasks.py @@ -1,4 +1,4 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- from ansible.playbook import PlayBook from ansible import callbacks, utils @@ -44,4 +44,5 @@ def playbook_run(inventory, playbook, default_user=None, default_port=None, defa else: results_r['success'].append(hostname) print "%s >>> Success" % hostname - return results_r \ No newline at end of file + return results_r + diff --git a/jumpserver/templatetags/__init__.pyc b/jumpserver/templatetags/__init__.pyc new file mode 100644 index 000000000..1e92dc2cb Binary files /dev/null and b/jumpserver/templatetags/__init__.pyc differ diff --git a/jumpserver/templatetags/mytags.py b/jumpserver/templatetags/mytags.py index 2bd1df20b..52da56a05 100644 --- a/jumpserver/templatetags/mytags.py +++ b/jumpserver/templatetags/mytags.py @@ -123,3 +123,62 @@ def result2bool(result=''): return '失败' else: return '成功' + + +@register.filter(name='rule_member_count') +def rule_member_count(instance, member): + """ + instance is a rule object, + use to get the number of the members + :param instance: + :param member: + :return: + """ + member = getattr(instance, member) + counts = member.all().count() + return str(counts) + + +@register.filter(name='rule_member_name') +def rule_member_name(instance, member): + """ + instance is a rule object, + use to get the name of the members + :param instance: + :param member: + :return: + """ + member = getattr(instance, member) + names = member.all() + + return names + + +@register.filter(name='user_which_groups') +def user_which_group(user, member): + """ + instance is a user object, + use to get the group of the user + :param instance: + :param member: + :return: + """ + member = getattr(user, member) + names = [members.name for members in member.all()] + + return ','.join(names) + + +@register.filter(name='asset_which_groups') +def asset_which_group(asset, member): + """ + instance is a user object, + use to get the group of the user + :param instance: + :param member: + :return: + """ + member = getattr(asset, member) + names = [members.name for members in member.all()] + + return ','.join(names) diff --git a/juser/models.py b/juser/models.py index 26aacffa6..7ea4bc95b 100644 --- a/juser/models.py +++ b/juser/models.py @@ -3,14 +3,11 @@ from django.db import models from django.contrib.auth.models import AbstractUser -from jasset.models import Asset, AssetGroup class UserGroup(models.Model): name = models.CharField(max_length=80, unique=True) comment = models.CharField(max_length=160, blank=True, null=True) - asset = models.ManyToManyField(Asset) - asset_group = models.ManyToManyField(AssetGroup) def __unicode__(self): return self.name @@ -27,6 +24,11 @@ class User(AbstractUser): role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU') group = models.ManyToManyField(UserGroup) ssh_key_pwd = models.CharField(max_length=200) + # is_active = models.BooleanField(default=True) + # last_login = models.DateTimeField(null=True) + # date_joined = models.DateTimeField(null=True) + + def __unicode__(self): return self.username diff --git a/logs/jumpserver.log b/logs/jumpserver.log new file mode 100644 index 000000000..e69de29bb diff --git a/templates/jperm/perm_role_add.html b/templates/jperm/perm_role_add.html new file mode 100644 index 000000000..031066b73 --- /dev/null +++ b/templates/jperm/perm_role_add.html @@ -0,0 +1,113 @@ +{% extends 'base.html' %} +{% block self_head_css_js %} + + + +{% endblock %} +{% load mytags %} +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写基本信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+{% endblock %} +{% block self_footer_js %} + + + +{% endblock %} + diff --git a/templates/jperm/perm_role_detail.html b/templates/jperm/perm_role_detail.html new file mode 100644 index 000000000..593ccd740 --- /dev/null +++ b/templates/jperm/perm_role_detail.html @@ -0,0 +1,161 @@ +{% extends 'base.html' %} +{% load mytags %} + + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+ +
+
+
+
+ 授权规则 +
+ + + + + + + + + + +
+
+
+
+
+ + + + + + + + + {% for rule in rules %} + + + + + {% endfor %} + +
时间名称
{{ rule.date_added | date:"Y-m-d H:i:s"}} {{ rule.name }}
+
+
+
+
+
+
+
+
+ 授权用户/用户组 +
+ + + + + + + + + + +
+
+
+
+
+ + + + + + + + + {% for user in users %} + + + + + {% endfor %} + +
用户用户组
{{ user.name }} {{ user | user_which_groups:"group" }}
+
+
+
+
+
+
+
+
+ 授权主机/主机组 +
+ + + + + + + + + + +
+
+
+
+
+ + + + + + + + + {% for asset in assets %} + + + + + {% endfor %} + +
主机主机组
{{ asset.ip }} {{ asset | asset_which_groups:"group" }}
+
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_role_edit.html b/templates/jperm/perm_role_edit.html new file mode 100644 index 000000000..23c7e7617 --- /dev/null +++ b/templates/jperm/perm_role_edit.html @@ -0,0 +1,113 @@ +{% extends 'base.html' %} +{% block self_head_css_js %} + + + +{% endblock %} +{% load mytags %} +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写基本信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+{% endblock %} +{% block self_footer_js %} + + + +{% endblock %} + diff --git a/templates/jperm/perm_user_list.html b/templates/jperm/perm_role_list.html similarity index 57% rename from templates/jperm/perm_user_list.html rename to templates/jperm/perm_role_list.html index 84fdc5678..dfecbf09c 100644 --- a/templates/jperm/perm_user_list.html +++ b/templates/jperm/perm_role_list.html @@ -8,7 +8,7 @@
-
查看小组
+
所有系统角色
@@ -24,7 +24,9 @@
- 添加用户 + 添加角色 + 推送角色 + 删除所选
+
+
+
+
+
+
+ 授权用户/用户组 +
+ + + + + + + + + + +
+
+
+
+
+ + + + + + + + + {% for user in users %} + + + + + {% endfor %} + +
用户用户组
{{ user.name }} {{ user | user_which_groups:"group" }}
+
+
+
+
+
+
+
+
+ 授权主机/主机组 +
+ + + + + + + + + + +
+
+
+
+
+ + + + + + + + + {% for asset in assets %} + + + + + {% endfor %} + +
主机主机组
{{ asset.ip }} {{ asset | asset_which_groups:"group" }}
+
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_rule_edit.html b/templates/jperm/perm_rule_edit.html new file mode 100644 index 000000000..e624acb55 --- /dev/null +++ b/templates/jperm/perm_rule_edit.html @@ -0,0 +1,209 @@ +{% extends 'base.html' %} +{% block self_head_css_js %} + + + +{% endblock %} +{% load mytags %} +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写基本信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +
+ +
+ +
+
+ +
+
+
+ + + +
+
+ +
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+{% endblock %} +{% block self_footer_js %} + + + +{% endblock %} + diff --git a/templates/jperm/perm_rule_list.html b/templates/jperm/perm_rule_list.html new file mode 100644 index 000000000..20c0fe831 --- /dev/null +++ b/templates/jperm/perm_rule_list.html @@ -0,0 +1,120 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
所有规则
+ +
+ +
+
+ 添加规则 + 删除所选 + +
+ + + + + + + + + + + + + + + {% for rule in rules %} + + + + + + + + + + {% endfor %} + +
规则名称 用户用户组资产资产组角色操作
{{ rule.name }} + {{ rule | rule_member_count:"user" }} + + {{ rule | rule_member_count:"user_group" }} + + {{ rule | rule_member_count:"asset" }} + + {{ rule | rule_member_count:"asset_group" }} + + {{ rule | rule_member_count:"role" }} + + 详情 + 编辑 + +
+
+
+
+ Showing {{ users.start_index }} to {{ users.end_index }} of {{ p.count }} entries +
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+ + + + + +{% endblock %} + + diff --git a/templates/jperm/perm_user_edit.html b/templates/jperm/perm_user_edit.html deleted file mode 100644 index 5d06997f5..000000000 --- a/templates/jperm/perm_user_edit.html +++ /dev/null @@ -1,122 +0,0 @@ -{% extends 'base.html' %} -{% load mytags %} -{% block content %} -{% include 'nav_cat_bar.html' %} - -
-
-
-
-
-
{{ user.name }}授权修改
- -
- -
-
- {% if error %} -
{{ error }}
- {% endif %} - {% if msg %} -
{{ msg }}
- {% endif %} -
-
- -
- -
-
- -
- -
- -
-
- -
-
- -
-
- - -
-
- -
-
- -
-
-
- -
- -
- -
-
- -
-
- -
-
- - -
-
- -
-
- -
-
-
-
- -
-
-
- - -
-
-
-
- -
-
-
-
-
- -{% endblock %} \ No newline at end of file diff --git a/templates/nav.html b/templates/nav.html index 7db03f2db..cc42a6fe4 100644 --- a/templates/nav.html +++ b/templates/nav.html @@ -28,15 +28,11 @@ 授权管理