jumpserver/webroot/AutoSa/AutoSa/views.py

516 lines
18 KiB
Python

#coding: utf-8
from django.http import HttpResponse
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from UserManage.models import User, Group
from Assets.models import Assets, AssetsUser
import subprocess
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import random
import ConfigParser
import pam
import os
import ldap
import ldap.modlist as modlist
import crypt
from UserManage.forms import UserAddForm, GroupAddForm
base_dir = "/opt/jumpserver/"
cf = ConfigParser.ConfigParser()
cf.read('%s/jumpserver.conf' % base_dir)
key = cf.get('jumpserver', 'key')
rsa_dir = cf.get('jumpserver', 'rsa_dir')
useradd_shell = cf.get('jumpserver', 'useradd_shell')
userdel_shell = cf.get('jumpserver', 'userdel_shell')
sudoadd_shell = cf.get('jumpserver', 'sudoadd_shell')
sudodel_shell = cf.get('jumpserver', 'sudodel_shell')
keygen_shell = cf.get('jumpserver', 'keygen_shell')
chgpass_shell = cf.get('jumpserver', 'chgpass_shell')
admin = ['admin']
ldap_host = cf.get('jumpserver', 'ldap_host')
ldap_base_dn = cf.get('jumpserver', 'ldap_base_dn')
admin_cn = cf.get('jumpserver', 'admin_cn')
admin_pass = cf.get('jumpserver', 'admin_pass')
def keygen(num):
"""生成随机密码"""
seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
sa = []
for i in range(num):
sa.append(random.choice(seed))
salt = ''.join(sa)
return salt
def bash(cmd):
return subprocess.call(cmd, shell=True)
class PyCrypt(object):
"""对称加密解密"""
def __init__(self, key):
self.key = key
self.mode = AES.MODE_CBC
def encrypt(self, text):
cryptor = AES.new(self.key, self.mode, b'0000000000000000')
length = 16
count = len(text)
if count < length:
add = (length - count)
text += ('\0' * add)
elif count > length:
add = (length - (count % length))
text += ('\0' * add)
ciphertext = cryptor.encrypt(text)
return b2a_hex(ciphertext)
def decrypt(self, text):
cryptor = AES.new(self.key, self.mode, b'0000000000000000')
plain_text = cryptor.decrypt(a2b_hex(text))
return plain_text.rstrip('\0')
def rsa_gen(username, key_pass, rsa_dir=rsa_dir):
rsa_file = '%s/%s' % (rsa_dir, username)
pub_file = '%s.pub' % rsa_file
authorized_file = '/home/%s/.ssh/authorized_keys' % username
if os.path.exists(rsa_file):
os.unlink(rsa_file)
ret = bash('ssh-keygen -t rsa -f %s -P %s &> /dev/null && echo "######## rsa_gen Ok."' % (rsa_file, key_pass))
if not ret:
try:
if not os.path.isdir('/home/%s/.ssh' % username):
os.mkdir('/home/%s/.ssh' % username)
pub = open(pub_file, 'r')
authorized = open(authorized_file, 'w')
authorized.write(pub.read())
pub.close()
authorized.close()
except Exception:
return 1
else:
return 0
class LDAPMgmt():
def __init__(self,
ldap_host=ldap_host,
ldap_base_dn=ldap_base_dn,
admin_cn=admin_cn,
admin_pass=admin_pass):
self.ldap_host = ldap_host
self.ldap_base_dn = ldap_base_dn
self.admin_cn = admin_cn
self.admin_pass = admin_pass
self.conn = ldap.initialize(ldap_host)
self.conn.set_option(ldap.OPT_REFERRALS, 0)
self.conn.protocol_version = ldap.VERSION3
self.conn.simple_bind_s(admin_cn, admin_pass)
def list(self, filter, scope=ldap.SCOPE_SUBTREE, attr=None):
try:
ldap_result = self.conn.search_s(self.ldap_base_dn, scope, filter, attr)
print 'Here is the result: '
for entry in ldap_result:
name, data = entry
print '#'*20, name, '#'*20
for k, v in data.items():
print '%s: %s' % (k,v)
except ldap.LDAPError, e:
print e
def add(self, dn, attrs):
try:
ldif = modlist.addModlist(attrs)
self.conn.add_s(dn, ldif)
except ldap.LDAPError, e:
print e
def modify(self, dn, attrs):
try:
attr_s = []
for k, v in attrs.items():
attr_s.append((2, k, v))
self.conn.modify_s(dn, attr_s)
except ldap.LDAPError, e:
print e
def delete(self, dn):
try:
self.conn.delete_s(dn)
except ldap.LDAPError, e:
print e
def gen_sha512(salt, password):
return crypt.crypt(password, '$6$%s$' % salt)
def login(request):
"""登录界面"""
if request.session.get('username'):
return HttpResponseRedirect('/')
if request.method == 'GET':
return render_to_response('login.html')
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if pam.authenticate(username, password):
if username in admin:
request.session['username'] = username
request.session['admin'] = 1
else:
request.session['username'] = username
request.session['admin'] = 0
return HttpResponseRedirect('/')
else:
error = '密码错误,请重新输入。'
return render_to_response('login.html',{'error': error})
def login_required(func):
"""要求登录的装饰器"""
def _deco(request, *args, **kwargs):
if not request.session.get('username'):
return HttpResponseRedirect('/login/')
return func(request, *args, **kwargs)
return _deco
def admin_required(func):
"""要求用户是admin的装饰器"""
def _deco(request, *args, **kwargs):
if not request.session.get('admin'):
return HttpResponseRedirect('/')
return func(request, *args, **kwargs)
return _deco
def logout(request):
"""注销登录调用"""
if request.session.get('username'):
del request.session['username']
return HttpResponseRedirect('/login/')
@login_required
def downKey(request):
"""下载key"""
username = request.session.get('username')
filename = '%s/keys/%s' % (base_dir, username)
f = open(filename)
data = f.read()
f.close()
response = HttpResponse(data, content_type='application/octet-stream')
response['Content-Disposition'] = 'attachment; filename=%s.rsa' % username
return response
@login_required
def index(request):
"""主页"""
username = request.session.get('username')
name = User.objects.filter(username=username)
assets = []
if name:
user_assets = AssetsUser.objects.filter(uid=name[0])
if user_assets:
for user_asset in user_assets:
assets.append(user_asset.aid)
return render_to_response('index.html', {'index': 'active', 'assets': assets},
context_instance=RequestContext(request))
@admin_required
def showUser(request):
"""查看所有用户"""
users = User.objects.all()
info = ''
error = ''
if request.method == 'POST':
selected_user = request.REQUEST.getlist('selected')
if selected_user:
for id in selected_user:
try:
user_del = User.objects.get(id=id)
username = user_del.username
user_del.delete()
except Exception,e:
error = u'数据库中用户删除错误' + unicode(e)
bash_del = bash("userdel -r %s" % username)
if bash_del != 0:
error = u'bash中用户删除错误'
try:
ldap_del = LDAPMgmt()
user_dn = "uid=%s,ou=People,%s" % (username, ldap_base_dn)
ldap_del.delete(user_dn)
except Exception, e:
error = u'ldap中用户删除错误' + unicode(e)
if not error:
info = '用户删除成功'
return render_to_response('showUser.html',
{'users': users, 'info': info, 'error': error, 'user_menu': 'active'},
context_instance=RequestContext(request))
@admin_required
def addUser(request):
"""添加用户"""
msg = ''
form = UserAddForm()
jm = PyCrypt(key)
if request.method == 'GET':
return render_to_response('addUser.html', {'user_menu': 'active', 'form': form},
context_instance=RequestContext(request))
else:
form = UserAddForm(request.POST)
if form.is_valid():
user = form.cleaned_data
username = user['username']
password = user['password']
key_pass = user['key_pass']
name = user['name']
is_admin = user['is_admin']
is_superuser = user['is_superuser']
ldap_password = keygen(16)
group_post = user['group']
groups = []
for group_name in group_post:
groups.append(Group.objects.get(name=group_name))
u = User(
username=username,
password=password,
key_pass=key_pass,
name=name,
is_admin=is_admin,
is_superuser=is_superuser,
ldap_password=ldap_password)
try:
u.save()
u.group = groups
u.save()
except Exception, e:
error = u'数据库插入用户错误' + unicode(e)
return render_to_response('addUser.html', {'user_menu': 'active', 'form': form, 'error': error},
context_instance=RequestContext(request))
ret_add = bash('useradd %s' % username)
ret_passwd = bash('echo %s | passwd --stdin %s' % (password, username))
ret_rsa = rsa_gen(username, key_pass)
if [ret_add, ret_passwd, ret_rsa].count(0) < 3:
error = u'跳板机添加用户失败'
ret_del = bash('userdel -r %s' % username)
u.delete()
return render_to_response('addUser.html', {'user_menu': 'active', 'form': form, 'error': error},
context_instance=RequestContext(request))
user_dn = "uid=%s,ou=People,%s" % (username, ldap_base_dn)
userPassword = gen_sha512(keygen(6), ldap_password)
user_attr = {
'uid': [str(username)],
'cn': [str(username)],
'objectClass': ['account', 'posixAccount', 'top', 'shadowAccount'],
'userPassword': ['{crypt}%s' % userPassword],
'shadowLastChange': ['16328'],
'shadowMin': ['0'],
'shadowMax': ['99999'],
'shadowWarning': ['7'],
'loginShell': ['/bin/bash'],
'uidNumber': [str(u.id)],
'gidNumber': [str(u.id)],
'homeDirectory': [str('/home/%s' % username)]}
group_dn = "cn=%s,out=Group,%s" % (username, ldap_base_dn)
group_attr = {
'objectClass': ['posixGroup', 'top'],
'cn': [str(username)],
'userPassword': ['{crypt}x'],
'gidNumber': [str(u.id)]
}
try:
ldap_user = LDAPMgmt()
ldap_user.add(user_dn, user_attr)
ldap_user.add(group_dn, group_attr)
except Exception, e:
error = u'添加ladp用户失败' + unicode(e)
try:
bash('userdel -r %s' % username)
u.delete()
ldap_user.delete(user_dn)
ldap_user.delete(group_dn)
except:
pass
return render_to_response('addUser.html', {'user_menu': 'active', 'form': form, 'error': error},
context_instance=RequestContext(request))
msg = u'添加用户成功'
return render_to_response('addUser.html', {'user_menu': 'active', 'form': form, 'msg': msg},
context_instance=RequestContext(request))
@admin_required
def showAssets(request):
"""查看服务器"""
info = ''
assets = Assets.objects.all()
if request.method == 'POST':
assets_del = request.REQUEST.getlist('selected')
for asset_id in assets_del:
asset_del = Assets.objects.get(id=asset_id)
asset_del.delete()
info = '主机信息删除成功!'
return render_to_response('showAssets.html', {'assets': assets, 'info': info, 'asset_menu': 'active'},
context_instance=RequestContext(request))
@admin_required
def addAssets(request):
"""添加服务器"""
error = ''
msg = ''
if request.method == 'POST':
ip = request.POST.get('ip')
port = request.POST.get('port')
comment = request.POST.get('comment')
if '' in (ip, port):
error = '带*号内容不能为空。'
elif Assets.objects.filter(ip=ip):
error = '主机已存在。'
if not error:
asset = Assets(ip=ip, port=port, comment=comment)
asset.save()
msg = u'%s 添加成功' % ip
return render_to_response('addAssets.html', {'msg': msg, 'error': error, 'asset_menu': 'active'},
context_instance=RequestContext(request))
@admin_required
def showPerm(request):
"""查看权限"""
users = User.objects.all()
if request.method == 'POST':
assets_del = request.REQUEST.getlist('selected')
username = request.POST.get('username')
user = User.objects.get(username=username)
for asset_id in assets_del:
asset = Assets.objects.get(id=asset_id)
asset_user_del = AssetsUser.objects.get(uid=user, aid=asset)
asset_user_del.delete()
return HttpResponseRedirect('/showPerm/?username=%s' % username)
elif request.method == 'GET':
if request.GET.get('username'):
username = request.GET.get('username')
user = User.objects.filter(username=username)[0]
assets_user = AssetsUser.objects.filter(uid=user.id)
return render_to_response('perms.html',
{'user': user, 'assets': assets_user, 'perm_menu': 'active'},
context_instance=RequestContext(request))
return render_to_response('showPerm.html', {'users': users, 'perm_menu': 'active'},
context_instance=RequestContext(request))
@admin_required
def addPerm(request):
"""增加授权"""
users = User.objects.all()
have_assets = []
if request.method == 'POST':
username = request.POST.get('username')
assets_id = request.REQUEST.getlist('asset')
user = User.objects.get(username=username)
for asset_id in assets_id:
asset = Assets.objects.get(id=asset_id)
asset_user = AssetsUser(uid=user, aid=asset)
asset_user.save()
return HttpResponseRedirect('/addPerm/?username=%s' % username)
elif request.method == 'GET':
if request.GET.get('username'):
username = request.GET.get('username')
user = User.objects.get(username=username)
assets_user = AssetsUser.objects.filter(uid=user.id)
for asset_user in assets_user:
have_assets.append(asset_user.aid)
all_assets = Assets.objects.all()
other_assets = list(set(all_assets) - set(have_assets))
return render_to_response('addUserPerm.html',
{'user': user, 'assets': other_assets, 'perm_menu': 'active'},
context_instance=RequestContext(request))
return render_to_response('addPerm.html',
{'users': users, 'perm_menu': 'active'},
context_instance=RequestContext(request))
@login_required
def chgPass(request):
"""修改登录系统的密码"""
error = ''
msg = ''
if request.method == 'POST':
username = request.session.get('username')
oldpass = request.POST.get('oldpass')
password = request.POST.get('password')
password_confirm = request.POST.get('password_confirm')
if '' in [oldpass, password, password_confirm]:
error = '带*内容不能为空'
elif not pam.authenticate(username, oldpass):
error = '密码不正确'
elif password != password_confirm:
error = '两次密码不匹配'
if not error:
ret = subprocess.call('%s %s %s' % (chgpass_shell, username, password), shell=True)
if ret:
error = '密码修改失败'
else:
msg = '修改密码成功'
return render_to_response('chgPass.html', {'msg': msg, 'error': error, 'pass_menu': 'active'},
context_instance=RequestContext(request))
@login_required
def chgKey(request):
"""修改密钥密码"""
error = ''
msg = ''
username = request.session.get('username')
oldpass = request.POST.get('oldpass')
password = request.POST.get('password')
password_confirm = request.POST.get('password_confirm')
keyfile = '%s/keys/%s' % (base_dir, username)
if request.method == 'POST':
if '' in [oldpass, password, password_confirm]:
error = '带*内容不能为空'
elif password != password_confirm:
error = '两次密码不匹配'
if not error:
ret = subprocess.call('ssh-keygen -p -P %s -N %s -f %s' % (oldpass, password, keyfile), shell=True)
if not ret:
error = '原来密码不正确'
else:
msg = '修改密码成功'
return render_to_response('chgKey.html',
{'error': error, 'msg': msg},
context_instance=RequestContext(request))