Пример #1
0
 def monitor_by_email(self, users):
     mail_service = AppSetting.get_default('mail_service', {})
     body = [
         f'告警名称:{self.title}',
         f'告警对象:{self.target}',
         f'{"告警" if self.event == "1" else "恢复"}时间:{human_datetime()}',
         f'告警描述:{self.message}'
     ]
     if self.event == '2':
         body.append('故障持续:' + self.duration)
     if mail_service.get('server'):
         event_map = {'1': '监控告警通知', '2': '告警恢复通知'}
         subject = f'{event_map[self.event]}-{self.title}'
         mail = Mail(**mail_service)
         mail.send_text_mail(users, subject, '\r\n'.join(body) + '\r\n\r\n自动发送,请勿回复。')
     elif self.spug_key:
         data = {
             'token': self.spug_key,
             'event': self.event,
             'subject': self.title,
             'body': '\r\n'.join(body),
             'users': list(users)
         }
         self.handle_request(f'{spug_server}/apis/notify/mail/', data, 'spug')
     else:
         Notify.make_monitor_notify('发送报警信息失败', '未配置报警服务调用凭据,请在系统管理/系统设置/报警服务设置中配置。')
Пример #2
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
    })
Пример #3
0
def notify_by_email(event, subject, grp):
    spug_key, u_ids = _parse_args(grp)
    users = set(
        x.email
        for x in Contact.objects.filter(id__in=u_ids, email__isnull=False))
    if users:
        mail_service = json.loads(AppSetting.get_default('mail_service', '{}'))
        if mail_service.get('server'):
            event_map = {'1': '告警', '2': '恢复'}
            subject = f'{event_map[event]}-{subject}'
            mail = Mail(**mail_service)
            mail.send_text_mail(users, subject, f'{subject}\r\n\r\n自动发送,请勿回复。')
        elif spug_key:
            data = {
                'token': spug_key,
                'event': event,
                'subject': subject,
                'users': list(users)
            }
            requests.post(f'{spug_server}/apis/notify/mail/', json=data)
        else:
            Notify.make_notify(notify_source, '1', '发送报警信息失败',
                               '未配置报警服务调用凭据,请在系统管理/系统设置/报警服务设置中配置。')
    else:
        Notify.make_notify(notify_source, '1', '发送报警信息失败',
                           '未找到可用的通知对象,请确保设置了相关报警联系人的邮件地址。')
Пример #4
0
def notify_by_email(event, obj):
    spug_key, u_ids = _parse_args(obj.grp)
    users = set(
        x.email
        for x in Contact.objects.filter(id__in=u_ids, email__isnull=False))
    if users:
        mail_service = json.loads(AppSetting.get_default('mail_service', '{}'))
        body = [
            '告警名称:' + obj.name, '告警时间:' + human_datetime(), '告警描述:' + obj.out
        ]
        if event == '2':
            body.append('故障持续:' + obj.duration)
        if mail_service.get('server'):
            event_map = {'1': '告警发生', '2': '告警恢复'}
            subject = f'{event_map[event]}-{obj.name}'
            mail = Mail(**mail_service)
            mail.send_text_mail(users, subject,
                                '\r\n'.join(body) + '\r\n\r\n自动发送,请勿回复。')
        elif spug_key:
            data = {
                'token': spug_key,
                'event': event,
                'subject': obj.name,
                'body': '\r\n'.join(body),
                'users': list(users)
            }
            requests.post(f'{spug_server}/apis/notify/mail/', json=data)
        else:
            Notify.make_notify(notify_source, '1', '发送报警信息失败',
                               '未配置报警服务调用凭据,请在系统管理/系统设置/报警服务设置中配置。')
    else:
        Notify.make_notify(notify_source, '1', '发送报警信息失败',
                           '未找到可用的通知对象,请确保设置了相关报警联系人的邮件地址。')
Пример #5
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)
    })
Пример #6
0
def _parse_args(grp):
    spug_key = AppSetting.get_default('spug_key')
    if not spug_key:
        Notify.make_notify(notify_source, '1', '发送报警信息失败',
                           '未配置报警服务调用凭据,请在系统管理/系统设置/报警服务设置中配置。')
        return None, None
    return spug_key, sum(
        [json.loads(x.contacts) for x in Group.objects.filter(id__in=grp)], [])
Пример #7
0
def send_login_wx_code(wx_token, code):
    url = f'{spug_server}/apis/login/wx/'
    spug_key = AppSetting.get_default('spug_key')
    res = requests.post(url, json={'token': spug_key, 'user': wx_token, 'code': code}, timeout=30)
    if res.status_code != 200:
        raise Exception(f'status code: {res.status_code}')
    res = res.json()
    if res.get('error'):
        raise Exception(res['error'])
Пример #8
0
 def __init__(self, grp, event, target, title, message, duration):
     self.grp = grp
     self.event = event
     self.title = title
     self.target = target
     self.message = message
     self.duration = duration
     self.spug_key = AppSetting.get_default('spug_key')
     self.u_ids = []
Пример #9
0
 def verify_user(self, scope, headers):
     close_old_connections()
     query_string = scope['query_string'].decode()
     x_real_ip = self.get_real_ip(headers)
     token = parse_qs(query_string).get('x-token', [''])[0]
     if token and len(token) == 32:
         user = User.objects.filter(access_token=token).first()
         if user and user.token_expired >= time.time() and user.is_active:
             if x_real_ip == user.last_ip or AppSetting.get_default(
                     'bind_ip') is False:
                 scope['user'] = user
                 return True, None
             return False, f'Verify failed: {x_real_ip} <> {user.last_ip if user else None}'
     return False, 'Token is invalid'
Пример #10
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)
Пример #11
0
def _parse_params(request):
    app, env_id = None, None
    api_token = request.GET.get('apiToken')
    if api_token:
        rds = get_redis_connection()
        content = rds.get(api_token)
        if content:
            app_id, env_id = content.decode().split(',')
            app = App.objects.filter(pk=app_id).first()
    else:
        api_key = AppSetting.get_default('api_key')
        if api_key and request.GET.get('apiKey') == api_key:
            app_key = request.GET.get('app')
            env_key = request.GET.get('env')
            if app_key and env_key:
                app = App.objects.filter(key=app_key).first()
                env = Environment.objects.filter(key=env_key).first()
                if env:
                    env_id = env.id
    return app, env_id, request.GET.get('noPrefix')
Пример #12
0
def _is_valid_token(request):
    api_key = AppSetting.get_default('api_key')

    # Gitlab Gitee Aliyun(Codeup)
    token = request.headers.get('X-Gitlab-Token')
    token = token or request.headers.get('X-Gitee-Token')
    token = token or request.headers.get('X-Codeup-Token')
    # Compatible the old version of gitlab
    token = token or request.GET.get('token')
    if token:
        return token == api_key

    # Gogs Github
    token = request.headers.get('X-Gogs-Signature')
    token = token or request.headers.get('X-Hub-Signature-256', '').replace(
        'sha256=', '')
    if token:
        return token == hmac.new(api_key.encode(), request.body,
                                 hashlib.sha256).hexdigest()
    return False
Пример #13
0
def notify_by_email(event, subject, grp):
    spug_key, u_ids = _parse_args(grp)
    if u_ids is None:
        return
    users = set(
        x.email
        for x in Contact.objects.filter(id__in=u_ids, email__isnull=False))
    if users:
        mail_service = json.loads(AppSetting.get_default('mail_service', '{}'))
        if mail_service.get('server'):
            event_map = {'1': '告警', '2': '恢复'}
            subject = f'{event_map[event]}-{subject}'
            mail = Mail(**mail_service)
            mail.send_text_mail(users, subject, f'{subject}\r\n\r\n自动发送,请勿回复。')
        else:
            data = {
                'token': spug_key,
                'event': event,
                'subject': subject,
                'users': list(users)
            }
            requests.post(f'{spug_server}/apis/notify/mail/', json=data)
Пример #14
0
def login(request):
    form, error = JsonParser(Argument('username', help='请输入用户名'),
                             Argument('password', help='请输入密码'),
                             Argument('captcha', required=False),
                             Argument('type',
                                      required=False)).parse(request.body)
    if error is None:
        user = User.objects.filter(username=form.username,
                                   type=form.type).first()
        if user and not user.is_active:
            return json_response(error="账户已被系统禁用")
        if form.type == 'ldap':
            config = AppSetting.get_default('ldap_service')
            if not config:
                return json_response(error='请在系统设置中配置LDAP后再尝试通过该方式登录')
            ldap = LDAP(**config)
            is_success, message = ldap.valid_user(form.username, form.password)
            if is_success:
                if not user:
                    user = User.objects.create(username=form.username,
                                               nickname=form.username,
                                               type=form.type)
                return handle_user_info(request, user, form.captcha)
            elif message:
                return json_response(error=message)
        else:
            if user and user.deleted_by is None:
                if user.verify_password(form.password):
                    return handle_user_info(request, user, form.captcha)

        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)
Пример #15
0
 def process_request(self, request):
     if request.path in settings.AUTHENTICATION_EXCLUDES:
         return None
     if any(
             x.match(request.path) for x in settings.AUTHENTICATION_EXCLUDES
             if hasattr(x, 'match')):
         return None
     access_token = request.headers.get('x-token') or request.GET.get(
         'x-token')
     if access_token and len(access_token) == 32:
         x_real_ip = get_request_real_ip(request.headers)
         user = User.objects.filter(access_token=access_token).first()
         if user and user.token_expired >= time.time() and user.is_active:
             if x_real_ip == user.last_ip or AppSetting.get_default(
                     'bind_ip') is False:
                 request.user = user
                 user.token_expired = time.time() + 8 * 60 * 60
                 user.save()
                 return None
     response = json_response(error="验证失败,请重新登录")
     response.status_code = 401
     return response
Пример #16
0
def _parse_args(grp):
    spug_key = AppSetting.get_default('spug_key')
    return spug_key, sum(
        [json.loads(x.contacts) for x in Group.objects.filter(id__in=grp)], [])
Пример #17
0
def fetch_repo(deploy_id, git_repo):
    repo_dir = os.path.join(settings.REPOS_DIR, str(deploy_id))
    pkey = AppSetting.get_default('private_key')
    with Git(git_repo, repo_dir, pkey) as git:
        return git.fetch_branches_tags()
Пример #18
0
def fetch_versions(deploy: Deploy):
    git_repo = deploy.extend_obj.git_repo
    repo_dir = os.path.join(settings.REPOS_DIR, str(deploy.id))
    pkey = AppSetting.get_default('private_key')
    with Git(git_repo, repo_dir, pkey) as git:
        return git.fetch_branches_tags()
Пример #19
0
def kit_key(request):
    api_key = AppSetting.get_default('api_key')
    return json_response(api_key)