mirror of https://github.com/jumpserver/jumpserver
perf: Pam dashboard
parent
afc1d6610f
commit
83dc15d441
|
@ -1,5 +1,6 @@
|
|||
from .account import *
|
||||
from .application import *
|
||||
from .pam_dashboard import *
|
||||
from .task import *
|
||||
from .template import *
|
||||
from .virtual import *
|
||||
from .application import *
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.http.response import JsonResponse
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from accounts.models import Account, RiskChoice
|
||||
|
||||
__all__ = ['PamDashboardApi']
|
||||
|
||||
|
||||
class PamDashboardApi(APIView):
|
||||
http_method_names = ['get']
|
||||
rbac_perms = {
|
||||
'GET': 'accounts.view_account',
|
||||
}
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
query_params = self.request.query_params
|
||||
data = {}
|
||||
|
||||
account_count = Account.objects.count()
|
||||
privileged_account_count = Account.objects.filter(privileged=True).count()
|
||||
|
||||
if query_params.get('total_privileged_accounts'):
|
||||
data['total_privileged_accounts'] = privileged_account_count
|
||||
|
||||
if query_params.get('total_ordinary_accounts'):
|
||||
data['total_ordinary_accounts'] = account_count - privileged_account_count
|
||||
|
||||
if query_params.get('total_unmanaged_accounts'):
|
||||
data['total_unmanaged_accounts'] = Account.get_risks(RiskChoice.new_found).count()
|
||||
|
||||
if query_params.get('total_unavailable_accounts'):
|
||||
data['total_unavailable_accounts'] = Account.objects.filter(is_active=False).count()
|
||||
|
||||
if query_params.get('total_weak_password_accounts'):
|
||||
data['total_weak_password_accounts'] = Account.get_risks(RiskChoice.weak_password)
|
||||
|
||||
if query_params.get('total_long_time_change_password_accounts'):
|
||||
data['total_long_time_change_password_accounts'] = Account.get_risks(RiskChoice.long_time_password)
|
||||
|
||||
return JsonResponse(data, status=200)
|
|
@ -3,7 +3,7 @@ from collections import defaultdict
|
|||
|
||||
from django.utils import timezone
|
||||
|
||||
from accounts.models import Account, AccountRisk
|
||||
from accounts.models import Account, AccountRisk, RiskChoice
|
||||
from assets.automations.base.manager import BaseManager
|
||||
from common.decorators import bulk_create_decorator, bulk_update_decorator
|
||||
from common.utils.strings import color_fmt
|
||||
|
@ -69,12 +69,12 @@ def check_account_secrets(accounts, assets):
|
|||
|
||||
if is_weak_password(account.secret):
|
||||
print(tmpl % (account, color_fmt("weak", "red")))
|
||||
summary["weak_password"] += 1
|
||||
result["weak_password"].append(result_item)
|
||||
summary[RiskChoice.weak_password] += 1
|
||||
result[RiskChoice.weak_password].append(result_item)
|
||||
risks.append(
|
||||
{
|
||||
"account": account,
|
||||
"risk": "weak_password",
|
||||
"risk": RiskChoice.weak_password,
|
||||
}
|
||||
)
|
||||
else:
|
||||
|
@ -143,7 +143,7 @@ class CheckAccountManager(BaseManager):
|
|||
"\n---\nSummary: \nok: %s, weak password: %s, no secret: %s, using time: %ss"
|
||||
% (
|
||||
self.summary["ok"],
|
||||
self.summary["weak_password"],
|
||||
self.summary[RiskChoice.weak_password],
|
||||
self.summary["no_secret"],
|
||||
int(self.duration),
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@ from collections import defaultdict
|
|||
from django.utils import timezone
|
||||
|
||||
from accounts.const import AutomationTypes
|
||||
from accounts.models import GatheredAccount, Account, AccountRisk
|
||||
from accounts.models import GatheredAccount, Account, AccountRisk, RiskChoice
|
||||
from common.const import ConfirmOrIgnore
|
||||
from common.decorators import bulk_create_decorator, bulk_update_decorator
|
||||
from common.utils import get_logger
|
||||
|
@ -68,7 +68,7 @@ class AnalyseAccountRisk:
|
|||
{"field": "date_last_login", "risk": "long_time_no_login", "delta": long_time},
|
||||
{
|
||||
"field": "date_password_change",
|
||||
"risk": "long_time_password",
|
||||
"risk": RiskChoice.long_time_password,
|
||||
"delta": long_time,
|
||||
},
|
||||
{
|
||||
|
@ -164,7 +164,7 @@ class AnalyseAccountRisk:
|
|||
self._create_risk(
|
||||
dict(
|
||||
**basic,
|
||||
risk="new_found",
|
||||
risk=RiskChoice.new_found,
|
||||
details=[{"datetime": self.now.isoformat()}],
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.db.models import Q, Exists, OuterRef
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
from django_filters import rest_framework as drf_filters
|
||||
|
||||
from assets.models import Node
|
||||
from common.drf.filters import BaseFilterSet
|
||||
from common.utils.timezone import local_zero_hour, local_now
|
||||
from .models import Account, GatheredAccount, ChangeSecretRecord, AccountRisk
|
||||
from .models import Account, GatheredAccount, ChangeSecretRecord
|
||||
|
||||
|
||||
class AccountFilterSet(BaseFilterSet):
|
||||
|
@ -62,16 +62,7 @@ class AccountFilterSet(BaseFilterSet):
|
|||
if not value:
|
||||
return queryset
|
||||
|
||||
queryset = queryset.filter(
|
||||
Exists(
|
||||
AccountRisk.objects.filter(
|
||||
risk=value,
|
||||
asset_id=OuterRef('asset_id'),
|
||||
username=OuterRef('username')
|
||||
)
|
||||
)
|
||||
)
|
||||
return queryset
|
||||
return Account.get_risks(queryset, value)
|
||||
|
||||
@staticmethod
|
||||
def filter_latest(queryset, name, value):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.db import models
|
||||
from django.db.models import Exists, OuterRef
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
||||
|
@ -165,6 +166,22 @@ class Account(AbsConnectivity, LabeledMixin, BaseAccount):
|
|||
|
||||
return escape(value)
|
||||
|
||||
@classmethod
|
||||
def get_risks(cls, queryset=None, risk_type=None):
|
||||
from accounts.models import AccountRisk
|
||||
subquery = AccountRisk.objects.filter(
|
||||
asset_id=OuterRef('asset_id'),
|
||||
username=OuterRef('username')
|
||||
)
|
||||
|
||||
if risk_type:
|
||||
subquery = subquery.filter(risk=risk_type)
|
||||
|
||||
if queryset is None:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
return queryset.filter(Exists(subquery))
|
||||
|
||||
|
||||
def replace_history_model_with_mixin():
|
||||
"""
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from accounts.const import AutomationTypes
|
||||
from common.const import ConfirmOrIgnore
|
||||
from accounts.models import (
|
||||
GatheredAccount,
|
||||
AccountRisk,
|
||||
SecretType,
|
||||
AutomationExecution,
|
||||
AutomationExecution, RiskChoice,
|
||||
)
|
||||
from django.utils import timezone
|
||||
|
||||
from common.const import ConfirmOrIgnore
|
||||
|
||||
TYPE_CHOICES = [
|
||||
|
@ -83,7 +81,7 @@ class RiskHandler:
|
|||
GatheredAccount.objects.filter(asset=self.asset, username=self.username).update(
|
||||
present=True, status=ConfirmOrIgnore.confirmed
|
||||
)
|
||||
self.risk = "new_found"
|
||||
self.risk = RiskChoice.new_found
|
||||
|
||||
def handle_disable_remote(self):
|
||||
pass
|
||||
|
|
|
@ -49,6 +49,7 @@ urlpatterns = [
|
|||
path('push-account/<uuid:pk>/nodes/', api.PushAccountNodeAddRemoveApi.as_view(),
|
||||
name='push-account-add-or-remove-node'),
|
||||
path('push-account/<uuid:pk>/assets/', api.PushAccountAssetsListApi.as_view(), name='push-account-assets'),
|
||||
path('pam-dashboard/', api.PamDashboardApi.as_view(), name='pam-dashboard'),
|
||||
path('change-secret-dashboard/', api.ChangeSecretDashboardApi.as_view(), name='change-secret-dashboard'),
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue