perf: Pam dashboard

pull/14760/head
feng 2025-01-03 17:47:18 +08:00 committed by feng626
parent afc1d6610f
commit 83dc15d441
8 changed files with 76 additions and 26 deletions

View File

@ -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 *

View File

@ -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)

View File

@ -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),
)

View File

@ -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()}],
)
)

View File

@ -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):

View File

@ -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():
"""

View File

@ -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

View File

@ -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'),
]