mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-12-26 05:52:36 +00:00
Compare commits
2 Commits
pr@dev@fea
...
pr@dev@per
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32481278ca | ||
|
|
95aa50ed4f |
@@ -1,34 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from rest_framework.throttling import SimpleRateThrottle
|
|
||||||
|
|
||||||
|
|
||||||
class RateThrottle(SimpleRateThrottle):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# Override the usual SimpleRateThrottle, because we can't determine
|
|
||||||
# the rate until called by the view.
|
|
||||||
pass
|
|
||||||
|
|
||||||
def allow_request(self, request, view):
|
|
||||||
if getattr(request, "user", None) and request.user.is_authenticated:
|
|
||||||
if getattr(request.user, "is_service_account", False):
|
|
||||||
self.scope = "service_account"
|
|
||||||
else:
|
|
||||||
self.scope = "user"
|
|
||||||
else:
|
|
||||||
self.scope = "anon"
|
|
||||||
|
|
||||||
self.rate = self.get_rate()
|
|
||||||
self.num_requests, self.duration = self.parse_rate(self.rate)
|
|
||||||
return super().allow_request(request, view)
|
|
||||||
|
|
||||||
def get_cache_key(self, request, view):
|
|
||||||
if request.user and request.user.is_authenticated:
|
|
||||||
ident = request.user.pk
|
|
||||||
else:
|
|
||||||
ident = self.get_ident(request)
|
|
||||||
|
|
||||||
return self.cache_format % {
|
|
||||||
'scope': self.scope,
|
|
||||||
'ident': ident
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
from django.core.cache import cache
|
||||||
from django.db.models import Count, Max, F, CharField, Q
|
from django.db.models import Count, Max, F, CharField, Q
|
||||||
from django.db.models.functions import Cast
|
from django.db.models.functions import Cast
|
||||||
from django.http.response import JsonResponse
|
from django.http.response import JsonResponse
|
||||||
@@ -144,6 +145,7 @@ class DateTimeMixin:
|
|||||||
|
|
||||||
|
|
||||||
class DatesLoginMetricMixin:
|
class DatesLoginMetricMixin:
|
||||||
|
days: int
|
||||||
dates_list: list
|
dates_list: list
|
||||||
date_start_end: tuple
|
date_start_end: tuple
|
||||||
command_type_queryset_list: list
|
command_type_queryset_list: list
|
||||||
@@ -155,6 +157,8 @@ class DatesLoginMetricMixin:
|
|||||||
operate_logs_queryset: OperateLog.objects
|
operate_logs_queryset: OperateLog.objects
|
||||||
password_change_logs_queryset: PasswordChangeLog.objects
|
password_change_logs_queryset: PasswordChangeLog.objects
|
||||||
|
|
||||||
|
CACHE_TIMEOUT = 60
|
||||||
|
|
||||||
@lazyproperty
|
@lazyproperty
|
||||||
def get_type_to_assets(self):
|
def get_type_to_assets(self):
|
||||||
result = Asset.objects.annotate(type=F('platform__type')). \
|
result = Asset.objects.annotate(type=F('platform__type')). \
|
||||||
@@ -214,19 +218,34 @@ class DatesLoginMetricMixin:
|
|||||||
return date_metrics_dict.get('id', [])
|
return date_metrics_dict.get('id', [])
|
||||||
|
|
||||||
def get_dates_login_times_assets(self):
|
def get_dates_login_times_assets(self):
|
||||||
|
cache_key = f"stats:top10_assets:{self.days}"
|
||||||
|
data = cache.get(cache_key)
|
||||||
|
if data is not None:
|
||||||
|
return data
|
||||||
|
|
||||||
assets = self.sessions_queryset.values("asset") \
|
assets = self.sessions_queryset.values("asset") \
|
||||||
.annotate(total=Count("asset")) \
|
.annotate(total=Count("asset")) \
|
||||||
.annotate(last=Cast(Max("date_start"), output_field=CharField())) \
|
.annotate(last=Cast(Max("date_start"), output_field=CharField())) \
|
||||||
.order_by("-total")
|
.order_by("-total")
|
||||||
return list(assets[:10])
|
|
||||||
|
result = list(assets[:10])
|
||||||
|
cache.set(cache_key, result, self.CACHE_TIMEOUT)
|
||||||
|
return result
|
||||||
|
|
||||||
def get_dates_login_times_users(self):
|
def get_dates_login_times_users(self):
|
||||||
|
cache_key = f"stats:top10_users:{self.days}"
|
||||||
|
data = cache.get(cache_key)
|
||||||
|
if data is not None:
|
||||||
|
return data
|
||||||
|
|
||||||
users = self.sessions_queryset.values("user_id") \
|
users = self.sessions_queryset.values("user_id") \
|
||||||
.annotate(total=Count("user_id")) \
|
.annotate(total=Count("user_id")) \
|
||||||
.annotate(user=Max('user')) \
|
.annotate(user=Max('user')) \
|
||||||
.annotate(last=Cast(Max("date_start"), output_field=CharField())) \
|
.annotate(last=Cast(Max("date_start"), output_field=CharField())) \
|
||||||
.order_by("-total")
|
.order_by("-total")
|
||||||
return list(users[:10])
|
result = list(users[:10])
|
||||||
|
cache.set(cache_key, result, self.CACHE_TIMEOUT)
|
||||||
|
return result
|
||||||
|
|
||||||
def get_dates_login_record_sessions(self):
|
def get_dates_login_record_sessions(self):
|
||||||
sessions = self.sessions_queryset.order_by('-date_start')
|
sessions = self.sessions_queryset.order_by('-date_start')
|
||||||
|
|||||||
@@ -38,14 +38,6 @@ REST_FRAMEWORK = {
|
|||||||
"oauth2_provider.contrib.rest_framework.OAuth2Authentication",
|
"oauth2_provider.contrib.rest_framework.OAuth2Authentication",
|
||||||
'authentication.backends.drf.SessionAuthentication',
|
'authentication.backends.drf.SessionAuthentication',
|
||||||
),
|
),
|
||||||
'DEFAULT_THROTTLE_CLASSES': (
|
|
||||||
'common.drf.throttling.RateThrottle',
|
|
||||||
),
|
|
||||||
'DEFAULT_THROTTLE_RATES': {
|
|
||||||
'anon': '60/min',
|
|
||||||
'user': '180/min',
|
|
||||||
'service_account': '300/min',
|
|
||||||
},
|
|
||||||
'DEFAULT_FILTER_BACKENDS': (
|
'DEFAULT_FILTER_BACKENDS': (
|
||||||
'django_filters.rest_framework.DjangoFilterBackend',
|
'django_filters.rest_framework.DjangoFilterBackend',
|
||||||
'common.drf.filters.SearchFilter',
|
'common.drf.filters.SearchFilter',
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ class BlockUtilBase:
|
|||||||
username = username.lower() if username else ''
|
username = username.lower() if username else ''
|
||||||
self.username = username
|
self.username = username
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.limit_key = self.LIMIT_KEY_TMPL.format(username, ip)
|
self.limit_key = self.LIMIT_KEY_TMPL.format(username)
|
||||||
self.block_key = self.BLOCK_KEY_TMPL.format(username)
|
self.block_key = self.BLOCK_KEY_TMPL.format(username)
|
||||||
self.key_ttl = int(settings.SECURITY_LOGIN_LIMIT_TIME) * 60
|
self.key_ttl = int(settings.SECURITY_LOGIN_LIMIT_TIME) * 60
|
||||||
|
|
||||||
@@ -236,12 +236,12 @@ class BlockGlobalIpUtilBase:
|
|||||||
|
|
||||||
|
|
||||||
class LoginBlockUtil(BlockUtilBase):
|
class LoginBlockUtil(BlockUtilBase):
|
||||||
LIMIT_KEY_TMPL = "_LOGIN_LIMIT_{}_{}"
|
LIMIT_KEY_TMPL = "_LOGIN_LIMIT_{}"
|
||||||
BLOCK_KEY_TMPL = "_LOGIN_BLOCK_{}"
|
BLOCK_KEY_TMPL = "_LOGIN_BLOCK_{}"
|
||||||
|
|
||||||
|
|
||||||
class MFABlockUtils(BlockUtilBase):
|
class MFABlockUtils(BlockUtilBase):
|
||||||
LIMIT_KEY_TMPL = "_MFA_LIMIT_{}_{}"
|
LIMIT_KEY_TMPL = "_MFA_LIMIT_{}"
|
||||||
BLOCK_KEY_TMPL = "_MFA_BLOCK_{}"
|
BLOCK_KEY_TMPL = "_MFA_BLOCK_{}"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user