def run( self, module_name="shell", module_args="", timeout=10, forks=10, pattern="*", become=False, become_method="sudo", become_user="******", become_pass="", ): """ run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """ hoc = Runner( module_name=module_name, module_args=module_args, timeout=timeout, inventory=self.inventory, pattern=pattern, forks=forks, become=become, become_method=become_method, become_user=become_user, become_pass=become_pass, ) self.results_raw = hoc.run() logger.debug(self.results_raw) return self.results_raw
def asset_ansible_update(obj_list, name=''): resource = gen_resource(obj_list) ansible_instance = MyRunner(resource) ansible_instance.run(module_name='setup', pattern='*') ansible_asset_info = ansible_instance.results logger.debug('获取硬件信息: %s' % ansible_asset_info) for asset in obj_list: try: setup_info = ansible_asset_info['ok'][asset.hostname] logger.debug("setup_info: %s" % setup_info) except KeyError as e: logger.error("获取setup_info失败: %s" % e) continue else: try: asset_info = get_ansible_asset_info(asset.ip, setup_info) other_ip, mac, cpu, memory, disk, sn, system_type, system_version, brand, system_arch = asset_info asset_dic = { "other_ip": other_ip, "mac": mac, "cpu": cpu, "memory": memory, "disk": json.dumps(disk), "sn": sn, "system_type": system_type, "system_version": system_version, "system_arch": system_arch, "brand": brand } ansible_record(asset, asset_dic, name) except Exception as e: logger.error("save setup info failed! %s" % e) traceback.print_exc()
def gen_ssh_key(username, password='', key_dir=os.path.join(settings.KEY_DIR, 'user'), authorized_keys=True, home="/home", length=2048): """ 生成用户ssh密匙对 :param username: :param password: :param key_dir: :param authorized_keys: :param home: :param length: :return: """ logger.debug('生成ssh_key,并设置authorized_keys') private_key_file = os.path.join(key_dir, username+'.perm') os.mkdir(key_dir, mode=777) if os.path.isfile(private_key_file): os.unlink(private_key_file) ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"') % (private_key_file, length, password) if authorized_keys: auth_key_dir = os.path.join(home, username, '.ssh') mkdir(auth_key_dir, username=username, mode=700) authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys') with open(private_key_file + '.pub') as pub_f: with open(authorized_key_file, 'w') as auth_f: auth_f.write(pub_f.read()) os.chmod(authorized_key_file, mode=0600) chown(authorized_key_file, username)
def perm_sudo_add(request): """ list sudo commands alias :param request: :return: """ # 渲染数据 header_title, path1, path2 = "Sudo命令", "别名管理", "添加别名" try: if request.method == "POST": # 获取参数: name, comment name = request.POST.get("sudo_name").strip().upper() comment = request.POST.get("sudo_comment").strip() commands = request.POST.get("sudo_commands").strip() if not name or not commands: raise ServerError(u"sudo name 和 commands是必填项!") pattern = re.compile(r'[\n,\r]') deal_space_commands = list_drop_str(pattern.split(commands), u'') deal_all_commands = map(trans_all, deal_space_commands) commands = ', '.join(deal_all_commands) logger.debug(u'添加sudo %s: %s' % (name, commands)) if get_object(PermSudo, name=name): error = 'Sudo别名 %s已经存在' % name else: sudo = PermSudo(name=name.strip(), comment=comment, commands=commands) sudo.save() msg = u"添加Sudo命令别名: %s" % name except ServerError, e: error = e
def del_register(request): """ 删除注册信息 不同意用户的注册申请 """ logger.debug("开始删除注册记录, 执行函数: del_register") if request.method == "GET": user_ids = request.GET.get('id', '') logger.debug("%s -- GET del uids: %s" % (datetime.now(),user_ids)) user_id_list = user_ids.split(',') elif request.method == "POST": user_ids = request.POST.get('id', '') looger.debug("%s -- POST del uids: %s" % (datetime.now(), user_ids)) user_id_list = user_ids.split(',') else: logger.debug("%s -- 非GET, 也不是POST请求无法处理的错误" % datetime.now()) return HttpResponse('错误请求') for user_id in user_id_list: try: user = RegisterUser.objects.get(id=int(user_id)) logger.debug("%s -- del user: %s" % (datetime.now(), user.name)) except: return HttpResponse(u'error') else: if user and user.username != 'admin': user.delete() logger.debug(u"删除注册记录:%s(%s) " % (user.name, user.username)) return HttpResponse(u'删除成功')
def perm_sudo_edit(request): """ list sudo commands alias :param request: :return: """ # 渲染数据 header_title, path1, path2 = "Sudo命令", "别名管理", "编辑别名" sudo_id = request.GET.get("id") sudo = PermSudo.objects.get(id=sudo_id) try: if request.method == "POST": name = request.POST.get("sudo_name").upper() commands = request.POST.get("sudo_commands") comment = request.POST.get("sudo_comment") if not name or not commands: raise ServerError(u"sudo name 和 commands是必填项!") pattern = re.compile(r'[\n,\r]') deal_space_commands = list_drop_str(pattern.split(commands), u'') deal_all_commands = map(trans_all, deal_space_commands) commands = ', '.join(deal_all_commands).strip() logger.debug(u'添加sudo %s: %s' % (name, commands)) sudo.name = name.strip() sudo.commands = commands sudo.comment = comment sudo.save() msg = u"更新命令别名: %s" % name except ServerError, e: error = e
def asset_apply(request): """ 普通用户可以对需要访问的主机提出申请 """ error = "" msg = "" # 取得登陆用户的ID uid = request.user.id # 取得用户ID对应的User对象 user = User.objects.get(id=uid) logger.debug("访问主机申请") # 通过User对象获取用户所有的授权规则 rule = user.perm_rule.all()[0] # 所有主机 assets = Asset.objects.all() asset_appled = [] if request.method == "POST": asset_selected = request.POST.getlist('asset') if asset_selected == []: error = "请至少选择一台主机" else: for asset_id in asset_selected: asset = Asset.objects.get(id=asset_id) if asset not in rule.asset.all(): msg = msg + asset.ip + " " if msg != "": new_apply = ApplyHosts(username=user.username, hosts=msg,is_added=0) new_apply.save() msg = "申请已受理, 请耐心等待!" return render(request, 'avazu/asset_apply.html', locals())
def run(self, module_name='shell', module_args='', timeout=10, forks=10, pattern='*', become=False, become_method='sudo', become_user='******', become_pass=''): """ run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """ hoc = Runner(module_name=module_name, module_args=module_args, timeout=timeout, inventory=self.inventory, pattern=pattern, forks=forks, become=become, become_method=become_method, become_user=become_user, become_pass=become_pass) self.results_raw = hoc.run() logger.debug(self.results_raw) return self.results_raw
def gen_ssh_key(username, password='', key_dir=os.path.join(settings.KEY_DIR, 'user'), authorized_keys=True, home="/home", length=2048): """ generate a user ssh key in a property dir 生成一个用户ssh密钥对 """ logger.debug('生成ssh key, 并设置authorized_keys') private_key_file = os.path.join(key_dir, username + '.pem') mkdir(key_dir, mode=777) if os.path.isfile(private_key_file): os.unlink(private_key_file) ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password)) if authorized_keys: auth_key_dir = os.path.join(home, username, '.ssh') mkdir(auth_key_dir, username=username, mode=700) authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys') with open(private_key_file + '.pub') as pub_f: with open(authorized_key_file, 'w') as auth_f: auth_f.write(pub_f.read()) os.chmod(authorized_key_file, 0o600) chown(authorized_key_file, username)
def Yanzhengma(): VerificationCode = str(random.randint(100000, 999999)) TYPE = "touser" touser = str(sys.argv[1]) TIME = str(sys.argv[2]) content = VerificationCode subject = "验证码:" corpid = '*****************' corpsecret = '**********************************' accesstoken = gettoken(corpid, corpsecret) #发送验证码 Status = senddata(accesstoken, TYPE, touser, subject, content) logger.debug(Status) logger.debug("New user login:"******"\t" + USER) Times = 4 Status = "no" while (Times >= 2) and (Status == "no"): try: VerificationCodeInput = "" print '\033[1;33;40m' VerificationCodeInput = str(raw_input("请输入验证码:\033[1;37;40m")) print '\033[0m' except Exception, e: print Exception, ":", e if (VerificationCodeInput == VerificationCode): #print "欢迎登陆希望金融小分队跳板机!" Status = "ok" else: print '\033[1;31;40m' print "请输入正确的验证码!!!" print '\033[0m' Times -= 1
def perm_role_edit(request): """ edit role page """ # 渲染数据 header_title, path1, path2 = "系统用户", "系统用户管理", "系统用户编辑" # 渲染数据 role_id = request.GET.get("id") role = PermRole.objects.get(id=role_id) ori_name = role.name if request.method == "GET": # role_pass = CRYPTOR.decrypt(role.password) sudo_all = PermSudo.objects.all() role_sudos = role.sudo.all() sudo_all = PermSudo.objects.all() return my_render('jperm/perm_role_edit.html', locals(), request) if request.method == "POST": # 获取 POST 数据 role_name = request.POST.get("role_name") role_password = request.POST.get("role_password") role_comment = request.POST.get("role_comment") role_sudo_names = request.POST.getlist("sudo_name") role_sudos = [ PermSudo.objects.get(id=sudo_id) for sudo_id in role_sudo_names ] key_content = request.POST.get("role_key", "") if len(role_password) > 64: raise ServerError(u'密码长度不能超过64位!') try: # if not role: # raise ServerError('该系统用户不能存在') if role_name == "root": raise ServerError(u'禁止使用root用户作为系统用户,这样非常危险!') if PermRole.objects.get( name=role_name) and (role_name != ori_name): raise ServerError(u'role %s is already exists.' % role_name) if role_password: encrypt_pass = CRYPTOR.encrypt(role_password) role.password = encrypt_pass # 生成随机密码,生成秘钥对 if key_content: try: key_path = gen_keys(key=key_content, key_path_dir=role.key_path) except SSHException: raise ServerError('输入的密钥不合法') logger.debug('Recreate role key: %s' % role.key_path) # 写入数据库 role.name = role_name role.comment = role_comment role.sudo = role_sudos role.save() msg = u"更新系统用户: %s" % role.name return HttpResponseRedirect(reverse('role_list')) except ServerError, e: error = e
def download(self): while True: if not self.user_perm: self.user_perm = get_group_user_perm(self.user) try: print("进入批量下载模式") print("请输入主机名或ansile支持的pattern, 多个主机:分隔,q退出") pattern = input("\033[1;32mPattern>:\033[0m ").strip() if pattern == 'q': break else: assets = self.user_perm.get('asset').keys() res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm) runner = MyRunner(res) asset_name_str = '' print("匹配用户:\n") for inv in runner.inventory.get_hosts(pattern=pattern): asset_name_str += '%s ' % inv.name print(' %s' % inv.name) if not asset_name_str: color_print('没有匹配主机') continue print() while True: tmp_dir = get_tmp_dir() logger.debug('Download tmp dir: %s' % tmp_dir) print("请输入文件路径(不支持目录)") file_path = input("\033[1;32mPath>:\033[0m ").strip() if file_path == 'q': break if not file_path: color_print("文件路径为空") continue runner.run('fetch', module_args='src=%s dest=%s' % (file_path, tmp_dir), pattern=pattern) ret = runner.results FileLog(user=self.user.name, host=asset_name_str, filename=file_path, type='download', remote_ip=remote_ip, result=ret).save() logger.debug('Download file result: %s' % ret) os.chdir('/tmp') tmp_dir_name = os.path.basename(tmp_dir) if not os.listdir(tmp_dir): color_print('下载全部失败') continue bash('tar czf %s.tar.gz %s && sz %s.tar.gz' % (tmp_dir, tmp_dir_name, tmp_dir)) if ret.get('failed'): error = '文件名称: %s \n下载失败: [ %s ] \n下载成功 [ %s ]' % \ ('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('failed').keys()), ', '.join(ret.get('ok').keys())) color_print(error) else: msg = '文件名称: %s \n下载成功 [ %s ]' % ( '%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('ok').keys())) color_print(msg, 'green') print except IndexError: pass
def server_del_user(username): """ 删除系统上的用户 :param username: :return: """ bash('userdel -r -f %s' % username) logger.debug('rm -f %s/%s_*.perm' % (os.path.join(settings.KEY_DIR, 'user'), username)) bash('rm -f %s/%s_*.perm' % (os.path.join(settings.KEY_DIR,'user'),username))
def perm_role_add(request): """ add role page """ # 渲染数据 header_title, path1, path2 = "系统用户", "系统用户管理", "添加系统用户" login_user_id = request.user.id if not login_user_id: return HttpResponseRedirect(reverse('index')) login_user = User.objects.get(id=login_user_id) productlines = ProductLine.objects.all() sudos = PermSudo.objects.all().filter(productLine=login_user.productLine) if request.method == "POST": # 获取参数: name, comment name = request.POST.get("role_name", "").strip() comment = request.POST.get("role_comment", "") password = request.POST.get("role_password", "") key_content = request.POST.get("role_key", "") sudo_ids = request.POST.getlist('sudo_name') productline_name = request.POST.get('productline_name', '') productLine = get_object_or_404(ProductLine, name=productline_name) try: if get_object(PermRole, name=name, productLine=productLine): raise ServerError(u'已经存在该用户 %s' % name) if name == "root": raise ServerError(u'禁止使用root用户作为系统用户,这样非常危险!') default = get_object(Setting, name='default') if len(password) > 64: raise ServerError(u'密码长度不能超过64位!') if password: encrypt_pass = CRYPTOR.encrypt(password) else: encrypt_pass = CRYPTOR.encrypt(CRYPTOR.gen_rand_pass(20)) # 生成随机密码,生成秘钥对 sudos_obj = [ get_object(PermSudo, id=sudo_id) for sudo_id in sudo_ids ] if key_content: try: key_path = gen_keys(key=key_content) except SSHException, e: raise ServerError(e) else: key_path = gen_keys() logger.debug('generate role key: %s' % key_path) role = PermRole(name=name, productLine=productLine, comment=comment, password=encrypt_pass, key_path=key_path) role.save() role.sudo = sudos_obj msg = u"添加系统用户: %s" % name return HttpResponseRedirect(reverse('role_list'))
def download(self): while True: if not self.user_perm: self.user_perm = get_group_user_perm(self.user) try: print "进入批量下载模式" print "请输入主机名或ansible支持的pattern, 多个主机:分隔,q退出" pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip() if pattern == 'q': break else: assets = self.user_perm.get('asset').keys() res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm) runner = MyRunner(res) asset_name_str = '' print "匹配主机:\n" for inv in runner.inventory.get_hosts(pattern=pattern): asset_name_str += '%s ' % inv.name print ' %s' % inv.name if not asset_name_str: color_print('没有匹配主机') continue print while True: tmp_dir = get_tmp_dir() logger.debug('Download tmp dir: %s' % tmp_dir) print "请输入文件路径(不支持目录)" file_path = raw_input("\033[1;32mPath>:\033[0m ").strip() if file_path == 'q': break if not file_path: color_print("文件路径为空") continue runner.run('fetch', module_args='src=%s dest=%s' % (file_path, tmp_dir), pattern=pattern) ret = runner.results FileLog(user=self.user.name, host=asset_name_str, filename=file_path, type='download', remote_ip=remote_ip, result=ret).save() logger.debug('Download file result: %s' % ret) os.chdir('/tmp') tmp_dir_name = os.path.basename(tmp_dir) if not os.listdir(tmp_dir): color_print('下载全部失败') continue bash('tar czf %s.tar.gz %s && sz %s.tar.gz' % (tmp_dir, tmp_dir_name, tmp_dir)) if ret.get('failed'): error = '文件名称: %s \n下载失败: [ %s ] \n下载成功 [ %s ]' % \ ('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('failed').keys()), ', '.join(ret.get('ok').keys())) color_print(error) else: msg = '文件名称: %s \n下载成功 [ %s ]' % ('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('ok').keys())) color_print(msg, 'green') print except IndexError: pass
def perm_role_edit(request): """ edit role page """ # 渲染数据 header_title, path1, path2 = "系统用户", "系统用户管理", "系统用户编辑" # 渲染数据 role_id = request.GET.get("id") role = PermRole.objects.get(id=role_id) role_pass = CRYPTOR.decrypt(role.password) sudo_all = PermSudo.objects.all() role_sudos = role.sudo.all() sudo_all = PermSudo.objects.all() if request.method == "GET": return my_render('jperm/perm_role_edit.html', locals(), request) if request.method == "POST": # 获取 POST 数据 role_name = request.POST.get("role_name") role_password = request.POST.get("role_password") role_comment = request.POST.get("role_comment") role_sudo_names = request.POST.getlist("sudo_name") role_sudos = [PermSudo.objects.get(id=sudo_id) for sudo_id in role_sudo_names] key_content = request.POST.get("role_key", "") if len(role_password) > 64: raise ServerError(u'密码长度不能超过64位!') try: if not role: raise ServerError('该系统用户不能存在') if role_name == "root": raise ServerError(u'禁止使用root用户作为系统用户,这样非常危险!') if role_password: encrypt_pass = CRYPTOR.encrypt(role_password) role.password = encrypt_pass # 生成随机密码,生成秘钥对 if key_content: try: key_path = gen_keys(key=key_content, key_path_dir=role.key_path) except SSHException: raise ServerError('输入的密钥不合法') logger.debug('Recreate role key: %s' % role.key_path) # 写入数据库 role.name = role_name role.comment = role_comment role.sudo = role_sudos role.save() msg = u"更新系统用户: %s" % role.name return HttpResponseRedirect(reverse('role_list')) except ServerError, e: error = e
def download(request): user = request.user assets = list(get_group_user_perm(user).get('asset').keys()) asset_select = [] if request.method == 'POST': remote_ip = request.META.get('REMOTE_ADDR') asset_ids = request.POST.getlist('asset_ids', '') file_path = request.POST.get('file_path') date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S") download_dir = get_tmp_dir() for asset_id in asset_ids: asset_select.append(get_object(Asset, id=asset_id)) if not set(asset_select).issubset(set(assets)): illegal_asset = set(asset_select).issubset(set(assets)) return HttpResponse( '没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset])) res = gen_resource({'user': user, 'asset': asset_select}) runner = MyRunner(res) runner.run('fetch', module_args='src=%s dest=%s' % (file_path, download_dir), pattern='*') FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]), filename=file_path, type='download', remote_ip=remote_ip, result=runner.results).save() logger.debug(runner.results) tmp_dir_name = os.path.basename(download_dir) file_zip = '/tmp/' + tmp_dir_name + '.zip' zf = zipfile.ZipFile(file_zip, "w", zipfile.ZIP_DEFLATED) for dirname, subdirs, files in os.walk(download_dir): arcname = dirname.split(download_dir)[-1] if arcname: zf.write(dirname, arcname) for filename in files: filename = os.path.join(dirname, filename) arcname = filename.split(download_dir)[-1] zf.write(filename, arcname) zf.close() f = open(file_zip, 'rb') data = f.read() f.close() response = HttpResponse(data, content_type='application/octet-stream') response[ 'Content-Disposition'] = 'attachment; filename=%s.zip' % tmp_dir_name return response return render(request, 'download.html', locals())
def server_del_user(username): """ delete a user from jumpserver linux system 删除系统上的某用户 """ bash('userdel -r -f %s' % username) logger.debug('rm -f %s/%s_*.pem' % (os.path.join(settings.KEY_DIR, 'user'), username)) bash('rm -f %s/%s_*.pem' % (os.path.join(settings.KEY_DIR, 'user'), username)) bash('rm -f %s/%s.pem*' % (os.path.join(settings.KEY_DIR, 'user'), username))
def get_connect_info(self): """ 获取需要登陆的主机的信息和映射用户的账号密码 """ asset_info = get_asset_info(self.asset) role_key = get_role_key(self.user, self.role) # 获取角色的key,因为ansible需要权限是600,所以统一生成用户_角色key role_pass = CRYPTOR.decrypt(self.role.password) connect_info = {'user': self.user, 'asset': self.asset, 'ip': asset_info.get('ip'), 'port': int(asset_info.get('port')), 'role_name': self.role.name, 'role_pass': role_pass, 'role_key': role_key} logger.debug(connect_info) return connect_info
def perm_role_add(request): """ add role page """ # 渲染数据 header_title, path1, path2 = "系统用户", "系统用户管理", "添加系统用户" sudos = PermSudo.objects.all() if request.method == "POST": # 获取参数: name, comment name = request.POST.get("role_name", "").strip() comment = request.POST.get("role_comment", "") password = request.POST.get("role_password", "") key_content = request.POST.get("role_key", "") sudo_ids = request.POST.getlist('sudo_name') try: if get_object(PermRole, name=name): raise ServerError('已经存在该用户 %s' % name) if name == "root": raise ServerError('禁止使用root用户作为系统用户,这样非常危险!') default = get_object(Setting, name='default') if len(password) > 64: raise ServerError('密码长度不能超过64位!') if password: encrypt_pass = CRYPTOR.encrypt(password) else: encrypt_pass = CRYPTOR.encrypt(CRYPTOR.gen_rand_pass(20)) # 生成随机密码,生成秘钥对 sudos_obj = [ get_object(PermSudo, id=sudo_id) for sudo_id in sudo_ids ] if key_content: try: key_path = gen_keys(key=key_content) except SSHException as e: raise ServerError(e) else: key_path = gen_keys() logger.debug('generate role key: %s' % key_path) role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path) role.save() role.sudo = sudos_obj msg = "添加系统用户: %s" % name return HttpResponseRedirect(reverse('role_list')) except ServerError as e: error = e return my_render('jperm/perm_role_add.html', locals(), request)
def perm_role_get(request): asset_id = request.GET.get('id', 0) if asset_id: asset = get_object(Asset, id=asset_id) if asset: role = user_have_perm(request.user, asset=asset) logger.debug(u'获取授权系统用户: ' + ','.join([i.name for i in role])) return HttpResponse(','.join([i.name for i in role])) else: roles = get_group_user_perm(request.user).get('role').keys() return HttpResponse(','.join(i.name for i in roles)) return HttpResponse('error')
def get_log(self): """ Logging user command and output. 记录用户的日志 """ banned_list = ['/', '\0', '*', '?'] tty_log_dir = os.path.join(LOG_DIR, 'tty') date_today = datetime.datetime.now() date_start = date_today.strftime('%Y%m%d') time_start = date_today.strftime('%H%M%S') today_connect_log_dir = os.path.join(tty_log_dir, date_start) filename = '%s_%s_%s' % (self.username, self.asset_name, time_start) for banned_char in banned_list: filename = filename.replace(banned_char, '_') log_file_path = os.path.join(today_connect_log_dir, filename) try: mkdir(os.path.dirname(today_connect_log_dir), mode=777) mkdir(today_connect_log_dir, mode=777) except OSError as e: logger.debug('创建目录 %s 失败,请修改%s目录权限 With error msg: %s' % (today_connect_log_dir, tty_log_dir, e)) raise ServerError('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir)) try: log_file_f = open(log_file_path + '.log', 'a') log_time_f = open(log_file_path + '.time', 'a') except IOError as e: logger.debug('创建tty日志文件失败, 请修改目录%s权限 With error msg: %s' % (today_connect_log_dir, e)) raise ServerError('创建tty日志文件失败, 请修改目录%s权限' % today_connect_log_dir) if self.login_type == 'ssh': # 如果是ssh连接过来,记录connect.py的pid,web terminal记录为日志的id pid = os.getpid() self.remote_ip = remote_ip # 获取远端IP else: pid = 0 log = Log(user=self.username, host=self.asset_name, remote_ip=self.remote_ip, login_type=self.login_type, log_path=log_file_path, start_time=date_today, pid=pid) log.save() if self.login_type == 'web': log.pid = log.id # 设置log id为websocket的id, 然后kill时干掉websocket log.save() log_file_f.write('Start at %s\r\n' % datetime.datetime.now()) return log_file_f, log_time_f, log
def get_log(self): """ Logging user command and output. 记录用户的日志 """ tty_log_dir = os.path.join(LOG_DIR, "tty") date_today = datetime.datetime.now() date_start = date_today.strftime("%Y%m%d") time_start = date_today.strftime("%H%M%S") today_connect_log_dir = os.path.join(tty_log_dir, date_start) log_file_path = os.path.join(today_connect_log_dir, "%s_%s_%s" % (self.username, self.asset_name, time_start)) try: mkdir(os.path.dirname(today_connect_log_dir), mode=0777) mkdir(today_connect_log_dir, mode=0777) except OSError: logger.debug("创建目录 %s 失败,请修改%s目录权限" % (today_connect_log_dir, tty_log_dir)) raise ServerError("创建目录 %s 失败,请修改%s目录权限" % (today_connect_log_dir, tty_log_dir)) try: log_file_f = open(log_file_path + ".log", "a") log_time_f = open(log_file_path + ".time", "a") except IOError: logger.debug("创建tty日志文件失败, 请修改目录%s权限" % today_connect_log_dir) raise ServerError("创建tty日志文件失败, 请修改目录%s权限" % today_connect_log_dir) if self.login_type == "ssh": # 如果是ssh连接过来,记录connect.py的pid,web terminal记录为日志的id pid = os.getpid() self.remote_ip = remote_ip # 获取远端IP else: pid = 0 log = Log( user=self.username, host=self.asset_name, remote_ip=self.remote_ip, login_type=self.login_type, log_path=log_file_path, start_time=date_today, pid=pid, ) log.save() if self.login_type == "web": log.pid = log.id # 设置log id为websocket的id, 然后kill时干掉websocket log.save() log_file_f.write("Start at %s\r\n" % datetime.datetime.now()) return log_file_f, log_time_f, log
def run(self, module_name='shell', module_args='', timeout=10, forks=10, pattern='*', become=False, become_method='sudo', become_user='******', become_pass=''): """ run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """ if module_name == 'user_check': hoc = Runner(module_name='command', module_args='cat /etc/group', timeout=timeout, inventory=self.inventory, pattern=pattern, forks=forks, become=become, become_method=become_method, become_user=become_user, become_pass=become_pass ) temp_result= hoc.run() output = temp_result['contacted'] temp_list = list() for node in output.keys(): lines = output[node]['stdout'].split('\n') groups = [line.split(':')[0] for line in lines] if module_name == 'user_check': for g in groups: temp_name = 'name='+g if module_args.split(' ')[0] == temp_name: temp_list.append(node) break if temp_list: return {'flag': False, 'nodes': temp_list} hoc = Runner(module_name=module_name, module_args=module_args, timeout=timeout, inventory=self.inventory, pattern=pattern, forks=forks, become=become, become_method=become_method, become_user=become_user, become_pass=become_pass ) self.results_raw = hoc.run() logger.debug(self.results_raw) return self.results_raw
def upload(request): user = request.user assets = list(get_group_user_perm(user).get('asset').keys()) asset_select = [] if request.method == 'POST': remote_ip = request.META.get('REMOTE_ADDR') asset_ids = request.POST.getlist('asset_ids', '') upload_files = request.FILES.getlist('file[]', None) date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S") upload_dir = get_tmp_dir() # file_dict = {} for asset_id in asset_ids: asset_select.append(get_object(Asset, id=asset_id)) if not set(asset_select).issubset(set(assets)): illegal_asset = set(asset_select).issubset(set(assets)) return HttpResponse( '没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset])) for upload_file in upload_files: file_path = '%s/%s' % (upload_dir, upload_file.name) with open(file_path, 'wb+') as f: for chunk in upload_file.chunks(): f.write(chunk) res = gen_resource({'user': user, 'asset': asset_select}) runner = MyRunner(res) runner.run('copy', module_args='src=%s dest=%s' % (upload_dir, '/tmp'), pattern='*') ret = runner.results logger.debug(ret) FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]), filename=' '.join([f.name for f in upload_files]), type='upload', remote_ip=remote_ip, result=ret).save() if ret.get('failed'): error = '上传目录: %s <br> 上传失败: [ %s ] <br>上传成功 [ %s ]' % ( upload_dir, ', '.join(list(ret.get('failed').keys())), ', '.join(list(ret.get('ok').keys()))) return HttpResponse(error, status=500) msg = '上传目录: %s <br> 传送成功 [ %s ]' % (upload_dir, ', '.join( list(ret.get('ok').keys()))) return HttpResponse(msg) return my_render('upload.html', locals(), request)
def user_del(request): if request.method == "GET": user_ids = request.GET.get('id', '') user_id_list = user_ids.split(',') elif request.method == "POST": user_ids = request.POST.get('id', '') user_id_list = user_ids.split(',') else: return HttpResponse('错误请求') for user_id in user_id_list: user = get_object(User, id=user_id) if user and user.username != 'admin': logger.debug("删除用户 %s " % user.username) server_del_user(user.username) user.delete() return HttpResponse('删除成功')
def get_connect_info(self): """ 获取需要登陆的主机的信息和映射用户的账号密码 """ asset_info = get_asset_info(self.asset) role_key = get_role_key(self.user, self.role) # 获取角色的key,因为ansible需要权限是600,所以统一生成用户_角色key role_pass = CRYPTOR.decrypt(self.role.password) connect_info = { "user": self.user, "asset": self.asset, "ip": asset_info.get("ip"), "port": int(asset_info.get("port")), "role_name": self.role.name, "role_pass": role_pass, "role_key": role_key, } logger.debug(connect_info) return connect_info
def perm_role_add(request): """ add role page """ # 渲染数据 header_title, path1, path2 = "系统用户", "系统用户管理", "添加系统用户" sudos = PermSudo.objects.all() if request.method == "POST": # 获取参数: name, comment name = request.POST.get("role_name", "").strip() comment = request.POST.get("role_comment", "") password = request.POST.get("role_password", "") key_content = request.POST.get("role_key", "") sudo_ids = request.POST.getlist('sudo_name') try: if get_object(PermRole, name=name): raise ServerError(u'已经存在该用户 %s' % name) if name == "root": raise ServerError(u'禁止使用root用户作为系统用户,这样非常危险!') default = get_object(Setting, name='default') if len(password) > 64: raise ServerError(u'密码长度不能超过64位!') if password: encrypt_pass = CRYPTOR.encrypt(password) else: encrypt_pass = CRYPTOR.encrypt(CRYPTOR.gen_rand_pass(20)) # 生成随机密码,生成秘钥对 sudos_obj = [get_object(PermSudo, id=sudo_id) for sudo_id in sudo_ids] if key_content: try: key_path = gen_keys(key=key_content) except SSHException, e: raise ServerError(e) else: key_path = gen_keys() logger.debug('generate role key: %s' % key_path) role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path) role.save() role.sudo = sudos_obj msg = u"添加系统用户: %s" % name return HttpResponseRedirect(reverse('role_list'))
def perm_sudo_add(request): """ list sudo commands alias :param request: :return: """ # 渲染数据 header_title, path1, path2 = "Sudo命令", "别名管理", "添加别名" login_user_id = request.user.id if not login_user_id: return HttpResponseRedirect(reverse('index')) login_user = User.objects.get(id=login_user_id) productlines = ProductLine.objects.all() try: if request.method == "POST": # 获取参数: name, comment name = request.POST.get("sudo_name").strip().upper() comment = request.POST.get("sudo_comment").strip() commands = request.POST.get("sudo_commands").strip() productline_name = request.POST.get('productline_name', '') productLine = get_object_or_404(ProductLine, name=productline_name) if not name or not commands: raise ServerError(u"sudo name 和 commands是必填项!") pattern = re.compile(r'[\n,\r]') deal_space_commands = list_drop_str(pattern.split(commands), u'') deal_all_commands = map(trans_all, deal_space_commands) commands = ', '.join(deal_all_commands) logger.debug(u'添加sudo %s: %s' % (name, commands)) if get_object(PermSudo, name=name, productLine=productLine): error = 'Sudo别名 %s已经存在' % name else: sudo = PermSudo(name=name.strip(), comment=comment, productLine=productLine, commands=commands) sudo.save() msg = u"添加Sudo命令别名: %s" % name except ServerError, e: error = e
def run(self, module_name='shell', module_args='', timeout=10, forks=10, pattern='*', become=False, become_method='sudo', become_user='******', become_pass=''): """ run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """ hoc = Runner(module_name=module_name, module_args=module_args, timeout=timeout, inventory=self.inventory, pattern=pattern, forks=forks, become=become, become_method=become_method, become_user=become_user, become_pass=become_pass ) self.results_raw = hoc.run() logger.debug(self.results_raw) return self.results_raw
def upload(self): while True: try: print "进入批量上传模式" print print "授权包含该系统用户的所有主机" assets = self.user_perm.get('asset').keys() for asset in assets: print ' %s' % asset.hostname print print "请输入主机名或ansible支持的pattern, 多个主机:分隔 q退出" print pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip() if pattern == 'q': break else: res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm) runner = MyRunner(res) asset_name_str = '' print "匹配主机:" for inv in runner.inventory.get_hosts(pattern=pattern): print inv.name asset_name_str += '%s ' % inv.name if not asset_name_str: color_print('没有匹配主机') continue tmp_dir = get_tmp_dir() logger.debug('Upload tmp dir: %s' % tmp_dir) os.chdir(tmp_dir) bash('rz') filename_str = ' '.join(os.listdir(tmp_dir)) if not filename_str: color_print("上传文件为空") continue logger.debug('上传文件: %s' % filename_str) runner = MyRunner(res) runner.run('copy', module_args='src=%s dest=%s directory_mode' % (tmp_dir, '/tmp'), pattern=pattern) ret = runner.results FileLog(user=self.user.username, name=self.user.name, host=asset_name_str, filename=filename_str, remote_ip=remote_ip, type='upload', result=ret).save() logger.debug('Upload file: %s' % ret) if ret.get('failed'): error = '上传目录: %s \n上传失败: [ %s ] \n上传成功 [ %s ]' % (tmp_dir, ', '.join(ret.get('failed').keys()), ', '.join(ret.get('ok').keys())) color_print(error) else: msg = '上传目录: %s \n传送成功 [ %s ]' % (tmp_dir, ', '.join(ret.get('ok').keys())) color_print(msg, 'green') print except IndexError: pass
def upload(self): while True: if not self.user_perm: self.user_perm = get_group_user_perm(self.user) try: print "进入批量上传模式" print "请输入主机名或ansible支持的pattern, 多个主机:分隔 q退出" pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip() if pattern == 'q': break else: assets = self.user_perm.get('asset').keys() res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm) runner = MyRunner(res) asset_name_str = '' print "匹配主机:" for inv in runner.inventory.get_hosts(pattern=pattern): print inv.name asset_name_str += '%s ' % inv.name if not asset_name_str: color_print('没有匹配主机') continue tmp_dir = get_tmp_dir() logger.debug('Upload tmp dir: %s' % tmp_dir) os.chdir(tmp_dir) bash('rz') filename_str = ' '.join(os.listdir(tmp_dir)) if not filename_str: color_print("上传文件为空") continue logger.debug('上传文件: %s' % filename_str) runner = MyRunner(res) runner.run('copy', module_args='src=%s dest=%s directory_mode' % (tmp_dir, tmp_dir), pattern=pattern) ret = runner.results FileLog(user=self.user.name, host=asset_name_str, filename=filename_str, remote_ip=remote_ip, type='upload', result=ret).save() logger.debug('Upload file: %s' % ret) if ret.get('failed'): error = '上传目录: %s \n上传失败: [ %s ] \n上传成功 [ %s ]' % (tmp_dir, ', '.join(ret.get('failed').keys()), ', '.join(ret.get('ok').keys())) color_print(error) else: msg = '上传目录: %s \n传送成功 [ %s ]' % (tmp_dir, ', '.join(ret.get('ok').keys())) color_print(msg, 'green') print except IndexError: pass
def add_register(request): """ 为注册用户创建jumpserver账号 """ logger.debug('添加注册用户到jumpserver, 执行函数: add_register') if request.method == 'GET': uid = request.GET.get('id','') logger.debug('选中的用户ID为: %s' % uid) # 取出选中的注册用户记录 try: new_user = RegisterUser.objects.get(id=uid) logger.debug("添加用户: %s(%s)", (new_user.username, new_user.name)) except: logger.debug("ERROR: 在注册用户表(registereduser)中没有找到用户, 添加失败") return HttpResponse("ERROR: 注册失败") msg = add_register_user(new_user) return HttpResponse(msg) else: return HttpResponse('improssable!')
def add_register_user(register_user): """ 创建用户账号 """ logger.debug("进入工具函数: 'add_register_user'") # 用户姓名 name = register_user.name # 注册账号名及密码 username = register_user.username password = register_user.password email = register_user.email # 自动生成用户UUID及SSH密钥 uuid_r = uuid.uuid4().get_hex() ssh_key_pwd = PyCrypt.gen_rand_pass(16) # 默认用户不加入任何组 groups = [] admin_groups = [] # 用户默认为普通用户 role = 'CU' # 默认激活用户账号 is_active = 1 try: # 创建jumpserver的User对象 user = db_add_user(username=username, name=name, password=password, email=email, role=role, uuid=uuid_r, groups=groups, admin_groups=admin_groups, ssh_key_pwd=ssh_key_pwd, is_active=is_active, date_joined=datetime.now()) logger.debug("jumpserver用户添加成功: %s", user.username) # 在堡垒机上添加jumpserver用户对应的操作系统账号 server_add_user(username=username, ssh_key_pwd=ssh_key_pwd) logger.debug("操作系统账号添加成功: %s", user.username) except ServerError, e: loggeo.debug(u'jumpserver用户账号添加失败: %s' % username) raise ServerError
except ServerError, e: loggeo.debug(u'jumpserver用户账号添加失败: %s' % username) raise ServerError # 开始为用户创建授权规则(PermRule) # 默认为每一个新注册用户创建一个与账号名相同的授权规则 # 该授权中含有一个名为'zero'的资产组, 资产组中所包含的主机数量为0 # rule_name = user.username # 授权规则说明信息 rule_comment = u'给(%s)的授权. 创建于: %s' % (user.name, datetime.now()) # 授权规则说明 # 创建一个授权规则对象, 随后更新授权信息 new_rule = PermRule(name=rule_name, comment=rule_comment) new_rule.save() logger.debug("%s :授权规则对象创建成功" % new_rule.name) try: # 授权规则对应的用户 rule_to_user = user logger.debug("规则对应的用户为 %s" % user.username) # 'zero'资产组 # 默认每个注册用户都会被赋予'zero'资产组 # asset_group = AssetGroup.objects.get(name='zero') logger.debug("规则对应的资产组为: %s" % asset_group.name) except e: logger.debug("ERROR: 无法找到用户或资产组: %s" % e) return "ERROR: 更新授权规则失败" # 系统用户, 账号关联到的系统账号(jperm_permrole)
def upload(self): while True: if not self.user_perm: self.user_perm = get_group_user_perm(self.user) try: print "进入批量上传模式" print "请输入主机名或ansile支持的pattern, 多个主机:分隔 q退出" pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip() if pattern == "q": break else: assets = self.user_perm.get("asset").keys() res = gen_resource({"user": self.user, "asset": assets}, perm=self.user_perm) runner = MyRunner(res) asset_name_str = "" print "匹配主机:" for inv in runner.inventory.get_hosts(pattern=pattern): print inv.name asset_name_str += "%s " % inv.name if not asset_name_str: color_print("没有匹配主机") continue tmp_dir = get_tmp_dir() logger.debug("Upload tmp dir: %s" % tmp_dir) os.chdir(tmp_dir) bash("rz") filename_str = " ".join(os.listdir(tmp_dir)) if not filename_str: color_print("上传文件为空") continue logger.debug("上传文件: %s" % filename_str) runner = MyRunner(res) runner.run( "copy", module_args="src=%s dest=%s directory_mode" % (tmp_dir, tmp_dir), pattern=pattern ) ret = runner.results FileLog( user=self.user.name, host=asset_name_str, filename=filename_str, remote_ip=remote_ip, type="upload", result=ret, ).save() logger.debug("Upload file: %s" % ret) if ret.get("failed"): error = "上传目录: %s \n上传失败: [ %s ] \n上传成功 [ %s ]" % ( tmp_dir, ", ".join(ret.get("failed").keys()), ", ".join(ret.get("ok").keys()), ) color_print(error) else: msg = "上传目录: %s \n传送成功 [ %s ]" % (tmp_dir, ", ".join(ret.get("ok").keys())) color_print(msg, "green") print except IndexError: pass
def perm_role_edit(request): """ edit role page """ # 渲染数据 header_title, path1, path2 = "系统用户", "系统用户管理", "系统用户编辑" # 渲染数据 role_id = request.GET.get("id") role = PermRole.objects.get(id=role_id) role_pass = CRYPTOR.decrypt(role.password) role_sudos = role.sudo.all() productlines = ProductLine.objects.all() username = request.user.username user_perm = request.session['role_id'] if user_perm == 2: sudo_all = PermSudo.objects.all() elif user_perm == 1: login_user = get_object(User, username=username) sudo_all = PermSudo.objects.all().filter( productLine=login_user.productLine) if request.method == "GET": return my_render('jperm/perm_role_edit.html', locals(), request) if request.method == "POST": # 获取 POST 数据 role_name = request.POST.get("role_name") role_password = request.POST.get("role_password") role_comment = request.POST.get("role_comment") role_sudo_names = request.POST.getlist("sudo_name") role_sudos = [ PermSudo.objects.get(id=sudo_id) for sudo_id in role_sudo_names ] key_content = request.POST.get("role_key", "") productline_name = request.POST.get('productline_name', '') productLine = get_object_or_404(ProductLine, name=productline_name) if len(role_password) > 64: raise ServerError(u'密码长度不能超过64位!') try: if not role: raise ServerError('该系统用户不能存在') if role_name == "root": raise ServerError(u'禁止使用root用户作为系统用户,这样非常危险!') if role_password: encrypt_pass = CRYPTOR.encrypt(role_password) role.password = encrypt_pass # 生成随机密码,生成秘钥对 if key_content: try: key_path = gen_keys(key=key_content, key_path_dir=role.key_path) except SSHException: raise ServerError('输入的密钥不合法') logger.debug('Recreate role key: %s' % role.key_path) # 写入数据库 role.name = role_name role.comment = role_comment role.sudo = role_sudos role.productLine = productLine role.save() msg = u"更新系统用户: %s" % role.name return HttpResponseRedirect(reverse('role_list')) except ServerError, e: error = e
else: return HttpResponse("filter_type: ?") except ServerError, e: return HttpResponse(e) if request.method == "POST": try: # 获取参数删除的role对象 role_id = request.POST.get("id") role = get_object(PermRole, id=role_id) if not role: logger.warning(u"Delete Role: role_id %s not exist" % role_id) raise ServerError(u"role_id %s 无数据记录" % role_id) role_key = role.key_path # 删除推送到主机上的role recycle_assets = [push.asset for push in role.perm_push.all() if push.success] logger.debug(u"delete role %s - delete_assets: %s" % (role.name, recycle_assets)) if recycle_assets: recycle_resource = gen_resource(recycle_assets) task = MyTask(recycle_resource) try: msg_del_user = task.del_user(get_object(PermRole, id=role_id).name) msg_del_sudo = task.del_user_sudo(get_object(PermRole, id=role_id).name) except Exception, e: logger.warning(u"Recycle Role failed: %s" % e) raise ServerError(u"回收已推送的系统用户失败: %s" % e) logger.info(u"delete role %s - execute delete user: %s" % (role.name, msg_del_user)) logger.info(u"delete role %s - execute delete sudo: %s" % (role.name, msg_del_sudo)) # TODO: 判断返回结果,处理异常 # 删除存储的秘钥,以及目录 try: key_files = os.listdir(role_key)
def download(self): while True: if not self.user_perm: self.user_perm = get_group_user_perm(self.user) try: print "进入批量下载模式" print "请输入主机名或ansile支持的pattern, 多个主机:分隔,q退出" pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip() if pattern == "q": break else: assets = self.user_perm.get("asset").keys() res = gen_resource({"user": self.user, "asset": assets}, perm=self.user_perm) runner = MyRunner(res) asset_name_str = "" print "匹配主机:\n" for inv in runner.inventory.get_hosts(pattern=pattern): asset_name_str += "%s " % inv.name print " %s" % inv.name if not asset_name_str: color_print("没有匹配主机") continue print while True: tmp_dir = get_tmp_dir() logger.debug("Download tmp dir: %s" % tmp_dir) print "请输入文件路径(不支持目录)" file_path = raw_input("\033[1;32mPath>:\033[0m ").strip() if file_path == "q": break if not file_path: color_print("文件路径为空") continue runner.run("fetch", module_args="src=%s dest=%s" % (file_path, tmp_dir), pattern=pattern) ret = runner.results FileLog( user=self.user.name, host=asset_name_str, filename=file_path, type="download", remote_ip=remote_ip, result=ret, ).save() logger.debug("Download file result: %s" % ret) os.chdir("/tmp") tmp_dir_name = os.path.basename(tmp_dir) if not os.listdir(tmp_dir): color_print("下载全部失败") continue bash("tar czf %s.tar.gz %s && sz %s.tar.gz" % (tmp_dir, tmp_dir_name, tmp_dir)) if ret.get("failed"): error = "文件名称: %s \n下载失败: [ %s ] \n下载成功 [ %s ]" % ( "%s.tar.gz" % tmp_dir_name, ", ".join(ret.get("failed").keys()), ", ".join(ret.get("ok").keys()), ) color_print(error) else: msg = "文件名称: %s \n下载成功 [ %s ]" % ( "%s.tar.gz" % tmp_dir_name, ", ".join(ret.get("ok").keys()), ) color_print(msg, "green") print except IndexError: pass
def perm_role_push(request): """ the role push page """ # 渲染数据 header_title, path1, path2 = "系统用户", "系统用户管理", "系统用户推送" role_id = request.GET.get('id') asset_ids = request.GET.get('asset_id') role = get_object(PermRole, id=role_id) assets = Asset.objects.all() asset_groups = AssetGroup.objects.all() if asset_ids: need_push_asset = [ get_object(Asset, id=asset_id) for asset_id in asset_ids.split(',') ] if request.method == "POST": # 获取推荐角色的名称列表 # 计算出需要推送的资产列表 asset_ids = request.POST.getlist("assets") asset_group_ids = request.POST.getlist("asset_groups") assets_obj = [Asset.objects.get(id=asset_id) for asset_id in asset_ids] asset_groups_obj = [ AssetGroup.objects.get(id=asset_group_id) for asset_group_id in asset_group_ids ] group_assets_obj = [] for asset_group in asset_groups_obj: group_assets_obj.extend(asset_group.asset_set.all()) calc_assets = list(set(assets_obj) | set(group_assets_obj)) push_resource = gen_resource(calc_assets) # 调用Ansible API 进行推送 password_push = True if request.POST.get("use_password") else False key_push = True if request.POST.get("use_publicKey") else False task = MyTask(push_resource) ret = {} # 因为要先建立用户,而push key是在 password也完成的情况下的 可选项 # 1. 以秘钥 方式推送角色 if key_push: ret["pass_push"] = task.add_user(role.name) ret["key_push"] = task.push_key( role.name, os.path.join(role.key_path, 'id_rsa.pub')) # 2. 推送账号密码 <为了安全 系统用户统一使用秘钥进行通信, 不再提供密码方式的推送> # elif password_push: # ret["pass_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password)) # 3. 推送sudo配置文件 if key_push: sudo_list = set([sudo for sudo in role.sudo.all() ]) # set(sudo1, sudo2, sudo3) if sudo_list: ret['sudo'] = task.push_sudo_file([role], sudo_list) logger.debug('推送role结果: %s' % ret) success_asset = {} failed_asset = {} logger.debug(ret) for push_type, result in ret.items(): if result.get('failed'): for hostname, info in result.get('failed').items(): if hostname in failed_asset.keys(): if info in failed_asset.get(hostname): failed_asset[hostname] += info else: failed_asset[hostname] = info for push_type, result in ret.items(): if result.get('ok'): for hostname, info in result.get('ok').items(): if hostname in failed_asset.keys(): continue elif hostname in success_asset.keys(): if str(info) in success_asset.get(hostname, ''): success_asset[hostname] += str(info) else: success_asset[hostname] = str(info) # 推送成功 回写push表 for asset in calc_assets: push_check = PermPush.objects.filter(role=role, asset=asset) if push_check: func = push_check.update else: def func(**kwargs): PermPush(**kwargs).save() if failed_asset.get(asset.hostname): func(is_password=password_push, is_public_key=key_push, role=role, asset=asset, success=False, result=failed_asset.get(asset.hostname)) else: func(is_password=password_push, is_public_key=key_push, role=role, asset=asset, success=True) if not failed_asset: msg = u'系统用户 %s 推送成功[ %s ]' % (role.name, ','.join( success_asset.keys())) else: error = u'系统用户 %s 推送失败 [ %s ], 推送成功 [ %s ] 进入系统用户详情,查看失败原因' % ( role.name, ','.join(failed_asset.keys()), ','.join( success_asset.keys())) return my_render('jperm/perm_role_push.html', locals(), request)
except ServerError, e: return HttpResponse(e) if request.method == "POST": try: # 获取参数删除的role对象 role_id = request.POST.get("id") role = get_object(PermRole, id=role_id) if not role: logger.warning(u"Delete Role: role_id %s not exist" % role_id) raise ServerError(u"role_id %s 无数据记录" % role_id) role_key = role.key_path # 删除推送到主机上的role recycle_assets = [ push.asset for push in role.perm_push.all() if push.success ] logger.debug(u"delete role %s - delete_assets: %s" % (role.name, recycle_assets)) if recycle_assets: recycle_resource = gen_resource(recycle_assets) task = MyTask(recycle_resource) try: msg_del_user = task.del_user( get_object(PermRole, id=role_id).name) msg_del_sudo = task.del_user_sudo( get_object(PermRole, id=role_id).name) except Exception, e: logger.warning(u"Recycle Role failed: %s" % e) raise ServerError(u"回收已推送的系统用户失败: %s" % e) logger.info(u"delete role %s - execute delete user: %s" % (role.name, msg_del_user)) logger.info(u"delete role %s - execute delete sudo: %s" % (role.name, msg_del_sudo))
def gen_resource(ob, perm=None): """ ob为用户或资产列表或资产queryset, 如果同时输入用户和{'role': role1, 'asset': []},则获取用户在这些资产上的信息 生成MyInventory需要的 resource文件 """ res = [] if isinstance(ob, dict): role = ob.get('role') asset_r = ob.get('asset') user = ob.get('user') if not perm: perm = get_group_user_perm(user) if role: roles = perm.get('role', {}).keys() # 获取用户所有授权角色 if role not in roles: return {} role_assets_all = perm.get('role').get(role).get( 'asset') # 获取用户该角色所有授权主机 assets = set(role_assets_all) & set(asset_r) # 获取用户提交中合法的主机 for asset in assets: asset_info = get_asset_info(asset) role_key = get_role_key(user, role) info = { 'hostname': asset.hostname, 'ip': asset.ip, 'port': asset_info.get('port', 22), 'ansible_ssh_private_key_file': role_key, 'username': role.name, # 'password': CRYPTOR.decrypt(role.password) } if os.path.isfile(role_key): info['ssh_key'] = role_key res.append(info) else: for asset, asset_info in perm.get('asset').items(): if asset not in asset_r: continue asset_info = get_asset_info(asset) try: role = sorted( list(perm.get('asset').get(asset).get('role')))[0] except IndexError: continue role_key = get_role_key(user, role) info = { 'hostname': asset.hostname, 'ip': asset.ip, 'port': asset_info.get('port', 22), 'username': role.name, 'password': CRYPTOR.decrypt(role.password), } if os.path.isfile(role_key): info['ssh_key'] = role_key res.append(info) elif isinstance(ob, User): if not perm: perm = get_group_user_perm(ob) for asset, asset_info in perm.get('asset').items(): asset_info = get_asset_info(asset) info = { 'hostname': asset.hostname, 'ip': asset.ip, 'port': asset_info.get('port', 22) } try: role = sorted(list( perm.get('asset').get(asset).get('role')))[0] except IndexError: continue info['username'] = role.name info['password'] = CRYPTOR.decrypt(role.password) role_key = get_role_key(ob, role) if os.path.isfile(role_key): info['ssh_key'] = role_key res.append(info) elif isinstance(ob, (list, QuerySet)): for asset in ob: info = get_asset_info(asset) res.append(info) logger.debug('生成res: %s' % res) return res
def perm_role_push(request): """ the role push page """ # 渲染数据 header_title, path1, path2 = "系统用户", "系统用户管理", "系统用户推送" role_id = request.GET.get('id') asset_ids = request.GET.get('asset_id') role = get_object(PermRole, id=role_id) assets = Asset.objects.all() asset_groups = AssetGroup.objects.all() if asset_ids: need_push_asset = [get_object(Asset, id=asset_id) for asset_id in asset_ids.split(',')] if request.method == "POST": # 获取推荐角色的名称列表 # 计算出需要推送的资产列表 asset_ids = request.POST.getlist("assets") asset_group_ids = request.POST.getlist("asset_groups") assets_obj = [Asset.objects.get(id=asset_id) for asset_id in asset_ids] asset_groups_obj = [AssetGroup.objects.get(id=asset_group_id) for asset_group_id in asset_group_ids] group_assets_obj = [] for asset_group in asset_groups_obj: group_assets_obj.extend(asset_group.asset_set.all()) calc_assets = list(set(assets_obj) | set(group_assets_obj)) push_resource = gen_resource(calc_assets) # 调用Ansible API 进行推送 password_push = True if request.POST.get("use_password") else False key_push = True if request.POST.get("use_publicKey") else False task = MyTask(push_resource) ret = {} # 因为要先建立用户,而push key是在 password也完成的情况下的 可选项 # 1. 以秘钥 方式推送角色 if key_push: ret["pass_push"] = task.add_user(role.name) ret["key_push"] = task.push_key(role.name, os.path.join(role.key_path, 'id_rsa.pub')) # 2. 推送账号密码 <为了安全 系统用户统一使用秘钥进行通信, 不再提供密码方式的推送> # elif password_push: # ret["pass_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password)) # 3. 推送sudo配置文件 if key_push: sudo_list = set([sudo for sudo in role.sudo.all()]) # set(sudo1, sudo2, sudo3) if sudo_list: ret['sudo'] = task.push_sudo_file([role], sudo_list) logger.debug('推送role结果: %s' % ret) success_asset = {} failed_asset = {} logger.debug(ret) for push_type, result in ret.items(): if result.get('failed'): for hostname, info in result.get('failed').items(): if hostname in failed_asset.keys(): if info in failed_asset.get(hostname): failed_asset[hostname] += info else: failed_asset[hostname] = info for push_type, result in ret.items(): if result.get('ok'): for hostname, info in result.get('ok').items(): if hostname in failed_asset.keys(): continue elif hostname in success_asset.keys(): if str(info) in success_asset.get(hostname, ''): success_asset[hostname] += str(info) else: success_asset[hostname] = str(info) # 推送成功 回写push表 for asset in calc_assets: push_check = PermPush.objects.filter(role=role, asset=asset) if push_check: func = push_check.update else: def func(**kwargs): PermPush(**kwargs).save() if failed_asset.get(asset.hostname): func(is_password=password_push, is_public_key=key_push, role=role, asset=asset, success=False, result=failed_asset.get(asset.hostname)) else: func(is_password=password_push, is_public_key=key_push, role=role, asset=asset, success=True) if not failed_asset: msg = u'系统用户 %s 推送成功[ %s ]' % (role.name, ','.join(success_asset.keys())) else: error = u'系统用户 %s 推送失败 [ %s ], 推送成功 [ %s ] 进入系统用户详情,查看失败原因' % (role.name, ','.join(failed_asset.keys()), ','.join(success_asset.keys())) return my_render('jperm/perm_role_push.html', locals(), request)