feat: автозаполнение вкладки «Безопасность» по данным объекта

Новая кнопка « Автозаполнить» в панели действий — заполняет пустые поля
логически, без выдумок:
- категория нарушителя: есть интернет → внешний, нет → внутренний
- уровень возможностей: Н1 (внутренний) / Н2 (внешний)
- виды нарушителей: по категории из словаря attacker_types.json
- угрозы: подбор программой (скоринг по характеристикам объекта)
- инциденты: выводятся из подобранных угроз по ключевым словам
- орг. меры: базовый набор (контролируемая зона, доступ, документы,
  ответственные, обучение, инциденты, перечень лиц)
- тех. меры: базовые + доп. по средствам защиты объекта (СЗИ:
  межсетевой экран → МЭ, антивирус, СОВ, СКЗИ, виртуализация)
Незаполненное пользователем не перезаписывает.
This commit is contained in:
2026-08-04 20:35:29 +04:00
parent 1ef8485b13
commit 68caaf9b63
2 changed files with 196 additions and 0 deletions
+59
View File
@@ -980,6 +980,8 @@ class DokoGenApp:
# --- Панель действий (сверху, всегда видна) ---
sec_actions = ttk.Frame(sec_frame)
sec_actions.pack(fill=tk.X, pady=(0, 6))
ttk.Button(sec_actions, text="⚡ Автозаполнить",
command=self._auto_fill_security_click).pack(side=tk.LEFT, padx=2)
ttk.Button(sec_actions, text="⬇️ Загрузить угрозы ФСТЭК",
command=self._download_fstec_threats).pack(side=tk.LEFT, padx=2)
ttk.Button(sec_actions, text="⚙️ Подобрать угрозы (программа)",
@@ -2047,6 +2049,63 @@ class DokoGenApp:
text="⚠ Список угроз ещё не скачан — нажмите «⬇️ Загрузить угрозы ФСТЭК»",
foreground='#c62828')
def _auto_fill_security_click(self):
"""⚡ Автозаполнение вкладки «Безопасность» по данным объекта (логическое).
Заполняет только пустые поля:
категория/уровень/виды нарушителя — по интернету и типу объекта;
угрозы — подбор программой (скоринг);
инциденты — из подобранных угроз;
орг./тех. меры — базовый набор + по средствам защиты объекта.
"""
if self._current_is_idx is None:
messagebox.showinfo("Автозаполнение", "Сначала выберите объект КИИ в списке слева")
return
self._collect_is()
isys = self.model.information_systems[self._current_is_idx]
try:
from .threat_rules import auto_fill_security, load_threats
threats_full = load_threats()
fill = auto_fill_security(isys, threats=threats_full)
except Exception as e:
messagebox.showerror("Ошибка", str(e))
return
if not fill:
messagebox.showinfo("Автозаполнение", "Все поля безопасности уже заполнены.")
return
# Применяем к виджетам
if 'attacker_category' in fill and hasattr(self, 'is_attacker_category_combo'):
self.is_attacker_category_combo.set(fill['attacker_category'])
if 'attacker_level' in fill and hasattr(self, 'is_attacker_level_combo'):
self.is_attacker_level_combo.set(fill['attacker_level'])
for key, attr in [('attacker_types', 'is_attacker_types_listbox'),
('threats', 'is_threats_listbox'),
('incidents', 'is_incidents_listbox'),
('org_measures', 'is_org_measures_listbox'),
('tech_measures', 'is_tech_measures_listbox')]:
if key in fill and hasattr(self, attr):
lb = getattr(self, attr)
lb.delete(0, tk.END)
for line in fill[key].split('\n'):
if line.strip():
lb.insert(tk.END, line.strip())
self._collect_is() # сохранить в модель
filled = ', '.join({
'attacker_category': 'нарушитель',
'attacker_level': 'уровень',
'attacker_types': 'виды нарушителя',
'threats': 'угрозы',
'incidents': 'инциденты',
'org_measures': 'орг. меры',
'tech_measures': 'тех. меры',
}.get(k, k) for k in fill)
self.log(f"⚡ Автозаполнение выполнено: {filled}")
messagebox.showinfo("Автозаполнение",
f"Заполнено: {filled}.\n\nНезаполненные поля (если есть) требуют ручного ввода "
f"или данных из опросника.")
def _suggest_threats_program_click(self):
"""Подобрать угрозы логикой программы по характеристикам объекта."""
if self._current_is_idx is None: