Example #1
0
def handle_user_info(user, x_real_ip):
    rds_cli = get_redis_connection()
    cache.delete(user.username)
    token_isvalid = user.access_token and len(
        user.access_token) == 32 and user.token_expired >= time.time()
    user.access_token = user.access_token if token_isvalid else uuid.uuid4(
    ).hex
    # 8小时过期
    user.token_expired = 8 * 60 * 60
    user.last_login = human_datetime()
    user.last_ip = x_real_ip
    user.save()
    rds_token = uuid.uuid4().hex
    rds_cli.set(REDIS_AUTH_KEY + rds_token, user.username, user.token_expired)
    return json_response({
        'access_token':
        rds_token,
        'nickname':
        user.nickname,
        'is_supper':
        user.is_supper,
        'has_real_ip':
        True if x_real_ip else False,
        'permissions': [] if user.is_supper else user.page_perms
    })
Example #2
0
 def _handle_event(self, event):
     close_old_connections()
     obj = SimpleLazyObject(lambda: Task.objects.filter(pk=event.job_id).first())
     if event.code == EVENT_SCHEDULER_SHUTDOWN:
         logging.warning(f'EVENT_SCHEDULER_SHUTDOWN: {event}')
         Notify.make_notify('schedule', '1', '调度器已关闭', '调度器意外关闭,你可以在github上提交issue')
     elif event.code == EVENT_JOB_MAX_INSTANCES:
         logging.warning(f'EVENT_JOB_MAX_INSTANCES: {event}')
         send_fail_notify(obj, '达到调度实例上限,一般为上个周期的执行任务还未结束,请增加调度间隔或减少任务执行耗时')
     elif event.code == EVENT_JOB_ERROR:
         logging.warning(f'EVENT_JOB_ERROR: job_id {event.job_id} exception: {event.exception}')
         send_fail_notify(obj, f'执行异常:{event.exception}')
     elif event.code == EVENT_JOB_EXECUTED:
         if event.retval:
             score = 0
             for item in event.retval:
                 score += 1 if item[1] else 0
             history = History.objects.create(
                 task_id=event.job_id,
                 status=2 if score == len(event.retval) else 1 if score else 0,
                 run_time=human_datetime(event.scheduled_run_time),
                 output=json.dumps(event.retval)
             )
             Task.objects.filter(pk=event.job_id).update(latest=history)
             if score != 0:
                 send_fail_notify(obj)
Example #3
0
 def _handle_event(self, event):
     close_old_connections()
     obj = SimpleLazyObject(lambda: Detection.objects.filter(pk=event.job_id).first())
     if event.code == EVENT_SCHEDULER_SHUTDOWN:
         logger.info(f'EVENT_SCHEDULER_SHUTDOWN: {event}')
         Notify.make_notify('monitor', '1', '调度器已关闭', '调度器意外关闭,你可以在github上提交issue', False)
     elif event.code == EVENT_JOB_MAX_INSTANCES:
         logger.info(f'EVENT_JOB_MAX_INSTANCES: {event}')
         Notify.make_notify('monitor', '1', f'{obj.name} - 达到调度实例上限', '一般为上个周期的执行任务还未结束,请增加调度间隔或减少任务执行耗时')
     elif event.code == EVENT_JOB_ERROR:
         logger.info(f'EVENT_JOB_ERROR: job_id {event.job_id} exception: {event.exception}')
         Notify.make_notify('monitor', '1', f'{obj.name} - 执行异常', f'{event.exception}')
     elif event.code == EVENT_JOB_EXECUTED:
         obj = Detection.objects.filter(pk=event.job_id).first()
         old_status = obj.latest_status
         obj.latest_status = 0 if event.retval else 1
         obj.latest_run_time = human_datetime(event.scheduled_run_time)
         if old_status in [0, None] and event.retval is False:
             obj.latest_fault_time = int(time.time())
         if obj.latest_status == 0:
             obj.latest_notify_time = 0
             obj.fault_times = 0
         else:
             obj.fault_times += 1
         obj.save()
         self._handle_notify(obj, old_status)
Example #4
0
 def _handle_event(self, event):
     close_old_connections()
     obj = SimpleLazyObject(
         lambda: Task.objects.filter(pk=event.job_id).first())
     if event.code == EVENT_SCHEDULER_SHUTDOWN:
         logger.info(f'EVENT_SCHEDULER_SHUTDOWN: {event}')
         Notify.make_notify('schedule', '1', '调度器已关闭',
                            '调度器意外关闭,你可以在github上提交issue')
     elif event.code == EVENT_JOB_MAX_INSTANCES:
         logger.info(f'EVENT_JOB_MAX_INSTANCES: {event}')
         Notify.make_notify('schedule', '1', f'{obj.name} - 达到调度实例上限',
                            '一般为上个周期的执行任务还未结束,请增加调度间隔或减少任务执行耗时')
     elif event.code == EVENT_JOB_ERROR:
         logger.info(
             f'EVENT_JOB_ERROR: job_id {event.job_id} exception: {event.exception}'
         )
         Notify.make_notify('schedule', '1', f'{obj.name} - 执行异常',
                            f'{event.exception}')
     elif event.code == EVENT_JOB_EXECUTED:
         if event.retval:
             score = 0
             for item in event.retval:
                 score += 1 if item[1] else 0
             history = History.objects.create(
                 task_id=event.job_id,
                 status=2
                 if score == len(event.retval) else 1 if score else 0,
                 run_time=human_datetime(event.scheduled_run_time),
                 output=json.dumps(event.retval))
             Task.objects.filter(pk=event.job_id).update(latest=history)
             if score != 0 and time.time() - counter.get(event.job_id,
                                                         0) > 3600:
                 counter[event.job_id] = time.time()
                 Notify.make_notify('schedule', '1', f'{obj.name} - 执行失败',
                                    '请在任务计划中查看失败详情')
Example #5
0
File: views.py Project: zzti/spug
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('type', help='请输入任务类型'),
         Argument('name', help='请输入任务名称'),
         Argument('command', help='请输入任务内容'),
         Argument('targets',
                  type=list,
                  filter=lambda x: len(x),
                  help='请选择执行对象'),
         Argument('trigger',
                  filter=lambda x: x in dict(Task.TRIGGERS),
                  help='请选择触发器类型'),
         Argument('trigger_args', help='请输入触发器参数'),
         Argument('desc', required=False),
     ).parse(request.body)
     if error is None:
         form.targets = json.dumps(form.targets)
         if form.id:
             Task.objects.filter(pk=form.id).update(
                 updated_at=human_datetime(),
                 updated_by=request.user,
                 **form)
             task = Task.objects.filter(pk=form.id).first()
             if task and task.is_active:
                 form.action = 'modify'
                 form.targets = json.loads(form.targets)
                 rds_cli = get_redis_connection()
                 rds_cli.lpush(settings.SCHEDULE_KEY, json.dumps(form))
         else:
             Task.objects.create(created_by=request.user, **form)
     return json_response(error=error)
Example #6
0
def handle_user_info(user, x_real_ip):
    cache.delete(user.username)
    token_isvalid = user.access_token and len(
        user.access_token) == 32 and user.token_expired >= time.time()
    user.access_token = user.access_token if token_isvalid else uuid.uuid4(
    ).hex
    user.token_expired = time.time() + 8 * 60 * 60
    user.last_login = human_datetime()
    user.last_ip = x_real_ip
    user.save()
    History.objects.create(user=user, ip=x_real_ip)
    verify_ip = AppSetting.get_default('verify_ip', 'True') == 'True'
    return json_response({
        'access_token':
        user.access_token,
        'nickname':
        user.nickname,
        'is_supper':
        user.is_supper,
        'has_real_ip':
        x_real_ip and ipaddress.ip_address(x_real_ip).is_global
        if verify_ip else True,
        'host_perms': [] if user.is_supper else user.host_perms,
        'permissions': [] if user.is_supper else user.page_perms
    })
Example #7
0
    def post(self, request, t_id):
        task = Task.objects.filter(pk=t_id).first()
        if not task:
            return json_response(error='未找到指定任务')
        outputs, status = {}, 1
        for host_id in json.loads(task.targets):
            if host_id == 'local':
                code, duration, out = local_executor(task.command)
            else:
                host = Host.objects.filter(pk=host_id).first()
                if not host:
                    code, duration, out = 1, 0, f'unknown host id for {host_id!r}'
                else:
                    code, duration, out = host_executor(host, task.command)
            if code != 0:
                status = 2
            outputs[host_id] = [code, duration, out]

        history = History.objects.create(
            task_id=task.id,
            status=status,
            run_time=human_datetime(),
            output=json.dumps(outputs)
        )
        return json_response(history.id)
Example #8
0
 def post(self, request, r_id):
     query = {'pk': r_id}
     if not request.user.is_supper:
         perms = request.user.deploy_perms
         query['deploy__app_id__in'] = perms['apps']
         query['deploy__env_id__in'] = perms['envs']
     req = DeployRequest.objects.filter(**query).first()
     if not req:
         return json_response(error='未找到指定发布申请')
     if req.status not in ('1', '-3'):
         return json_response(error='该申请单当前状态还不能执行发布')
     hosts = Host.objects.filter(id__in=json.loads(req.host_ids))
     token = uuid.uuid4().hex
     outputs = {str(x.id): {'data': []} for x in hosts}
     outputs.update(local={'data': [f'{human_time()} 建立接连...        ']})
     req.status = '2'
     req.do_at = human_datetime()
     req.do_by = request.user
     if not req.version:
         req.version = f'{req.deploy_id}_{req.id}_{datetime.now().strftime("%Y%m%d%H%M%S")}'
     req.save()
     Thread(target=deploy_dispatch, args=(request, req, token)).start()
     return json_response({
         'token': token,
         'type': req.type,
         'outputs': outputs
     })
Example #9
0
 def delete(self, request):
     form, error = JsonParser(Argument('id', type=int,
                                       help='请指定操作对象')).parse(request.GET)
     if error is None:
         User.objects.filter(pk=form.id).update(deleted_at=human_datetime(),
                                                deleted_by=request.user)
     return json_response(error=error)
Example #10
0
 def post(self, request, r_id):
     query = {'pk': r_id}
     if not request.user.is_supper:
         perms = request.user.deploy_perms
         query['deploy__app_id__in'] = perms['apps']
         query['deploy__env_id__in'] = perms['envs']
     req = DeployRequest.objects.filter(**query).first()
     if not req:
         return json_response(error='未找到指定发布申请')
     if req.status not in ('1', '-3'):
         return json_response(error='该申请单当前状态还不能执行发布')
     hosts = Host.objects.filter(id__in=json.loads(req.host_ids))
     message = f'{human_time()} 等待调度...        '
     outputs = {
         x.id: {
             'id': x.id,
             'title': x.name,
             'step': 0,
             'data': message
         }
         for x in hosts
     }
     req.status = '2'
     req.do_at = human_datetime()
     req.do_by = request.user
     req.save()
     Thread(target=dispatch, args=(req, )).start()
     if req.is_quick_deploy:
         if req.repository_id:
             outputs['local'] = {
                 'id': 'local',
                 'step': 100,
                 'data': f'{human_time()} 已构建完成忽略执行。'
             }
         else:
             outputs['local'] = {
                 'id': 'local',
                 'step': 0,
                 'data': f'{human_time()} 建立连接...        '
             }
     if req.deploy.extend == '2':
         outputs['local'] = {
             'id': 'local',
             'step': 0,
             'data': f'{human_time()} 建立连接...        '
         }
         s_actions = json.loads(req.deploy.extend_obj.server_actions)
         h_actions = json.loads(req.deploy.extend_obj.host_actions)
         for item in h_actions:
             if item.get('type') == 'transfer' and item.get(
                     'src_mode') == '0':
                 s_actions.append({'title': '执行打包'})
         if not h_actions:
             outputs = {'local': outputs['local']}
         return json_response({
             's_actions': s_actions,
             'h_actions': h_actions,
             'outputs': outputs
         })
     return json_response({'outputs': outputs})
Example #11
0
File: views.py Project: 9233/spug
 def delete(self, request):
     form, error = JsonParser(Argument('id', type=int,
                                       help='请指定操作对象')).parse(request.GET)
     if error is None:
         deploy = Deploy.objects.filter(
             host_ids__regex=fr'[^0-9]{form.id}[^0-9]').annotate(
                 app_name=F('app__name'), env_name=F('env__name')).first()
         if deploy:
             return json_response(
                 error=
                 f'应用【{deploy.app_name}】在【{deploy.env_name}】的发布配置关联了该主机,请解除关联后再尝试删除该主机'
             )
         task = Task.objects.filter(
             targets__regex=fr'[^0-9]{form.id}[^0-9]').first()
         if task:
             return json_response(
                 error=f'任务计划中的任务【{task.name}】关联了该主机,请解除关联后再尝试删除该主机')
         detection = Detection.objects.filter(type__in=('3', '4'),
                                              addr=form.id).first()
         if detection:
             return json_response(
                 error=f'监控中心的任务【{detection.name}】关联了该主机,请解除关联后再尝试删除该主机')
         role = Role.objects.filter(
             host_perms__regex=fr'[^0-9]{form.id}[^0-9]').first()
         if role:
             return json_response(
                 error=f'角色【{role.name}】的主机权限关联了该主机,请解除关联后再尝试删除该主机')
         Host.objects.filter(pk=form.id).update(
             deleted_at=human_datetime(),
             deleted_by=request.user,
         )
     return json_response(error=error)
Example #12
0
 def post(self, request):
     form, error = JsonParser(
         Argument('host_id', type=int, help='参数错误'),
         Argument('instance_id', required=False),
         Argument('os_name', help='请输入操作系统'),
         Argument('cpu', type=int, help='请输入CPU核心数'),
         Argument('memory', type=float, help='请输入内存大小'),
         Argument('disk', type=list, filter=lambda x: len(x), help='请添加磁盘'),
         Argument('private_ip_address',
                  type=list,
                  filter=lambda x: len(x),
                  help='请添加内网IP'),
         Argument('public_ip_address', type=list, required=False),
         Argument('instance_charge_type', default='Other'),
         Argument('internet_charge_type', default='Other'),
         Argument('created_time', required=False),
         Argument('expired_time', required=False)).parse(request.body)
     if error is None:
         host = Host.objects.filter(pk=form.host_id).first()
         form.disk = json.dumps(form.disk)
         form.public_ip_address = json.dumps(
             form.public_ip_address) if form.public_ip_address else '[]'
         form.private_ip_address = json.dumps(form.private_ip_address)
         form.updated_at = human_datetime()
         form.os_type = check_os_type(form.os_name)
         if hasattr(host, 'hostextend'):
             extend = host.hostextend
             extend.update_by_dict(form)
         else:
             extend = HostExtend.objects.create(host=host, **form)
         return json_response(extend.to_view())
     return json_response(error=error)
Example #13
0
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('name', help='请输入任务名称'),
         Argument('addr', help='请输入监控地址'),
         Argument('type', filter=lambda x: x in dict(Detection.TYPES), help='请选择监控类型'),
         Argument('extra', required=False),
         Argument('desc', required=False),
         Argument('rate', type=int, default=5),
         Argument('threshold', type=int, default=3),
         Argument('quiet', type=int, default=24 * 60),
         Argument('notify_grp', type=list, help='请选择报警联系组'),
         Argument('notify_mode', type=list, help='请选择报警方式'),
     ).parse(request.body)
     if error is None:
         form.notify_grp = json.dumps(form.notify_grp)
         form.notify_mode = json.dumps(form.notify_mode)
         if form.id:
             Detection.objects.filter(pk=form.id).update(
                 updated_at=human_datetime(),
                 updated_by=request.user,
                 **form)
             task = Detection.objects.filter(pk=form.id).first()
             if task and task.is_active:
                 form.action = 'modify'
                 rds_cli = get_redis_connection()
                 rds_cli.rpush(settings.MONITOR_KEY, json.dumps(form))
         else:
             dtt = Detection.objects.create(created_by=request.user, **form)
             form.action = 'add'
             form.id = dtt.id
             rds_cli = get_redis_connection()
             rds_cli.rpush(settings.MONITOR_KEY, json.dumps(form))
     return json_response(error=error)
Example #14
0
def login(request):
    form, error = JsonParser(Argument('username', help='请输入用户名'),
                             Argument('password', help='请输入密码'),
                             Argument('type')).parse(request.body)
    if error is None:
        user = User.objects.filter(username=form.username)
        if form.type == 'ldap':
            u = LDAP()
            valid = u.valid_user(form.username, form.password)
            if valid['status']:
                user = user.filter(type='LDAP').first()
                if user:
                    if not user.is_active:
                        return json_response(error="账户已被系统禁用")
                    if not user.role_id:
                        return json_response(error="LDAP用户角色未分配")

                    x_real_ip = request.headers.get('x-real-ip', '')
                    ret = handle_user_info(user, form.username, x_real_ip)
                    return json_response(ret)

                x_real_ip = request.headers.get('x-real-ip', '')
                form.access_token = uuid.uuid4().hex
                form.nickname = form.username
                form.token_expired = time.time() + 8 * 60 * 60
                form.last_login = human_datetime()
                form.last_ip = x_real_ip
                form.type = 'LDAP'
                form.pop('password')
                User.objects.create(**form)
                return json_response({
                    'access_token': form.access_token,
                    'nickname': form.username,
                    'is_supper': False,
                    'has_real_ip': True if x_real_ip else False,
                    'permissions': []
                })
            return json_response(error=valid['info'])
        else:
            user = user.filter(type='系统用户').first()
            if user and user.deleted_by is None:
                if not user.is_active:
                    return json_response(error="账户已被系统禁用")
                if user.verify_password(form.password):
                    cache.delete(form.username)
                    x_real_ip = request.headers.get('x-real-ip', '')
                    ret = handle_user_info(user, form.username, x_real_ip)
                    return json_response(ret)

            value = cache.get_or_set(form.username, 0, 86400)
            if value >= 3:
                if user and user.is_active:
                    user.is_active = False
                    user.save()
                return json_response(error='账户已被系统禁用')
            cache.set(form.username, value + 1, 86400)
            return json_response(error="用户名或密码错误,连续多次错误账户将会被禁用")
    return json_response(error=error)
Example #15
0
 def delete(self, request):
     form, error = JsonParser(
         Argument('host_list', type=list, help='请输入主机列表'),
     ).parse(request.GET)
     if error is None and len(form.host_list) > 0:
         for host in form.host_list:
             Host.objects.filter(pk=host.get('id')).update(
                 deleted_at=human_datetime(),
                 deleted_by=request.user,
             )
     return json_response(error=error)
Example #16
0
 def delete(self, request):
     form, error = JsonParser(Argument('id', type=int,
                                       help='请指定操作对象')).parse(request.GET)
     if error is None:
         user = User.objects.filter(pk=form.id).first()
         if user:
             user.role_id = None
             user.deleted_at = human_datetime()
             user.deleted_by = request.user
             user.save()
     return json_response(error=error)
Example #17
0
File: views.py Project: zzti/spug
 def delete(self, request):
     form, error = JsonParser(Argument('id', type=int,
                                       help='请指定操作对象')).parse(request.GET)
     if error is None:
         user = User.objects.filter(pk=form.id).first()
         if user:
             if user.type == 'ldap':
                 return json_response(error='ldap账户无法删除,请使用禁用功能来禁止该账户访问系统')
             user.deleted_at = human_datetime()
             user.deleted_by = request.user
             user.save()
     return json_response(error=error)
Example #18
0
 def _dispatch(self, task_id, command, targets):
     output = {x: None for x in targets}
     history = History.objects.create(
         task_id=task_id,
         status='0',
         run_time=human_datetime(),
         output=json.dumps(output)
     )
     Task.objects.filter(pk=task_id).update(latest_id=history.id)
     rds_cli = get_redis_connection()
     for t in targets:
         rds_cli.rpush(SCHEDULE_WORKER_KEY, json.dumps([history.id, t, command]))
     connections.close_all()
Example #19
0
 def post(self, request, t_id):
     task = Task.objects.filter(pk=t_id).first()
     if not task:
         return json_response(error='未找到指定任务')
     data = dispatch(task.command, json.loads(task.targets), True)
     score = 0
     for item in data:
         score += 1 if item[1] else 0
     history = History.objects.create(
         task_id=t_id,
         status=2 if score == len(data) else 1 if score else 0,
         run_time=human_datetime(),
         output=json.dumps(data))
     return json_response(history.id)
Example #20
0
def add_monitor(user, form):
    form.notify_grp = json.dumps(form.notify_grp)
    form.notify_mode = json.dumps(form.notify_mode)
    if form.id:
        Detection.objects.filter(pk=form.id).update(
            updated_at=human_datetime(), updated_by=user, **form)
        task = Detection.objects.filter(pk=form.id).first()
        if task and task.is_active:
            form.action = 'modify'
            rds_cli = get_redis_connection()
            rds_cli.lpush(settings.MONITOR_KEY, json.dumps(form))
        return
    elif form.deploy_id:
        task = Detection.objects.filter(deploy_id=form.deploy_id).first()
        if task:
            form['id'] = task.id
            Detection.objects.filter(pk=task.id).update(
                updated_at=human_datetime(), updated_by=user, **form)
            task = Detection.objects.filter(deploy_id=form.deploy_id).first()
            if task and task.is_active:
                form.action = 'modify'
                form.rate = task.rate
                rds_cli = get_redis_connection()
                rds_cli.lpush(settings.MONITOR_KEY, json.dumps(form))
            return
    # 其它为新增
    # 填充默认值
    form['rate'] = form.get('rate') if form.get('rate') else 5
    form['threshold'] = form.get('threshold') if form.get('threshold') else 20
    form['quiet'] = form.get('quiet') if form.get('quiet') else 24 * 60

    dtt = Detection.objects.create(created_by=user, **form)
    form.action = 'add'
    form.id = dtt.id
    rds_cli = get_redis_connection()
    rds_cli.lpush(settings.MONITOR_KEY, json.dumps(form))
Example #21
0
File: views.py Project: zerlee/spug
 def post(self, request):
     form, error = JsonParser(
         Argument('id', type=int, required=False),
         Argument('type', help='请输入任务类型'),
         Argument('name', help='请输入任务名称'),
         Argument('command', help='请输入任务内容'),
         Argument('rst_notify', type=dict, help='请选择执行失败通知方式'),
         Argument('targets',
                  type=list,
                  filter=lambda x: len(x),
                  help='请选择执行对象'),
         Argument('trigger',
                  filter=lambda x: x in dict(Task.TRIGGERS),
                  help='请选择触发器类型'),
         Argument('trigger_args', help='请输入触发器参数'),
         Argument('desc', required=False),
     ).parse(request.body)
     if error is None:
         form.targets = json.dumps(form.targets)
         form.rst_notify = json.dumps(form.rst_notify)
         if form.trigger == 'cron':
             args = json.loads(form.trigger_args)['rule'].split()
             if len(args) != 5:
                 return json_response(error='无效的执行规则,请更正后再试')
             minute, hour, day, month, week = args
             week = '0' if week == '7' else week
             try:
                 CronTrigger(minute=minute,
                             hour=hour,
                             day=day,
                             month=month,
                             day_of_week=week)
             except ValueError:
                 return json_response(error='无效的执行规则,请更正后再试')
         if form.id:
             Task.objects.filter(pk=form.id).update(
                 updated_at=human_datetime(),
                 updated_by=request.user,
                 **form)
             task = Task.objects.filter(pk=form.id).first()
             if task and task.is_active:
                 form.action = 'modify'
                 form.targets = json.loads(form.targets)
                 rds_cli = get_redis_connection()
                 rds_cli.lpush(settings.SCHEDULE_KEY, json.dumps(form))
         else:
             Task.objects.create(created_by=request.user, **form)
     return json_response(error=error)
Example #22
0
def do_task(request):
    form, error = JsonParser(
        Argument('host_ids', type=list, filter=lambda x: len(x), help='请选择执行主机'),
        Argument('command', help='请输入执行命令内容'),
        Argument('interpreter', default='sh'),
        Argument('template_id', type=int, required=False)
    ).parse(request.body)
    if error is None:
        if not has_host_perm(request.user, form.host_ids):
            return json_response(error='无权访问主机,请联系管理员')
        token, rds = uuid.uuid4().hex, get_redis_connection()
        for host in Host.objects.filter(id__in=form.host_ids):
            data = dict(
                key=host.id,
                name=host.name,
                token=token,
                interpreter=form.interpreter,
                hostname=host.hostname,
                port=host.port,
                username=host.username,
                command=form.command,
                pkey=host.private_key,
            )
            rds.rpush(settings.EXEC_WORKER_KEY, json.dumps(data))
        form.host_ids.sort()
        host_ids = json.dumps(form.host_ids)
        tmp_str = f'{form.interpreter},{host_ids},{form.command}'
        digest = hashlib.md5(tmp_str.encode()).hexdigest()
        record = ExecHistory.objects.filter(user=request.user, digest=digest).first()
        if form.template_id:
            template = ExecTemplate.objects.filter(pk=form.template_id).first()
            if not template or template.body != form.command:
                form.template_id = None
        if record:
            record.template_id = form.template_id
            record.updated_at = human_datetime()
            record.save()
        else:
            ExecHistory.objects.create(
                user=request.user,
                digest=digest,
                interpreter=form.interpreter,
                template_id=form.template_id,
                command=form.command,
                host_ids=json.dumps(form.host_ids),
            )
        return json_response(token)
    return json_response(error=error)
Example #23
0
 def post(self, request):
     form, error = JsonParser(Argument('id', type=int, required=False),
                              Argument('name', help='请输入模版名称'),
                              Argument('type', help='请选择模版类型'),
                              Argument('body', help='请输入模版内容'),
                              Argument('desc',
                                       required=False)).parse(request.body)
     if error is None:
         if form.id:
             form.updated_at = human_datetime()
             form.updated_by = request.user
             ExecTemplate.objects.filter(pk=form.pop('id')).update(**form)
         else:
             form.created_by = request.user
             ExecTemplate.objects.create(**form)
     return json_response(error=error)
Example #24
0
def handle_user_info(user, x_real_ip):
    cache.delete(user.username)
    token_isvalid = user.access_token and len(user.access_token) == 32 and user.token_expired >= time.time()
    user.access_token = user.access_token if token_isvalid else uuid.uuid4().hex
    user.token_expired = time.time() + 8 * 60 * 60
    user.last_login = human_datetime()
    user.last_ip = x_real_ip
    user.save()
    return json_response({
        'access_token': user.access_token,
        'nickname': user.nickname,
        'is_supper': user.is_supper,
        'has_real_ip': x_real_ip and ipaddress.ip_address(x_real_ip).is_global,
        'host_perms': [] if user.is_supper else user.host_perms,
        'permissions': [] if user.is_supper else user.page_perms
    })
Example #25
0
def handle_user_info(request, user, captcha):
    cache.delete(user.username)
    key = f'{user.username}:code'
    if captcha:
        code = cache.get(key)
        if not code:
            return json_response(error='验证码已失效,请重新获取')
        if code != captcha:
            ttl = cache.ttl(key)
            cache.expire(key, ttl - 100)
            return json_response(error='验证码错误')
        cache.delete(key)
    else:
        mfa = AppSetting.get_default('MFA', {'enable': False})
        if mfa['enable']:
            if not user.wx_token:
                return json_response(error='已启用登录双重认证,但您的账户未配置微信Token,请联系管理员')
            code = generate_random_str(6)
            send_login_wx_code(user.wx_token, code)
            cache.set(key, code, 300)
            return json_response({'required_mfa': True})

    x_real_ip = get_request_real_ip(request.headers)
    token_isvalid = user.access_token and len(
        user.access_token) == 32 and user.token_expired >= time.time()
    user.access_token = user.access_token if token_isvalid else uuid.uuid4(
    ).hex
    user.token_expired = time.time() + 8 * 60 * 60
    user.last_login = human_datetime()
    user.last_ip = x_real_ip
    user.save()
    History.objects.create(user=user, ip=x_real_ip)
    verify_ip = AppSetting.get_default('verify_ip', True)
    return json_response({
        'id':
        user.id,
        'access_token':
        user.access_token,
        'nickname':
        user.nickname,
        'is_supper':
        user.is_supper,
        'has_real_ip':
        x_real_ip and ipaddress.ip_address(x_real_ip).is_global
        if verify_ip else True,
        'permissions': [] if user.is_supper else list(user.page_perms)
    })
Example #26
0
def handle_user_info(user, username, x_real_ip):
    cache.delete(username)
    token_isvalid = user.access_token and len(
        user.access_token) == 32 and user.token_expired >= time.time()
    user.access_token = user.access_token if token_isvalid else uuid.uuid4(
    ).hex
    user.token_expired = time.time() + 8 * 60 * 60
    user.last_login = human_datetime()
    user.last_ip = x_real_ip
    user.save()
    return {
        'access_token': user.access_token,
        'nickname': user.nickname,
        'is_supper': user.is_supper,
        'has_real_ip': True if x_real_ip else False,
        'permissions': [] if user.is_supper else user.page_perms
    }
Example #27
0
    def post(self, request):
        form, error = JsonParser(
            Argument('id', type=int, required=False),
            Argument('name', help='请输入任务名称'),
            Argument('group', help='请选择任务分组'),
            Argument('targets',
                     type=list,
                     filter=lambda x: len(x),
                     help='请输入监控地址'),
            Argument('type',
                     filter=lambda x: x in dict(Detection.TYPES),
                     help='请选择监控类型'),
            Argument('extra', required=False),
            Argument('desc', required=False),
            Argument('rate', type=int, default=5),
            Argument('threshold', type=int, default=3),
            Argument('quiet', type=int, default=24 * 60),
            Argument('notify_grp', type=list, help='请选择报警联系组'),
            Argument('notify_mode', type=list, help='请选择报警方式'),
        ).parse(request.body)
        if error is None:
            if set(form.notify_mode).intersection(['1', '2', '4']):
                if not AppSetting.get_default('spug_key'):
                    return json_response(
                        error='报警方式 微信、短信、邮件需要配置调用凭据(系统设置/基本设置),请配置后再启用该报警方式。')

            form.targets = json.dumps(form.targets)
            form.notify_grp = json.dumps(form.notify_grp)
            form.notify_mode = json.dumps(form.notify_mode)
            if form.id:
                Detection.objects.filter(pk=form.id).update(
                    updated_at=human_datetime(),
                    updated_by=request.user,
                    **form)
                task = Detection.objects.filter(pk=form.id).first()
                if task and task.is_active:
                    form.action = 'modify'
                    rds_cli = get_redis_connection()
                    rds_cli.lpush(settings.MONITOR_KEY, json.dumps(form))
            else:
                dtt = Detection.objects.create(created_by=request.user, **form)
                form.action = 'add'
                form.id = dtt.id
                rds_cli = get_redis_connection()
                rds_cli.lpush(settings.MONITOR_KEY, json.dumps(form))
        return json_response(error=error)
Example #28
0
 def patch(self, request, r_id):
     form, error = JsonParser(Argument('reason', required=False),
                              Argument('is_pass', type=bool,
                                       help='参数错误')).parse(request.body)
     if error is None:
         req = DeployRequest.objects.filter(pk=r_id).first()
         if not req:
             return json_response(error='未找到指定申请')
         if not form.is_pass and not form.reason:
             return json_response(error='请输入驳回原因')
         if req.status != '0':
             return json_response(error='该申请当前状态不允许审核')
         req.approve_at = human_datetime()
         req.approve_by = request.user
         req.status = '1' if form.is_pass else '-1'
         req.reason = form.reason
         req.save()
     return json_response(error=error)
Example #29
0
def login(request):
    form, error = JsonParser(Argument('username', help='请输入用户名'),
                             Argument('password',
                                      help='请输入密码')).parse(request.body)
    if error is None:
        user = User.objects.filter(username=form.username).first()
        if user:
            if not user.is_active:
                return json_response(error="账户已被禁用")
            if user.verify_password(form.password):
                cache.delete(form.username)
                x_real_ip = request.headers.get('x-real-ip', '')
                token_isvalid = user.access_token and len(
                    user.access_token
                ) == 32 and user.token_expired >= time.time()
                user.access_token = user.access_token if token_isvalid else uuid.uuid4(
                ).hex
                user.token_expired = time.time() + 8 * 60 * 60
                user.last_login = human_datetime()
                user.last_ip = x_real_ip
                user.save()
                return json_response({
                    'access_token':
                    user.access_token,
                    'nickname':
                    user.nickname,
                    'is_supper':
                    user.is_supper,
                    'has_real_ip':
                    True if x_real_ip else False,
                    'permissions': [] if user.is_supper else user.page_perms
                })

        value = cache.get_or_set(form.username, 0, 86400)
        if value >= 3:
            if user and user.is_active:
                user.is_active = False
                user.save()
            return json_response(error='账户已被禁用')
        cache.set(form.username, value + 1, 86400)
        return json_response(error="用户名或密码错误,连续多次错误账户将会被禁用")
    return json_response(error=error)
Example #30
0
 def _dispatch(self, task_id, tp, targets, extra, threshold, quiet):
     Detection.objects.filter(pk=task_id).update(latest_run_time=human_datetime())
     rds_cli = get_redis_connection()
     for t in json.loads(targets):
         rds_cli.rpush(MONITOR_WORKER_KEY, json.dumps([task_id, tp, t, extra, threshold, quiet]))
     connections.close_all()