From eb901b29460a4987f37abd830f4960639dfa6908 Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Mon, 2 Dec 2024 19:09:16 +0800 Subject: [PATCH] perf: Change secret report --- .../accounts/api/automations/change_secret.py | 1 + .../automations/change_secret/manager.py | 41 ++-- apps/accounts/notifications.py | 24 +-- .../accounts/change_secret_report.html | 134 ++++++++++++ .../accounts/check_account_report.html | 130 ++++++------ .../accounts/gather_account_report.html | 190 +++++++++--------- 6 files changed, 332 insertions(+), 188 deletions(-) create mode 100644 apps/accounts/templates/accounts/change_secret_report.html diff --git a/apps/accounts/api/automations/change_secret.py b/apps/accounts/api/automations/change_secret.py index 7f2ca1979..8aa2d3f94 100644 --- a/apps/accounts/api/automations/change_secret.py +++ b/apps/accounts/api/automations/change_secret.py @@ -125,6 +125,7 @@ class ChangSecretExecutionViewSet(AutomationExecutionViewSet): ("list", "accounts.view_changesecretexecution"), ("retrieve", "accounts.view_changesecretexecution"), ("create", "accounts.add_changesecretexecution"), + ("report", "accounts.view_changesecretexecution"), ) tp = AutomationTypes.change_secret diff --git a/apps/accounts/automations/change_secret/manager.py b/apps/accounts/automations/change_secret/manager.py index 159128163..90abb15af 100644 --- a/apps/accounts/automations/change_secret/manager.py +++ b/apps/accounts/automations/change_secret/manager.py @@ -11,7 +11,7 @@ from accounts.const import ( AutomationTypes, SecretType, SSHKeyStrategy, SecretStrategy, ChangeSecretRecordStatusChoice ) from accounts.models import ChangeSecretRecord, BaseAccountQuerySet -from accounts.notifications import ChangeSecretExecutionTaskMsg, ChangeSecretFailedMsg +from accounts.notifications import ChangeSecretExecutionTaskMsg, ChangeSecretReportMsg from accounts.serializers import ChangeSecretRecordBackUpSerializer from assets.const import HostTypes from common.db.utils import safe_db_connection @@ -183,6 +183,14 @@ class ChangeSecretManager(AccountBasePlaybookManager): with safe_db_connection(): recorder.save(update_fields=['status', 'date_finished']) account.save(update_fields=['secret', 'version', 'date_updated']) + self.summary['ok_accounts'] += 1 + self.result['ok_accounts'].append( + { + "asset": str(account.asset), + "username": account.username, + } + ) + super().on_host_success(host, result) def on_host_error(self, host, error, result): recorder = self.name_recorder_mapper.get(host) @@ -195,9 +203,14 @@ class ChangeSecretManager(AccountBasePlaybookManager): recorder.save() except Exception as e: print(f"\033[31m Save {host} recorder error: {e} \033[0m\n") - - def on_runner_failed(self, runner, e, **kwargs): - logger.error("Account error: ", e) + self.summary['fail_accounts'] += 1 + self.result['fail_accounts'].append( + { + "asset": str(recorder.asset), + "username": recorder.account.username, + } + ) + super().on_host_success(host, result) def check_secret(self): if self.secret_strategy == SecretStrategy.custom \ @@ -236,24 +249,13 @@ class ChangeSecretManager(AccountBasePlaybookManager): if self.record_map: return - failed_recorders = [ - r for r in recorders - if r.status == ChangeSecretRecordStatusChoice.failed.value - ] - recipients = self.execution.recipients if not recipients: return - if failed_recorders: - name = self.execution.snapshot.get('name') - execution_id = str(self.execution.id) - _ids = [r.id for r in failed_recorders] - asset_account_errors = ChangeSecretRecord.objects.filter( - id__in=_ids).values_list('asset__name', 'account__username', 'error') - - for user in recipients: - ChangeSecretFailedMsg(name, execution_id, user, asset_account_errors).publish() + context = self.get_report_context() + for user in recipients: + ChangeSecretReportMsg(user, context).publish() if not recorders: return @@ -295,3 +297,6 @@ class ChangeSecretManager(AccountBasePlaybookManager): ws.write_string(row_index, col_index, col_data) wb.close() return True + + def get_report_template(self): + return "accounts/change_secret_report.html" diff --git a/apps/accounts/notifications.py b/apps/accounts/notifications.py index e981443a0..75697a8bc 100644 --- a/apps/accounts/notifications.py +++ b/apps/accounts/notifications.py @@ -1,5 +1,6 @@ from django.template.loader import render_to_string from django.utils.translation import gettext_lazy as _ +from premailer import transform from accounts.models import ChangeSecretRecord from common.tasks import send_mail_attachment_async, upload_backup_to_obj_storage @@ -101,24 +102,19 @@ class GatherAccountChangeMsg(UserMessage): return cls(user, {}) -class ChangeSecretFailedMsg(UserMessage): +class ChangeSecretReportMsg(UserMessage): subject = _('Change secret or push account failed information') - def __init__(self, name, execution_id, user, asset_account_errors: list): - self.name = name - self.execution_id = execution_id - self.asset_account_errors = asset_account_errors + def __init__(self, user, context: dict): + self.context = context super().__init__(user) def get_html_msg(self) -> dict: - context = { - 'name': self.name, - 'recipient': self.user, - 'execution_id': self.execution_id, - 'asset_account_errors': self.asset_account_errors - } - message = render_to_string('accounts/change_secret_failed_info.html', context) - + report = render_to_string( + 'accounts/change_secret_report.html', + self.context + ) + message = transform(report) return { 'subject': str(self.subject), 'message': message @@ -130,4 +126,4 @@ class ChangeSecretFailedMsg(UserMessage): user = User.objects.first() record = ChangeSecretRecord.objects.first() execution_id = str(record.execution_id) - return cls(name, execution_id, user, []) + return cls(user, {}) diff --git a/apps/accounts/templates/accounts/change_secret_report.html b/apps/accounts/templates/accounts/change_secret_report.html new file mode 100644 index 000000000..5459d23d6 --- /dev/null +++ b/apps/accounts/templates/accounts/change_secret_report.html @@ -0,0 +1,134 @@ +{% load i18n %} + +
+

{% trans 'The following is a summary of account change secret tasks, please review and handle them' %}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
任务汇总:
{% trans 'Task name' %}:{{ execution.automation.name }}
{% trans 'Date start' %}:{{ execution.date_start | date:"Y/m/d H:i:s" }}
{% trans 'Date end' %}:{{ execution.date_finished | date:"Y/m/d H:i:s" }}
{% trans 'Time using' %}:{{ execution.duration }}s
{% trans 'Assets count' %}:{{ summary.total_assets }}
{% trans 'Asset success count' %}:{{ summary.ok_assets }}
{% trans 'Asset failed count' %}:{{ summary.fail_assets }}
{% trans 'Asset not support count' %}:{{ summary.error_assets }}
+
+ +
+ {% if summary.ok_accounts %} +

{% trans 'Success accounts' %}: {{ summary.ok_accounts }}

+ + + + + + + + + + + {% for account in result.ok_accounts %} + + + + + + {% endfor %} + +
{% trans 'No.' %}{% trans 'Asset' %}{% trans 'Username' %}
{{ forloop.counter }}{{ account.asset }}{{ account.username }}
+ {% endif %} +
+
+ {% if summary.lost_accounts %} +

{% trans 'Failed accounts' %}: {{ summary.fail_accounts }}

+ + + + + + + + + + + {% for account in result.fail_accounts %} + + + + + + {% endfor %} + +
{% trans 'No.' %}{% trans 'Asset' %}{% trans 'Username' %}
{{ forloop.counter }}{{ account.asset }}{{ account.username }}
+ {% endif %} +
+ + diff --git a/apps/accounts/templates/accounts/check_account_report.html b/apps/accounts/templates/accounts/check_account_report.html index bf2e99c10..58ad6e906 100644 --- a/apps/accounts/templates/accounts/check_account_report.html +++ b/apps/accounts/templates/accounts/check_account_report.html @@ -3,74 +3,88 @@

{% trans 'The following is a summary of the account check tasks. Please review and handle them' %}

+ - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
任务汇总:
任务汇总:
{% trans 'Task name' %}: {{ execution.automation.name }}
{% trans 'Date start' %}: {{ execution.date_start }}
{% trans 'Date end' %}: {{ execution.date_finished }}
{% trans 'Time using' %}: {{ execution.duration }}s
{% trans 'Assets count' %}: {{ summary.assets }}
{% trans 'Account count' %}: {{ summary.accounts }}
{% trans 'Week password count' %}: {{ summary.weak_password }}
{% trans 'Ok count' %}: {{ summary.ok }}
{% trans 'No password count' %}: {{ summary.no_secret }}
{% trans 'Task name' %}:{{ execution.automation.name }}
{% trans 'Date start' %}:{{ execution.date_start | date:"Y/m/d H:i:s" }}
{% trans 'Date end' %}:{{ execution.date_finished | date:"Y/m/d H:i:s" }}
{% trans 'Time using' %}:{{ execution.duration }}s
{% trans 'Assets count' %}:{{ summary.assets }}
{% trans 'Asset success count' %}:{{ summary.ok_assets }}
{% trans 'Asset failed count' %}:{{ summary.fail_assets }}
{% trans 'Asset not support count' %}:{{ summary.error_assets }}
{% trans 'Account count' %}:{{ summary.accounts }}
{% trans 'Ok count' %}:{{ summary.ok }}
{% trans 'No password count' %}:{{ summary.no_secret }}
-

{% trans 'Account check details' %}:

- - - - - - - - - - - {% for account in result.weak_password %} + {% if summary.weak_password %} +

{% trans 'Week password' %}: {{ summary.weak_password }}

+

{% trans 'Account check details' %}:

+
{% trans 'No.' %}{% trans 'Asset' %}{% trans 'Username' %}{% trans 'Result' %}
+ + - - - - + + + + - {% endfor %} - -
{{ forloop.counter }}{{ account.asset }}{{ account.username }}{% trans 'Week password' %}{% trans 'No.' %}{% trans 'Asset' %}{% trans 'Username' %}{% trans 'Result' %}
+ + + {% for account in result.weak_password %} + + {{ forloop.counter }} + {{ account.asset }} + {{ account.username }} + {% trans 'Week password' %} + + {% endfor %} + + + {% endif %}