perf: update pam

pull/14387/merge
ibuler 2 weeks ago
parent 82222f9c23
commit 39f87c1c64

@ -96,7 +96,6 @@ class GatherAccountsFilter:
user['groups'] = username_groups.get(username) or ''
user['sudoers'] = username_sudo.get(username) or ''
user['authorized_keys'] = username_authorized.get(username) or ''
result[username] = user
return result

@ -49,13 +49,13 @@
register: user_authorized
- set_fact:
info:
users: "{{ users.stdout_lines }}"
last_login: "{{ last_login.stdout_lines }}"
user_groups: "{{ user_groups.stdout_lines }}"
user_sudo: "{{ user_sudo.stdout_lines }}"
user_authorized: "{{ user_authorized.stdout_lines }}"
passwd_date: "{{ passwd_date.stdout_lines }}"
info:
users: "{{ users.stdout_lines }}"
last_login: "{{ last_login.stdout_lines }}"
user_groups: "{{ user_groups.stdout_lines }}"
user_sudo: "{{ user_sudo.stdout_lines }}"
user_authorized: "{{ user_authorized.stdout_lines }}"
passwd_date: "{{ passwd_date.stdout_lines }}"
- debug:
var: info
var: info

@ -20,9 +20,13 @@ logger = get_logger(__name__)
class GatherAccountsManager(AccountBasePlaybookManager):
diff_items = [
'authorized_keys', 'sudoers', 'groups',
'date_password_change', 'date_password_expired',
]
long_time = timezone.timedelta(days=90)
datetime_check_items = [
{'field': 'date_last_login', 'risk': 'zombie', 'delta': long_time},
{'field': 'date_password_change', 'risk': 'long_time_password', 'delta': long_time},
{'field': 'date_password_expired', 'risk': 'password_expired', 'delta': timezone.timedelta(seconds=1)}
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@ -70,6 +74,7 @@ class GatherAccountsManager(AccountBasePlaybookManager):
self.asset_account_info[asset] = accounts
def on_runner_failed(self, runner, e):
print("Runner failed: ", e)
raise e
def on_host_success(self, host, result):
@ -167,6 +172,7 @@ class GatherAccountsManager(AccountBasePlaybookManager):
now = timezone.now().isoformat()
diff = self.get_items_diff(ori_account, d)
print("Diff items: ", diff)
if not diff:
return
@ -175,20 +181,43 @@ class GatherAccountsManager(AccountBasePlaybookManager):
asset=ori_account.asset, username=ori_account.username,
risk=k+'_changed', details=[{'datetime': now, 'diff': v}]
))
print("Pending add risks: ", self.pending_add_risks)
@staticmethod
def perform_save_risks(risks):
# 提前取出来,避免每次都查数据库
assets = {r.asset for r in risks}
assets_risks = AccountRisk.objects.filter(asset__in=assets)
assets_risks = {f"{r.asset_id}_{r.username}": r for r in assets_risks}
assets_risks = {f"{r.asset_id}_{r.username}_{r.risk}": r for r in assets_risks}
for r in risks:
found = assets_risks.get(f"{r.asset_id}_{r.username}")
found = assets_risks.get(f"{r.asset_id}_{r.username}_{r.risk}")
if not found:
r.save()
else:
found.details.extend(r.details)
continue
found.details.extend(r.details)
found.save(update_fields=['details'])
def _analyse_datetime_changed(self, ori_account, d, asset, username):
for item in self.datetime_check_items:
field = item['field']
risk = item['risk']
delta = item['delta']
date = d.get(field)
if not date:
continue
pre_date = ori_account and getattr(ori_account, field)
if pre_date == date:
continue
if date and date < timezone.now() - delta:
self.pending_add_risks.append(
AccountRisk(asset=asset, username=username, risk=risk)
)
def batch_analyse_risk(self, asset, ori_account, d, batch_size=20):
if asset is None:
@ -204,26 +233,10 @@ class GatherAccountsManager(AccountBasePlaybookManager):
self._analyse_item_changed(ori_account, d)
else:
self.pending_add_risks.append(
AccountRisk(**basic, risk='ghost', )
AccountRisk(**basic, risk='ghost')
)
last_login = d.get('date_last_login')
if last_login and last_login < timezone.now() - self.long_time:
self.pending_add_risks.append(
AccountRisk(**basic, risk='zombie')
)
date_password_change = d.get('date_password_change')
if date_password_change and date_password_change < timezone.now() - self.long_time:
self.pending_add_risks.append(
AccountRisk(**basic, risk='long_time_password')
)
date_password_expired = d.get('date_password_expired')
if date_password_expired and date_password_expired < timezone.now():
self.pending_add_risks.append(
AccountRisk(**basic, risk='password_expired')
)
self._analyse_datetime_changed(ori_account, d, asset, d['username'])
if len(self.pending_add_risks) > batch_size:
self.batch_analyse_risk(None, None, {})
@ -279,6 +292,7 @@ class GatherAccountsManager(AccountBasePlaybookManager):
else:
self.batch_update_gathered_account(ori_account, d)
print("Batch analyse risk")
self.batch_analyse_risk(asset, ori_account, d)
self.update_gather_accounts_status(asset)

@ -0,0 +1,18 @@
# Generated by Django 4.1.13 on 2024-11-12 06:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("accounts", "0010_accountrisk_details_alter_accountrisk_comment"),
]
operations = [
migrations.RenameField(
model_name="gatheredaccount",
old_name="date_change_password",
new_name="date_password_change",
),
]

@ -22,7 +22,7 @@ class GatheredAccount(JMSOrgBaseModel):
groups = models.TextField(default='', blank=True, verbose_name=_("Groups"))
remote_present = models.BooleanField(default=True, verbose_name=_("Remote present")) # 远端资产上是否还存在
present = models.BooleanField(default=False, verbose_name=_("Present")) # 系统资产上是否还存在
date_change_password = models.DateTimeField(null=True, verbose_name=_("Date change password"))
date_password_change = models.DateTimeField(null=True, verbose_name=_("Date change password"))
date_password_expired = models.DateTimeField(null=True, verbose_name=_("Date password expired"))
status = models.CharField(max_length=32, default='', blank=True, choices=ConfirmOrIgnore.choices, verbose_name=_("Status"))

@ -1,6 +1,5 @@
from .account import *
from .backup import *
from .base import *
from .gathered_account import *
from .template import *
from .virtual import *

@ -1,42 +0,0 @@
from django.utils.translation import gettext_lazy as _
from accounts.models import GatheredAccount
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from .account import AccountAssetSerializer as _AccountAssetSerializer
from .base import BaseAccountSerializer
__all__ = [
'GatheredAccountSerializer',
'GatheredAccountActionSerializer',
]
class AccountAssetSerializer(_AccountAssetSerializer):
class Meta(_AccountAssetSerializer.Meta):
fields = [f for f in _AccountAssetSerializer.Meta.fields if f != 'auto_config']
class GatheredAccountSerializer(BulkOrgResourceModelSerializer):
asset = AccountAssetSerializer(label=_('Asset'))
class Meta(BaseAccountSerializer.Meta):
model = GatheredAccount
fields = [
'id', 'asset', 'username',
'date_updated', 'address_last_login',
'groups', 'sudoers', 'authorized_keys',
'remote_present', 'present',
'date_last_login', 'status'
]
read_only_fields = fields
@classmethod
def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('asset', 'asset__platform')
return queryset
class GatheredAccountActionSerializer(GatheredAccountSerializer):
class Meta(GatheredAccountSerializer.Meta):
read_only_fields = list(set(GatheredAccountSerializer.Meta.read_only_fields) - {'status'})

@ -28,7 +28,7 @@ class AccountRiskSerializer(serializers.ModelSerializer):
model = AccountRisk
fields = [
'id', 'asset', 'username', 'risk', 'status',
'date_created', 'comment'
'date_created', 'details',
]

@ -1,14 +1,16 @@
# -*- coding: utf-8 -*-
#
from django.utils.translation import gettext_lazy as _
from accounts.const import AutomationTypes
from accounts.models import GatherAccountsAutomation
from common.utils import get_logger
from accounts.models import GatheredAccount
from accounts.serializers.account.account import AccountAssetSerializer as _AccountAssetSerializer
from accounts.serializers.account.base import BaseAccountSerializer
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from .base import BaseAutomationSerializer
logger = get_logger(__file__)
__all__ = [
'GatheredAccountSerializer',
'GatheredAccountActionSerializer',
'GatherAccountAutomationSerializer',
]
@ -25,3 +27,33 @@ class GatherAccountAutomationSerializer(BaseAutomationSerializer):
@property
def model_type(self):
return AutomationTypes.gather_accounts
class AccountAssetSerializer(_AccountAssetSerializer):
class Meta(_AccountAssetSerializer.Meta):
fields = [f for f in _AccountAssetSerializer.Meta.fields if f != 'auto_config']
class GatheredAccountSerializer(BulkOrgResourceModelSerializer):
asset = AccountAssetSerializer(label=_('Asset'))
class Meta(BaseAccountSerializer.Meta):
model = GatheredAccount
fields = [
'id', 'asset', 'username',
'date_last_login', 'address_last_login',
'remote_present', 'present',
'date_updated', 'status',
]
read_only_fields = fields
@classmethod
def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('asset', 'asset__platform')
return queryset
class GatheredAccountActionSerializer(GatheredAccountSerializer):
class Meta(GatheredAccountSerializer.Meta):
read_only_fields = list(set(GatheredAccountSerializer.Meta.read_only_fields) - {'status'})

Loading…
Cancel
Save