perf: add delete account action (#15059)

This commit is contained in:
fit2bot
2025-03-18 16:57:27 +08:00
committed by GitHub
parent e802e145af
commit cdebfd8121
17 changed files with 2792 additions and 2573 deletions

View File

@@ -30,7 +30,6 @@ __all__ = [
]
from ...filters import NodeFilterBackend
from ...risk_handlers import RiskHandler
@@ -130,11 +129,13 @@ class AccountRiskViewSet(OrgBulkModelViewSet):
s.validated_data, ("asset", "username", "action", "risk")
)
handler = RiskHandler(asset=asset, username=username, request=self.request)
data = handler.handle(act, risk)
if not data:
return Response(data={"message": "Success"})
s = serializers.AccountRiskSerializer(instance=data)
return Response(data=s.data)
try:
risk = handler.handle(act, risk)
s = serializers.AccountRiskSerializer(instance=risk)
return Response(data=s.data)
except Exception as e:
return Response(status=400, data=str(e))
class CheckAccountEngineViewSet(JMSModelViewSet):

View File

@@ -155,6 +155,19 @@ class AnalyseAccountRisk:
def _update_risk(self, account):
return account
def lost_accounts(self, asset, lost_users):
if not self.check_risk:
return
for user in lost_users:
self._create_risk(
dict(
asset_id=str(asset.id),
username=user,
risk=RiskChoice.account_deleted,
details=[{"datetime": self.now.isoformat()}],
)
)
def analyse_risk(self, asset, ga, d, sys_found):
if not self.check_risk:
return
@@ -289,6 +302,8 @@ class GatherAccountsManager(AccountBasePlaybookManager):
"username": username,
}
)
risk_analyser = AnalyseAccountRisk(self.check_risk)
risk_analyser.lost_accounts(asset, lost_users)
# 收集的账号 比 账号列表多的, 有可能是账号中删掉了, 但这时候状态已经是 confirm 了
# 标识状态为 待处理, 让管理员去确认

View File

@@ -139,6 +139,7 @@ class Migration(migrations.Migration):
choices=[
("long_time_no_login", "Long time no login"),
("new_found", "New found"),
("account_deleted", "Account deleted"),
("groups_changed", "Groups change"),
("sudoers_changed", "Sudo changed"),
("authorized_keys_changed", "Authorized keys changed"),

View File

@@ -1,8 +1,9 @@
from itertools import islice
from django.db import models
from django.db.models import TextChoices
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from itertools import islice
from common.const import ConfirmOrIgnore
from common.db.models import JMSBaseModel
@@ -41,6 +42,7 @@ class RiskChoice(TextChoices):
# 依赖自动发现的
long_time_no_login = 'long_time_no_login', _('Long time no login') # 好久没登录的账号, 禁用、删除
new_found = 'new_found', _('New found') # 未被纳管的账号, 纳管, 删除, 禁用
account_deleted = 'account_deleted', _('Account deleted') # 账号被删除, 纳管, 删除, 禁用
group_changed = 'groups_changed', _('Groups change') # 组变更, 确认
sudo_changed = 'sudoers_changed', _('Sudo changed') # sudo 变更, 确认
authorized_keys_changed = 'authorized_keys_changed', _('Authorized keys changed') # authorized_keys 变更, 确认

View File

@@ -8,7 +8,7 @@ from accounts.models import (
AccountRisk,
SecretType,
AutomationExecution,
RiskChoice
RiskChoice, Account
)
from common.const import ConfirmOrIgnore
from common.utils import random_string
@@ -19,10 +19,11 @@ TYPE_CHOICES = [
("close", _("Close")),
("disable_remote", _("Disable remote")),
("delete_remote", _("Delete remote")),
("delete_account", _("Delete account")),
("delete_both", _("Delete remote")),
("add_account", _("Add account")),
("change_password_add", _("Change password and Add")),
("change_password", _("Change password"))
("change_password", _("Change password")),
]
@@ -73,6 +74,10 @@ class RiskHandler:
def handle_reopen(self):
pass
def handle_delete_account(self):
Account.objects.filter(asset=self.asset, username=self.username).delete()
GatheredAccount.objects.filter(asset=self.asset, username=self.username).delete()
def handle_close(self):
pass
@@ -102,7 +107,7 @@ class RiskHandler:
present=True, status=ConfirmOrIgnore.confirmed
)
self.risk = RiskChoice.new_found
risk = self.get_risk()
risk.account = account
risk.save()
@@ -113,6 +118,15 @@ class RiskHandler:
def handle_delete_remote(self):
self._handle_delete(delete="remote")
@staticmethod
def start_execution(execution):
execution.save()
execution.start()
if execution.status != "success":
msg = _("Execution failed: {}").format(execution.status)
raise ValidationError(msg)
def _handle_delete(self, delete="both"):
asset = self.asset
execution = AutomationExecution()
@@ -124,9 +138,7 @@ class RiskHandler:
"delete": delete,
"risk": self.risk
}
execution.save()
execution.start()
return execution.summary
self.start_execution(execution)
def handle_delete_both(self):
self._handle_delete(delete="both")
@@ -134,7 +146,11 @@ class RiskHandler:
def handle_change_password(self):
asset = self.asset
execution = AutomationExecution()
account = self.asset.accounts.get(username=self.username)
account = self.asset.accounts.filter(username=self.username, secret_type=SecretType.PASSWORD).first()
if not account:
raise ValidationError("Account not found")
execution.snapshot = {
"assets": [str(asset.id)],
"accounts": [str(account.id)],
@@ -143,9 +159,7 @@ class RiskHandler:
"secret_strategy": "random",
"name": "Change account password: {}@{}".format(self.username, asset.name),
}
execution.save()
execution.start()
return execution.summary
self.start_execution(execution)
def handle_change_password_add(self):
asset = self.asset
@@ -174,10 +188,10 @@ class RiskHandler:
'check_conn_after_change': True,
"name": "Push account password: {}@{}".format(self.username, asset.name),
}
execution.save()
execution.start()
self.start_execution(execution)
GatheredAccount.objects.filter(asset=self.asset, username=self.username).update(
present=True
(
GatheredAccount.objects
.filter(asset=self.asset, username=self.username)
.update(present=True)
)
return execution.summary