fix: аудит ветки source — критические и высокие замечания
- api_settings: убраны реальные API-ключи из кода (чтение из env/файла) — 1.1
- variables: {{is_security_requirements}} больше не подставляет всегда УЗ-4;
extended_fields/defence_level передаются в контекст — 1.2
- defence.py: эталонная таблица ПП-1119 (п.9-12), 48 комбинаций;
ui.py: авторасчёт УЗ переведён на неё (public больше не 'всегда 4',
спец/био/общедоступные/иные разделены) — 2.1
- generator: убран дубль хвоста параграфа в _highlight_unmatched — 2.2
- importer: категории ПДн взаимоисключающие ('иные' только если нет
спец/био); УЗ пересчитывается при импорте — 2.3
- import_settings(.py/.json): убран перехват 'администратора безопасности'
правилом ответственного за ПДн — 3.1
- variables: {{category}}/{{is.category}} резолвятся из personal_data_category — 3.2
- verify: ИИ-предложения ИНН/ОГРН/КПП валидируются контрольными суммами
перед применением — 3.3
- models: defence_level None вместо '' (не маскирует 'не рассчитано')
- .gitignore: api_settings.json/.env не попадают в git
- test_defence.py: юнит-тест всех 48 комбинаций таблицы УЗ
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""DokoGen — расчёт уровня защищённости ПДн по ПП РФ № 1119 от 01.11.2012.
|
||||
|
||||
Эталонная таблица (п. 9–12 ПП-1119), сверено с текстом постановления:
|
||||
|
||||
Специальные категории:
|
||||
- угрозы 1 типа → УЗ-1 (любое количество, п.9а)
|
||||
- угрозы 2 типа: >100к не-сотрудников → УЗ-1 (п.9б); сотрудники или ≤100к → УЗ-2 (п.10б)
|
||||
- угрозы 3 типа: >100к не-сотрудников → УЗ-2 (п.10е); сотрудники или ≤100к → УЗ-3 (п.11в)
|
||||
|
||||
Биометрические:
|
||||
- угрозы 1 типа → УЗ-1 (п.9а); угрозы 2 типа → УЗ-2 (п.10в); угрозы 3 типа → УЗ-3 (п.11г)
|
||||
(без разбивки по количеству)
|
||||
|
||||
Общедоступные:
|
||||
- угрозы 1 типа → УЗ-2 (п.10а)
|
||||
- угрозы 2 типа: >100к → УЗ-2 (п.10г); сотрудники или ≤100к → УЗ-3 (п.11а)
|
||||
- угрозы 3 типа → УЗ-4 (п.12а)
|
||||
|
||||
Иные категории:
|
||||
- угрозы 1 типа → УЗ-1 (п.9а)
|
||||
- угрозы 2 типа: >100к не-сотрудников → УЗ-2 (п.10д); сотрудники или ≤100к → УЗ-3 (п.11б)
|
||||
- угрозы 3 типа: >100к не-сотрудников → УЗ-3 (п.11д); сотрудники или ≤100к → УЗ-4 (п.12б)
|
||||
|
||||
Используется и в авторасчёте (ui.py), и при импорте (importer.py).
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
|
||||
|
||||
def calc_defence_level(
|
||||
categories: List[str],
|
||||
is_employees: bool,
|
||||
is_large: bool,
|
||||
threat_type: str,
|
||||
) -> int:
|
||||
"""Расчёт уровня защищённости ПДн (1–4) по ПП РФ № 1119.
|
||||
|
||||
categories — список категорий ПДн ('специальные', 'биометрические',
|
||||
'общедоступные', 'иные').
|
||||
is_employees — True, если обрабатываются ПДн только сотрудников оператора.
|
||||
is_large — True, если количество субъектов > 100 000.
|
||||
threat_type — тип актуальных угроз: '1', '2' или '3'.
|
||||
"""
|
||||
threat = str(threat_type or '3').strip()
|
||||
has = lambda *names: any(n in categories for n in names)
|
||||
|
||||
# Приоритет категорий: специальные > биометрические > общедоступные > иные
|
||||
if has('специальные'):
|
||||
return _special(threat, is_employees, is_large)
|
||||
if has('биометрические'):
|
||||
return _bio(threat)
|
||||
if has('общедоступные') and not has('иные'):
|
||||
return _public(threat, is_employees, is_large)
|
||||
return _other(threat, is_employees, is_large)
|
||||
|
||||
|
||||
def _special(threat: str, employees: bool, large: bool) -> int:
|
||||
if threat == '1':
|
||||
return 1
|
||||
if threat == '2':
|
||||
return 1 if (not employees and large) else 2
|
||||
# threat == '3'
|
||||
return 2 if (not employees and large) else 3
|
||||
|
||||
|
||||
def _bio(threat: str) -> int:
|
||||
return {'1': 1, '2': 2, '3': 3}.get(threat, 3)
|
||||
|
||||
|
||||
def _public(threat: str, employees: bool, large: bool) -> int:
|
||||
if threat == '1':
|
||||
return 2
|
||||
if threat == '2':
|
||||
return 2 if (not employees and large) else 3
|
||||
# threat == '3'
|
||||
return 4
|
||||
|
||||
|
||||
def _other(threat: str, employees: bool, large: bool) -> int:
|
||||
if threat == '1':
|
||||
return 1
|
||||
if threat == '2':
|
||||
return 2 if (not employees and large) else 3
|
||||
# threat == '3'
|
||||
return 3 if (not employees and large) else 4
|
||||
Reference in New Issue
Block a user