mirror of https://github.com/jumpserver/jumpserver
Merge branch 'v3' of github.com:jumpserver/jumpserver into v3
commit
3b1c8a2327
|
@ -154,6 +154,7 @@ class RDPFileClientProtocolURLMixin:
|
|||
data = {
|
||||
'id': str(token.id),
|
||||
'value': token.value,
|
||||
'protocol': token.protocol,
|
||||
'command': '',
|
||||
'file': {}
|
||||
}
|
||||
|
|
|
@ -13,48 +13,121 @@ from rest_framework.response import Response
|
|||
from users.models import User
|
||||
from assets.models import Asset
|
||||
from assets.const import AllTypes
|
||||
from terminal.models import Session
|
||||
from terminal.models import Session, Command
|
||||
from terminal.utils import ComponentsPrometheusMetricsUtil
|
||||
from orgs.utils import current_org
|
||||
from common.utils import lazyproperty
|
||||
from audits.models import UserLoginLog, PasswordChangeLog, OperateLog
|
||||
from audits.const import LoginStatusChoices
|
||||
from common.utils.timezone import local_now, local_zero_hour
|
||||
from orgs.caches import OrgResourceStatisticsCache
|
||||
|
||||
__all__ = ['IndexApi']
|
||||
|
||||
|
||||
class DatesLoginMetricMixin:
|
||||
class DateTimeMixin:
|
||||
request: Request
|
||||
|
||||
@property
|
||||
def org(self):
|
||||
return current_org
|
||||
|
||||
@lazyproperty
|
||||
def days(self):
|
||||
query_params = self.request.query_params
|
||||
# monthly
|
||||
count = query_params.get('days')
|
||||
count = int(count) if count else 0
|
||||
return count
|
||||
|
||||
@lazyproperty
|
||||
def sessions_queryset(self):
|
||||
@property
|
||||
def days_to_datetime(self):
|
||||
days = self.days
|
||||
if days == 0:
|
||||
t = local_zero_hour()
|
||||
else:
|
||||
t = local_now() - timezone.timedelta(days=days)
|
||||
sessions_queryset = Session.objects.filter(date_start__gte=t)
|
||||
return sessions_queryset
|
||||
return t
|
||||
|
||||
@lazyproperty
|
||||
def session_dates_list(self):
|
||||
def dates_list(self):
|
||||
now = local_now()
|
||||
dates = [(now - timezone.timedelta(days=i)).date() for i in range(self.days)]
|
||||
dates.reverse()
|
||||
return dates
|
||||
|
||||
def get_dates_metrics_date(self):
|
||||
dates_metrics_date = [d.strftime('%m-%d') for d in self.session_dates_list] or ['0']
|
||||
dates_metrics_date = [d.strftime('%m-%d') for d in self.dates_list] or ['0']
|
||||
return dates_metrics_date
|
||||
|
||||
@lazyproperty
|
||||
def users(self):
|
||||
return self.org.get_members()
|
||||
|
||||
@lazyproperty
|
||||
def sessions_queryset(self):
|
||||
t = self.days_to_datetime
|
||||
sessions_queryset = Session.objects.filter(date_start__gte=t)
|
||||
return sessions_queryset
|
||||
|
||||
def get_logs_queryset(self, queryset, query_params):
|
||||
query = {}
|
||||
if not self.org.is_root():
|
||||
if query_params == 'username':
|
||||
query = {
|
||||
f'{query_params}__in': self.users.values_list('username', flat=True)
|
||||
}
|
||||
else:
|
||||
query = {
|
||||
f'{query_params}__in': [str(user) for user in self.users]
|
||||
}
|
||||
queryset = queryset.filter(**query)
|
||||
return queryset
|
||||
|
||||
@lazyproperty
|
||||
def login_logs_queryset(self):
|
||||
t = self.days_to_datetime
|
||||
queryset = UserLoginLog.objects.filter(datetime__gte=t)
|
||||
queryset = self.get_logs_queryset(queryset, 'username')
|
||||
return queryset
|
||||
|
||||
@lazyproperty
|
||||
def password_change_logs_queryset(self):
|
||||
t = self.days_to_datetime
|
||||
queryset = PasswordChangeLog.objects.filter(datetime__gte=t)
|
||||
queryset = self.get_logs_queryset(queryset, 'user')
|
||||
return queryset
|
||||
|
||||
@lazyproperty
|
||||
def operate_logs_queryset(self):
|
||||
t = self.days_to_datetime
|
||||
queryset = OperateLog.objects.filter(datetime__gte=t)
|
||||
queryset = self.get_logs_queryset(queryset, 'user')
|
||||
return queryset
|
||||
|
||||
@lazyproperty
|
||||
def ftp_logs_queryset(self):
|
||||
t = self.days_to_datetime
|
||||
queryset = OperateLog.objects.filter(datetime__gte=t)
|
||||
queryset = self.get_logs_queryset(queryset, 'user')
|
||||
return queryset
|
||||
|
||||
@lazyproperty
|
||||
def command_queryset(self):
|
||||
t = self.days_to_datetime
|
||||
t = t.timestamp()
|
||||
queryset = Command.objects.filter(timestamp__gte=t)
|
||||
return queryset
|
||||
|
||||
|
||||
class DatesLoginMetricMixin:
|
||||
dates_list: list
|
||||
command_queryset: Command.objects
|
||||
sessions_queryset: Session.objects
|
||||
ftp_logs_queryset: OperateLog.objects
|
||||
login_logs_queryset: UserLoginLog.objects
|
||||
operate_logs_queryset: OperateLog.objects
|
||||
password_change_logs_queryset: PasswordChangeLog.objects
|
||||
|
||||
@staticmethod
|
||||
def get_cache_key(date, tp):
|
||||
date_str = date.strftime("%Y%m%d")
|
||||
|
@ -93,7 +166,7 @@ class DatesLoginMetricMixin:
|
|||
|
||||
def get_dates_metrics_total_count_login(self):
|
||||
data = []
|
||||
for d in self.session_dates_list:
|
||||
for d in self.dates_list:
|
||||
count = self.get_date_login_count(d)
|
||||
data.append(count)
|
||||
if len(data) == 0:
|
||||
|
@ -112,7 +185,7 @@ class DatesLoginMetricMixin:
|
|||
|
||||
def get_dates_metrics_total_count_active_users(self):
|
||||
data = []
|
||||
for d in self.session_dates_list:
|
||||
for d in self.dates_list:
|
||||
count = self.get_date_user_count(d)
|
||||
data.append(count)
|
||||
return data
|
||||
|
@ -129,11 +202,28 @@ class DatesLoginMetricMixin:
|
|||
|
||||
def get_dates_metrics_total_count_active_assets(self):
|
||||
data = []
|
||||
for d in self.session_dates_list:
|
||||
for d in self.dates_list:
|
||||
count = self.get_date_asset_count(d)
|
||||
data.append(count)
|
||||
return data
|
||||
|
||||
def get_date_session_count(self, date):
|
||||
tp = "SESSION"
|
||||
count = self.__get_data_from_cache(date, tp)
|
||||
if count is not None:
|
||||
return count
|
||||
ds, de = self.get_date_start_2_end(date)
|
||||
count = Session.objects.filter(date_start__range=(ds, de)).count()
|
||||
self.__set_data_to_cache(date, tp, count)
|
||||
return count
|
||||
|
||||
def get_dates_metrics_total_count_sessions(self):
|
||||
data = []
|
||||
for d in self.dates_list:
|
||||
count = self.get_date_session_count(d)
|
||||
data.append(count)
|
||||
return data
|
||||
|
||||
@lazyproperty
|
||||
def get_type_to_assets(self):
|
||||
result = Asset.objects.annotate(type=F('platform__type')). \
|
||||
|
@ -181,8 +271,44 @@ class DatesLoginMetricMixin:
|
|||
]
|
||||
return sessions
|
||||
|
||||
@lazyproperty
|
||||
def user_login_logs_amount(self):
|
||||
return self.login_logs_queryset.count()
|
||||
|
||||
class IndexApi(DatesLoginMetricMixin, APIView):
|
||||
@lazyproperty
|
||||
def user_login_success_logs_amount(self):
|
||||
return self.login_logs_queryset.filter(status=LoginStatusChoices.success).count()
|
||||
|
||||
@lazyproperty
|
||||
def user_login_amount(self):
|
||||
return self.login_logs_queryset.values('username').distinct().count()
|
||||
|
||||
@lazyproperty
|
||||
def operate_logs_amount(self):
|
||||
return self.operate_logs_queryset.count()
|
||||
|
||||
@lazyproperty
|
||||
def change_password_logs_amount(self):
|
||||
return self.password_change_logs_queryset.count()
|
||||
|
||||
@lazyproperty
|
||||
def commands_amount(self):
|
||||
return self.command_queryset.count()
|
||||
|
||||
@lazyproperty
|
||||
def commands_danger_amount(self):
|
||||
return self.command_queryset.filter(risk_level=Command.RISK_LEVEL_DANGEROUS).count()
|
||||
|
||||
@lazyproperty
|
||||
def sessions_amount(self):
|
||||
return self.sessions_queryset.count()
|
||||
|
||||
@lazyproperty
|
||||
def ftp_logs_amount(self):
|
||||
return self.ftp_logs_queryset.count()
|
||||
|
||||
|
||||
class IndexApi(DateTimeMixin, DatesLoginMetricMixin, APIView):
|
||||
http_method_names = ['get']
|
||||
|
||||
def check_permissions(self, request):
|
||||
|
@ -193,7 +319,7 @@ class IndexApi(DatesLoginMetricMixin, APIView):
|
|||
|
||||
query_params = self.request.query_params
|
||||
|
||||
caches = OrgResourceStatisticsCache(current_org)
|
||||
caches = OrgResourceStatisticsCache(self.org)
|
||||
|
||||
_all = query_params.get('all')
|
||||
|
||||
|
@ -217,9 +343,9 @@ class IndexApi(DatesLoginMetricMixin, APIView):
|
|||
'total_count_assets_this_week': caches.new_assets_amount_this_week,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_today_login_users'):
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_login_users'):
|
||||
data.update({
|
||||
'total_count_today_login_users': caches.total_count_today_login_users,
|
||||
'total_count_login_users': self.user_login_amount
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_today_active_assets'):
|
||||
|
@ -242,9 +368,50 @@ class IndexApi(DatesLoginMetricMixin, APIView):
|
|||
'total_count_today_failed_sessions': caches.total_count_today_failed_sessions,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_type_to_assets_amount'):
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_user_login_logs'):
|
||||
data.update({
|
||||
'total_count_type_to_assets_amount': self.get_type_to_assets,
|
||||
'total_count_user_login_logs': self.user_login_logs_amount,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_user_login_success_logs'):
|
||||
data.update({
|
||||
'total_count_user_login_success_logs': self.user_login_success_logs_amount,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_operate_logs'):
|
||||
data.update({
|
||||
'total_count_operate_logs': self.operate_logs_amount,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_change_password_logs'):
|
||||
data.update({
|
||||
'total_count_change_password_logs': self.change_password_logs_amount,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_commands'):
|
||||
data.update({
|
||||
'total_count_commands': self.commands_amount,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_commands_danger'):
|
||||
data.update({
|
||||
'total_count_commands_danger': self.commands_danger_amount,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_history_sessions'):
|
||||
data.update({
|
||||
'total_count_history_sessions': self.sessions_amount - caches.total_count_online_sessions,
|
||||
})
|
||||
|
||||
if _all or query_params.get('total_count') or query_params.get('total_count_ftp_logs'):
|
||||
data.update({
|
||||
'total_count_ftp_logs': self.ftp_logs_amount,
|
||||
})
|
||||
|
||||
if _all or query_params.get('session_dates_metrics'):
|
||||
data.update({
|
||||
'dates_metrics_date': self.get_dates_metrics_date(),
|
||||
'dates_metrics_total_count_session': self.get_dates_metrics_total_count_sessions(),
|
||||
})
|
||||
|
||||
if _all or query_params.get('dates_metrics'):
|
||||
|
|
|
@ -7,8 +7,6 @@ from common.cache import Cache, IntegerField
|
|||
from common.utils import get_logger
|
||||
from common.utils.timezone import local_zero_hour, local_monday
|
||||
from users.models import UserGroup, User
|
||||
from audits.models import UserLoginLog
|
||||
from audits.const import LoginStatusChoices
|
||||
from assets.models import Node, Domain, Asset, Account
|
||||
from terminal.models import Session
|
||||
from perms.models import AssetPermission
|
||||
|
@ -64,7 +62,6 @@ class OrgResourceStatisticsCache(OrgRelatedCache):
|
|||
asset_perms_amount = IntegerField(queryset=AssetPermission.objects)
|
||||
total_count_online_users = IntegerField()
|
||||
total_count_online_sessions = IntegerField()
|
||||
total_count_today_login_users = IntegerField()
|
||||
total_count_today_active_assets = IntegerField()
|
||||
total_count_today_failed_sessions = IntegerField()
|
||||
|
||||
|
@ -113,16 +110,6 @@ class OrgResourceStatisticsCache(OrgRelatedCache):
|
|||
def compute_total_count_online_sessions():
|
||||
return Session.objects.filter(is_finished=False).count()
|
||||
|
||||
def compute_total_count_today_login_users(self):
|
||||
t = local_zero_hour()
|
||||
user_login_logs = UserLoginLog.objects.filter(
|
||||
datetime__gte=t, status=LoginStatusChoices.success
|
||||
)
|
||||
if not self.org.is_root():
|
||||
usernames = self.org.get_members().values('username')
|
||||
user_login_logs = user_login_logs.filter(username__in=usernames)
|
||||
return user_login_logs.values('username').distinct().count()
|
||||
|
||||
@staticmethod
|
||||
def compute_total_count_today_active_assets():
|
||||
t = local_zero_hour()
|
||||
|
|
|
@ -88,6 +88,9 @@ class AssetsSerializerFormatMixin:
|
|||
serializer_class = serializers.AssetGrantedSerializer
|
||||
filterset_fields = ['name', 'address', 'id', 'comment']
|
||||
search_fields = ['name', 'address', 'comment']
|
||||
filterset_class = AssetFilterSet
|
||||
ordering_fields = ("name", "address")
|
||||
ordering = ('name',)
|
||||
|
||||
|
||||
class AssetsTreeFormatMixin(SerializeToTreeNodeMixin):
|
||||
|
|
|
@ -5,8 +5,8 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from rest_framework import serializers
|
||||
|
||||
from assets.const import Category, AllTypes
|
||||
from assets.serializers.asset.common import AssetProtocolsSerializer
|
||||
from assets.models import Node, Asset, Platform, Account
|
||||
from assets.serializers.asset.common import AssetProtocolsSerializer
|
||||
from common.drf.fields import ObjectRelatedField, LabeledChoiceField
|
||||
from perms.serializers.permission import ActionChoicesField
|
||||
|
||||
|
@ -48,5 +48,6 @@ class AccountsPermedSerializer(serializers.ModelSerializer):
|
|||
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = ['id', 'name', 'has_username', 'username', 'has_secret', 'secret_type', 'actions']
|
||||
fields = ['id', 'name', 'has_username', 'username',
|
||||
'has_secret', 'secret_type', 'actions']
|
||||
read_only_fields = fields
|
||||
|
|
|
@ -131,10 +131,11 @@ class NativeClient(TextChoices):
|
|||
|
||||
@classmethod
|
||||
def get_launch_command(cls, name, token, endpoint, os='windows'):
|
||||
username = f'JMS-{token.id}'
|
||||
commands = {
|
||||
cls.ssh: f'ssh {token.id}@{endpoint.host} -p {endpoint.ssh_port}',
|
||||
cls.putty: f'putty -ssh {token.id}@{endpoint.host} -P {endpoint.ssh_port}',
|
||||
cls.xshell: f'xshell -url ssh://{token.id}:{token.value}@{endpoint.host}:{endpoint.ssh_port}',
|
||||
cls.ssh: f'ssh {username}@{endpoint.host} -p {endpoint.ssh_port}',
|
||||
cls.putty: f'putty.exe -ssh {username}@{endpoint.host} -P {endpoint.ssh_port}',
|
||||
cls.xshell: f'xshell.exe -url ssh://{username}:{token.value}@{endpoint.host}:{endpoint.ssh_port}',
|
||||
# cls.mysql: 'mysql -h {hostname} -P {port} -u {username} -p',
|
||||
# cls.psql: {
|
||||
# 'default': 'psql -h {hostname} -p {port} -U {username} -W',
|
||||
|
|
Loading…
Reference in New Issue