# coding: utf-8 # Author: Guanghongwei # Email: ibuler@qq.com import time import os import random import subprocess from Crypto.PublicKey import RSA import crypt from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.core.exceptions import ObjectDoesNotExist from django.db.models import Q from django.template import RequestContext from django.http import HttpResponse from django.core.paginator import Paginator, EmptyPage, InvalidPage from juser.models import UserGroup, User from connect import PyCrypt, KEY from connect import BASE_DIR from connect import CONF from jumpserver.views import md5_crypt, LDAPMgmt, LDAP_ENABLE, ldap_conn, page_list_return if LDAP_ENABLE: LDAP_HOST_URL = CONF.get('ldap', 'host_url') LDAP_BASE_DN = CONF.get('ldap', 'base_dn') LDAP_ROOT_DN = CONF.get('ldap', 'root_dn') LDAP_ROOT_PW = CONF.get('ldap', 'root_pw') CRYPTOR = PyCrypt(KEY) def gen_rand_pwd(num): """生成随机密码""" seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" salt_list = [] for i in range(num): salt_list.append(random.choice(seed)) salt = ''.join(salt_list) return salt def bash(cmd): """执行bash命令""" return subprocess.call(cmd, shell=True) def is_dir(dir_name, mode=0755): if not os.path.isdir(dir_name): os.makedirs(dir_name) os.chmod(dir_name, mode) class AddError(Exception): pass def gen_sha512(salt, password): return crypt.crypt(password, '$6$%s$' % salt) def group_db_add(**kwargs): group_name = kwargs.get('name') group = UserGroup.objects.filter(name=group_name) if group: raise AddError('Group %s have been exist .' % group_name) UserGroup.objects.create(**kwargs) def group_add_user(group_name, user_id=None, username=None): try: if user_id: user = User.objects.get(id=user_id) else: user = User.objects.get(username=username) except ObjectDoesNotExist: raise AddError('用户获取失败') else: group = UserGroup.objects.get(name=group_name) group.user_set.add(user) def group_update_user(group_id, users_id): group = UserGroup.objects.get(id=group_id) group.user_set.clear() for user_id in users_id: user = User.objects.get(id=user_id) group.user_set.add(user) def db_add_user(**kwargs): groups_post = kwargs.pop('groups') user = User(**kwargs) group_select = [] for group_id in groups_post: group = UserGroup.objects.filter(id=group_id) group_select.extend(group) user.save() user.user_group = group_select def db_update_user(**kwargs): groups_post = kwargs.pop('groups') username = kwargs.get('username') user = User.objects.filter(username=username) user.update(**kwargs) user = User.objects.get(username=username) group_select = [] for group_id in groups_post: group = UserGroup.objects.filter(id=group_id) group_select.extend(group) user.save() user.user_group = group_select def db_del_user(username): try: user = User.objects.get(username=username) user.delete() except ObjectDoesNotExist: pass def gen_ssh_key(username, password=None, length=2048): private_key_dir = os.path.join(BASE_DIR, 'keys/jumpserver/') private_key_file = os.path.join(private_key_dir, username) public_key_dir = '/home/%s/.ssh/' % username public_key_file = os.path.join(public_key_dir, 'authorized_keys') is_dir(private_key_dir) is_dir(public_key_dir, mode=0700) key = RSA.generate(length) with open(private_key_file, 'w') as pri_f: pri_f.write(key.exportKey('PEM', password)) os.chmod(private_key_file, 0600) pub_key = key.publickey() with open(public_key_file, 'w') as pub_f: pub_f.write(pub_key.exportKey('OpenSSH')) os.chmod(public_key_file, 0600) bash('chown %s:%s %s' % (username, username, public_key_file)) def server_add_user(username, password, ssh_key_pwd): bash('useradd %s; echo %s | passwd --stdin %s' % (username, password, username)) gen_ssh_key(username, ssh_key_pwd) def server_del_user(username): bash('userdel -r %s' % username) def ldap_add_user(username, ldap_pwd): user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN) password_sha512 = gen_sha512(gen_rand_pwd(6), ldap_pwd) user = User.objects.get(username=username) user_attr = {'uid': [str(username)], 'cn': [str(username)], 'objectClass': ['account', 'posixAccount', 'top', 'shadowAccount'], 'userPassword': ['{crypt}%s' % password_sha512], 'shadowLastChange': ['16328'], 'shadowMin': ['0'], 'shadowMax': ['99999'], 'shadowWarning': ['7'], 'loginShell': ['/bin/bash'], 'uidNumber': [str(user.id)], 'gidNumber': [str(user.id)], 'homeDirectory': [str('/home/%s' % username)]} group_dn = "cn=%s,ou=Group,%s" % (username, LDAP_BASE_DN) group_attr = {'objectClass': ['posixGroup', 'top'], 'cn': [str(username)], 'userPassword': ['{crypt}x'], 'gidNumber': [str(user.id)]} # sudo_dn = 'cn=%s,ou=Sudoers,%s' % (username, LDAP_BASE_DN) # sudo_attr = {'objectClass': ['top', 'sudoRole'], # 'cn': ['%s' % str(username)], # 'sudoCommand': ['/bin/pwd'], # 'sudoHost': ['192.168.1.1'], # 'sudoOption': ['!authenticate'], # 'sudoRunAsUser': ['root'], # 'sudoUser': ['%s' % str(username)]} ldap_conn.add(user_dn, user_attr) ldap_conn.add(group_dn, group_attr) # ldap_conn.add(sudo_dn, sudo_attr) def ldap_del_user(username): user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN) group_dn = "cn=%s,ou=Group,%s" % (username, LDAP_BASE_DN) sudo_dn = 'cn=%s,ou=Sudoers,%s' % (username, LDAP_BASE_DN) ldap_conn.delete(user_dn) ldap_conn.delete(group_dn) ldap_conn.delete(sudo_dn) # def ldap_group_add(group_name, username_list, gid): # group_dn = "cn=%s,ou=Group,%s" % (group_name, LDAP_BASE_DN) # group_attr = {'objectClass': ['posixGroup', 'top'], # 'cn': [str(group_name)], # 'userPassword': ['{crypt}x'], # 'gidNumber': [gid], # 'memberUid': username_list} # ldap_conn.add(group_dn, group_attr) def group_add(request, group_type_select='A'): error = '' msg = '' header_title, path1, path2 = '添加属组 | Group Add', '用户管理', '添加用户组' group_types = { 'M': '部门', 'A': '用户组', } users_all = User.objects.all() if group_type_select == 'M': users = [user for user in users_all if not user.user_group.filter(type='M')] else: users = users_all if request.method == 'POST': group_name = request.POST.get('group_name', '') group_type = request.POST.get('group_type', 'A') users_selected = request.POST.getlist('users_selected', '') comment = request.POST.get('comment', '') try: if not group_name: error = u'组名不能为空' raise AddError group_db_add(name=group_name, comment=comment, type=group_type) for user_id in users_selected: group_add_user(group_name, user_id=user_id) except AddError: pass except TypeError: error = u'保存用户组失败' else: msg = u'添加组 %s 成功' % group_name return render_to_response('juser/group_add.html', locals(), context_instance=RequestContext(request)) def group_add_ajax(request): group_type = request.POST.get('type', 'A') users_all = User.objects.all() if group_type == 'A': users = users_all else: users = [user for user in users_all if not user.user_group.filter(type='M')] return render_to_response('juser/group_add_ajax.html', locals(), context_instance=RequestContext(request)) def group_list(request): header_title, path1, path2 = '查看属组 | Show Group', '用户管理', '查看用户组' groups = contact_list = UserGroup.objects.filter(Q(type='M') | Q(type='A')).order_by('type') p = paginator = Paginator(contact_list, 10) try: current_page = int(request.GET.get('page', '1')) except ValueError: current_page = 1 page_range = page_list_return(len(p.page_range), current_page) try: contacts = paginator.page(current_page) except (EmptyPage, InvalidPage): contacts = paginator.page(paginator.num_pages) return render_to_response('juser/group_list.html', locals(), context_instance=RequestContext(request)) def group_detail(request): group_id = request.GET.get('id', None) if not group_id: return HttpResponseRedirect('/') group = UserGroup.objects.get(id=group_id) users = group.user_set.all() return render_to_response('juser/group_detail.html', locals(), context_instance=RequestContext(request)) def group_del(request): group_id = request.GET.get('id', None) if not group_id: return HttpResponseRedirect('/') group = UserGroup.objects.get(id=group_id) group.delete() return HttpResponseRedirect('/juser/group_list/', locals(), context_instance=RequestContext(request)) def group_edit(request): error = '' msg = '' header_title, path1, path2 = '修改属组 | Edit Group', 'juser', 'group_edit' group_types = { 'M': '部门', 'A': '用户组', } if request.method == 'GET': group_id = request.GET.get('id', None) group = UserGroup.objects.get(id=group_id) group_name = group.name comment = group.comment group_type = group.type users_all = User.objects.all() users_selected = group.user_set.all() users = [user for user in users_all if user not in users_selected] return render_to_response('juser/group_edit.html', locals(), context_instance=RequestContext(request)) else: group_id = request.POST.get('group_id', None) group_name = request.POST.get('group_name', None) comment = request.POST.get('comment', '') users_selected = request.POST.getlist('users_selected') group_type = request.POST.get('group_type') group = UserGroup.objects.filter(id=group_id) group.update(name=group_name, comment=comment, type=group_type) group_update_user(group_id, users_selected) return HttpResponseRedirect('/juser/group_list/') def user_list(request): user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} header_title, path1, path2 = '查看用户 | Show User', '用户管理', '用户列表' users = contact_list = User.objects.all().order_by('id') p = paginator = Paginator(contact_list, 10) try: current_page = int(request.GET.get('page', '1')) except ValueError: current_page = 1 page_range = page_list_return(len(p.page_range), current_page) try: contacts = paginator.page(current_page) except (EmptyPage, InvalidPage): contacts = paginator.page(paginator.num_pages) return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request)) def user_detail(request): user_id = request.GET.get('id', None) if not user_id: return HttpResponseRedirect('/') user = User.objects.get(id=user_id) return render_to_response('juser/user_detail.html', locals(), context_instance=RequestContext(request)) def user_del(request): user_id = request.GET.get('id', None) if not user_id: return HttpResponseRedirect('/') user = User.objects.get(id=user_id) user.delete() group = UserGroup.objects.get(name=user.username) group.delete() server_del_user(user.username) ldap_del_user(user.username) return HttpResponseRedirect('/juser/user_list/', locals(), context_instance=RequestContext(request)) def user_edit(request): header_title, path1, path2 = '编辑用户 | Edit User', 'juser', 'user_edit' readonly = "readonly" if request.method == 'GET': user_id = request.GET.get('id', None) if not user_id: return HttpResponseRedirect('/') user = User.objects.get(id=user_id) username = user.username password = user.password ssh_key_pwd = user.ssh_key_pwd name = user.name manage_groups = UserGroup.objects.filter(type='M') auth_groups = UserGroup.objects.filter(type='A') manage_group_id = user.user_group.get(type='M').id groups_str = ' '.join([str(group.id) for group in auth_groups]) user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} role_post = user.role ssh_pwd = user.ssh_pwd email = user.email else: username = request.POST.get('username', None) password = request.POST.get('password', None) name = request.POST.get('name', None) email = request.POST.get('email', '') manage_group_id = request.POST.get('manage_group', '') auth_groups = request.POST.getlist('groups', None) groups = auth_groups groups.append(manage_group_id) groups_str = ' '.join(auth_groups) role_post = request.POST.get('role', None) ssh_pwd = request.POST.get('ssh_pwd', None) ssh_key_pwd = request.POST.get('ssh_key_pwd', None) is_active = request.POST.get('is_active', '1') ldap_pwd = gen_rand_pwd(16) all_group = UserGroup.objects.filter(Q(type='M') | Q(type='A')) user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} if username: user = User.objects.get(username=username) else: return HttpResponseRedirect('/') if password != user.password: password = md5_crypt(password) if ssh_pwd != user.ssh_pwd: ssh_pwd = CRYPTOR.encrypt(ssh_pwd) if ssh_key_pwd != user.ssh_key_pwd: ssh_key_pwd = CRYPTOR.encrypt(ssh_key_pwd) db_update_user(username=username, password=password, name=name, email=email, groups=groups, role=role_post, ssh_pwd=ssh_pwd, ssh_key_pwd=ssh_key_pwd) msg = u'修改用户成功' return HttpResponseRedirect('/juser/user_list/') return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request)) def user_add(request): error = '' msg = '' header_title, path1, path2 = '添加用户 | User Add', '用户管理', '添加用户' user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} manage_groups = UserGroup.objects.filter(type='M') auth_groups = UserGroup.objects.filter(type='A') if request.method == 'POST': username = request.POST.get('username', None) password = request.POST.get('password', '') name = request.POST.get('name', None) email = request.POST.get('email', '') manage_group_id = request.POST.get('manage_group') auth_groups = request.POST.getlist('groups', None) groups = auth_groups groups.append(manage_group_id) groups_str = ' '.join(auth_groups) role_post = request.POST.get('role', 'CU') ssh_pwd = request.POST.get('ssh_pwd', '') ssh_key_pwd = request.POST.get('ssh_key_pwd', '') is_active = request.POST.get('is_active', '1') ldap_pwd = gen_rand_pwd(16) try: if None in [username, password, ssh_key_pwd, name, groups, role_post, is_active]: error = u'带*内容不能为空' raise AddError user = User.objects.filter(username=username) if user: error = u'用户 %s 已存在' % username raise AddError except AddError: pass else: time_now = time.time() try: db_add_user(username=username, password=md5_crypt(password), name=name, email=email, groups=groups, role=role_post, ssh_pwd=CRYPTOR.encrypt(ssh_pwd) if ssh_pwd else '', ssh_key_pwd=CRYPTOR.encrypt(ssh_key_pwd), ldap_pwd=CRYPTOR.encrypt(ldap_pwd), is_active=is_active, date_joined=time_now) server_add_user(username, password, ssh_key_pwd) group_db_add(name=username, comment=username, type='P') group_add_user(group_name=username, username=username) if LDAP_ENABLE: ldap_add_user(username, ldap_pwd) msg = u'添加用户 %s 成功!' % username except Exception, e: error = u'添加用户 %s 失败 %s ' % (username, e) try: db_del_user(username) server_del_user(username) if LDAP_ENABLE: ldap_del_user(username) except Exception: pass return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request)) def profile(request): user_id = request.session.get('user_id') if not user_id: return HttpResponseRedirect('/') user = User.objects.get(id=user_id) return render_to_response('juser/user_detail.html', locals(), context_instance=RequestContext(request)) def chg_pass(request): header_title, path1, path2 = '修改信息 | Edit Info', '用户管理', '修改个人信息' return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request))