mirror of https://github.com/jumpserver/jumpserver
perf: update pam
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…
Reference in New Issue