perf: check account engine

pull/14833/head
feng 2025-01-21 17:04:27 +08:00 committed by feng626
parent 01ac001f84
commit ef0df85a15
5 changed files with 88 additions and 80 deletions

View File

@ -138,47 +138,16 @@ class CheckAccountEngineViewSet(JMSModelViewSet):
search_fields = ("name",)
serializer_class = serializers.CheckAccountEngineSerializer
@staticmethod
def get_default_engines():
data = [
{
"id": "00000000-0000-0000-0000-000000000001",
"slug": "check_gathered_account",
"name": "检查发现的账号",
"comment": "基于自动发现的账号结果进行检查分析,检查 用户组、公钥、sudoers 等信息",
},
{
"id": "00000000-0000-0000-0000-000000000002",
"slug": "check_account_secret",
"name": "检查账号密码强弱",
"comment": "基于账号密码的安全性进行检查分析, 检查密码强度、泄露等信息",
},
{
"id": "00000000-0000-0000-0000-000000000003",
"slug": "check_account_repeat",
"name": "检查账号密码是否重复",
"comment": "检查账号是否与其它账号相同"
},
{
"id": "00000000-0000-0000-0000-000000000004",
"slug": "check_account_leak",
"name": "检查账号密码是否是常见密码",
"comment": "检查账号密码是否是常见泄露的密码"
},
]
return data
def init_if_need(self):
data = self.get_default_engines()
model_cls = CheckAccountEngine
if model_cls.objects.count() == 4:
return
for item in data:
model_cls.objects.update_or_create(defaults=item, id=item["id"])
perm_model = CheckAccountEngine
def get_queryset(self):
# return self.get_default_engines()
self.init_if_need()
return CheckAccountEngine.objects.all()
return CheckAccountEngine.get_default_engines()
def filter_queryset(self, queryset: list):
search = self.request.GET.get('search')
if search is not None:
queryset = [
item for item in queryset
if search in item['name']
]
return queryset

View File

@ -6,28 +6,7 @@ import django.db.models.deletion
from django.db import migrations, models
def init_account_check_engine(apps, schema_editor):
data = [
{
'id': '00000000-0000-0000-0000-000000000001',
'slug': 'check_gathered_account',
'name': '检查发现的账号',
'comment': '基于自动发现的账号结果进行检查分析,检查 用户组、公钥、sudoers 等信息'
},
{
'id': '00000000-0000-0000-0000-000000000002',
'slug': 'check_account_secret',
'name': '检查账号密码强弱',
'comment': '基于账号密码的安全性进行检查分析, 检查密码强度、泄露等信息'
}
]
model_cls = apps.get_model('accounts', 'CheckAccountEngine')
for item in data:
model_cls.objects.create(**item)
class Migration(migrations.Migration):
dependencies = [
("assets", "0007_baseautomation_date_last_run_and_more"),
(
@ -139,5 +118,4 @@ class Migration(migrations.Migration):
verbose_name="Engines",
),
),
migrations.RunPython(init_account_check_engine),
]

View File

@ -0,0 +1,26 @@
# Generated by Django 4.1.13 on 2025-01-21 08:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0027_accountrisk_gathered_account'),
]
operations = [
migrations.RemoveField(
model_name='checkaccountengine',
name='is_active',
),
migrations.RemoveField(
model_name='checkaccountautomation',
name='engines',
),
migrations.AddField(
model_name='checkaccountautomation',
name='engines',
field=models.JSONField(default=list, verbose_name='Engines'),
),
]

View File

@ -15,13 +15,13 @@ __all__ = ['CheckAccountAutomation', 'AccountRisk', 'RiskChoice', 'CheckAccountE
class CheckAccountAutomation(AccountBaseAutomation):
engines = models.ManyToManyField('CheckAccountEngine', related_name='check_automations', verbose_name=_('Engines'))
engines = models.JSONField(default=list, verbose_name=_('Engines'))
recipients = models.ManyToManyField('users.User', verbose_name=_("Recipient"), blank=True)
def to_attr_json(self):
attr_json = super().to_attr_json()
attr_json.update({
'engines': [engine.slug for engine in self.engines.all()],
'engines': self.engines,
'recipients': [str(user.id) for user in self.recipients.all()]
})
return attr_json
@ -117,14 +117,43 @@ class AccountRisk(JMSOrgBaseModel):
class CheckAccountEngine(JMSBaseModel):
name = models.CharField(max_length=128, verbose_name=_('Name'), unique=True)
slug = models.SlugField(max_length=128, verbose_name=_('Slug'), unique=True) #
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
slug = models.SlugField(max_length=128, verbose_name=_('Slug'), unique=True)
def __str__(self):
return self.name
def internals(self):
return [
'check_gathered_account',
'check_account_secret'
@staticmethod
def get_default_engines():
data = [
{
"id": "00000000-0000-0000-0000-000000000001",
"slug": "check_gathered_account",
"name": _("Check the discovered accounts"),
"comment": _(
"Perform checks and analyses based on automatically discovered account results, "
"including user groups, public keys, sudoers, and other information"
)
},
{
"id": "00000000-0000-0000-0000-000000000002",
"slug": "check_account_secret",
"name": _("Check the strength of your account and password"),
"comment": _(
"Perform checks and analyses based on the security of account passwords, "
"including password strength, leakage, etc."
)
},
{
"id": "00000000-0000-0000-0000-000000000003",
"slug": "check_account_repeat",
"name": _("Check if the account and password are repeated"),
"comment": _("Check if the account is the same as other accounts")
},
{
"id": "00000000-0000-0000-0000-000000000004",
"slug": "check_account_leak",
"name": _("Check whether the account password is a common password"),
"comment": _("Check whether the account password is a commonly leaked password")
},
]
return data

View File

@ -10,12 +10,12 @@ from accounts.models import (
RiskChoice,
CheckAccountEngine,
)
from accounts.risk_handlers import TYPE_CHOICES
from assets.models import Asset
from common.const import ConfirmOrIgnore
from common.serializers.fields import ObjectRelatedField, LabeledChoiceField
from common.utils import get_logger
from .base import BaseAutomationSerializer
from accounts.risk_handlers import TYPE_CHOICES
logger = get_logger(__file__)
@ -88,9 +88,9 @@ class CheckAccountAutomationSerializer(BaseAutomationSerializer):
model = CheckAccountAutomation
read_only_fields = BaseAutomationSerializer.Meta.read_only_fields
fields = (
BaseAutomationSerializer.Meta.fields
+ ["engines", "recipients"]
+ read_only_fields
BaseAutomationSerializer.Meta.fields
+ ["engines", "recipients"]
+ read_only_fields
)
extra_kwargs = BaseAutomationSerializer.Meta.extra_kwargs
@ -98,12 +98,18 @@ class CheckAccountAutomationSerializer(BaseAutomationSerializer):
def model_type(self):
return AutomationTypes.check_account
@staticmethod
def validate_engines(engines):
valid_slugs = {i['slug'] for i in CheckAccountEngine.get_default_engines()}
if not all(engine in valid_slugs for engine in engines):
raise serializers.ValidationError(_("Invalid engine id"))
return engines
class CheckAccountEngineSerializer(serializers.ModelSerializer):
class Meta:
model = CheckAccountEngine
fields = ["id", "name", "slug", "is_active", "comment"]
fields = ["id", "name", "slug", "comment"]
read_only_fields = ["slug"]
extra_kwargs = {
"is_active": {"required": False},
}