diff --git a/dokogen/dictionaries/org_measures.json b/dokogen/dictionaries/org_measures.json index a5a5b2e..6a69804 100644 --- a/dokogen/dictionaries/org_measures.json +++ b/dokogen/dictionaries/org_measures.json @@ -1,9 +1,17 @@ [ - "Установление контролируемой зоны", - "Контроль физического доступа к объекту", - "Разработка документов (регламентов, инструкций, руководств) по обеспечению безопасности объекта", - "Назначение ответственных за обеспечение безопасности объекта", - "Обучение и инструктаж персонала", - "Регламентация действий при компьютерных инцидентах", - "Утверждение перечня лиц, имеющих доступ к объекту" -] + "Установлены границы контролируемой зоны.", + "Физическая охрана периметра обеспечена бетонным забором с колючей проволокой, исключающим прямой доступ к зданиям, и турникетом на проходной; въезд и вход осуществляются по пропускам с применением СКУД, ведется учет посетителей.", + "Имеется система видеонаблюдения.", + "Здания не имеют окон, выходящих во вне, входная группа оснащена металлической дверью.", + "Установлены охранно-пожарная сигнализация и тревожная кнопка.", + "Исключена возможность неконтролируемого пребывания посторонних лиц в помещениях, где ведется работа с объектами критической информационной инфраструктуры.", + "Назначены: ответственный за организацию обеспечения безопасности объектов критической информационной инфраструктуры, администратор и администратор безопасности объектов критической информационной инфраструктуры, утверждены инструкции, регламентирующие работу с данными и объектами критической информационной инфраструктуры.", + "Осуществляется внутренний контроль соответствия обеспечения безопасности объектов критической информационной инфраструктуры установленным требованиям.", + "Работники, непосредственно осуществляющие работу с объектами критической информационной инфраструктуры, ознакомлены с положениями законодательства Российской Федерации об объектах критической информационной инфраструктуры, документами, определяющими политику организации в отношении работы с объектами критической информационной инфраструктуры.", + "Обеспечивается учет машинных носителей объектов критической информационной инфраструктуры.", + "Обеспечивается резервирование и восстановление данных, модифицированных или уничтоженных вследствие несанкционированного доступа к ним.", + "Разработаны правила доступа к данным, обрабатываемым в объектах критической информационной инфраструктуры.", + "Определён перечень сотрудников, осуществляющих работу с объектами критической информационной инфраструктуры.", + "Ведётся учёт всех защищаемых носителей информации с помощью их маркировки и занесения учетных данных в журнал учета с отметкой об их выдаче (приеме).", + "Обеспечено раздельное хранение материальных носителей, обработка которых осуществляется в различных целях." +] \ No newline at end of file diff --git a/dokogen/import_settings.json b/dokogen/import_settings.json index bde1378..10643dc 100644 --- a/dokogen/import_settings.json +++ b/dokogen/import_settings.json @@ -7,48 +7,317 @@ ], "value_column": 1, "fields": [ - {"name": "Полное наименование организации", "var": "fullName", "cell": "", "keywords": "полное наименование организации"}, - {"name": "Сокращённое наименование организации", "var": "shortName", "cell": "", "keywords": "сокращенное наименование организации"}, - {"name": "Юридический адрес", "var": "addressLegal", "cell": "", "keywords": "адрес организации \\(юридический\\)"}, - {"name": "Фактический адрес", "var": "addressActual", "cell": "", "keywords": "адрес организации \\(фактический\\)"}, - {"name": "Электронная почта", "var": "email", "cell": "", "keywords": "электронная почта"}, - {"name": "Телефон", "var": "phone", "cell": "", "keywords": "телефон"}, - {"name": "ИНН", "var": "inn", "cell": "", "keywords": "инн"}, - {"name": "ОГРН", "var": "ogrn", "cell": "", "keywords": "огрн"}, - {"name": "Дата получения ОГРН", "var": "ogrnDate", "cell": "", "keywords": "дата получения огрн|дата.*огрн"}, - {"name": "КПП", "var": "kpp", "cell": "", "keywords": "кпп"}, - {"name": "Основной ОКВЭД", "var": "okved", "cell": "", "keywords": "основной оквэд"}, - {"name": "Дополнительные ОКВЭД", "var": "okvedExtra", "cell": "", "keywords": "дополнительные оквэд"}, - {"name": "Должность руководителя", "var": "chiefPosition", "cell": "", "keywords": "должность руководителя"}, - {"name": "ФИО руководителя", "var": "chiefFio", "cell": "", "keywords": "фио руководителя"}, - {"name": "Должность ответственного лица (безопасность ЗОКИИ)", "var": "responsiblePosition", "cell": "", "keywords": "должность ответственного лица"}, - {"name": "ФИО ответственного лица (безопасность ЗОКИИ)", "var": "responsibleFio", "cell": "", "keywords": "фио ответственного лица"}, - {"name": "Подразделение по безопасности ОКИИ", "var": "ispdnDepartment", "cell": "", "keywords": "структур.*подраздел"}, - {"name": "Рабочий телефон ответственного", "var": "ispdnPhone", "cell": "", "keywords": "рабочий телефон ответственного|мобильный телефон ответственного"}, - {"name": "Электронная почта ответственного", "var": "ispdnEmail", "cell": "", "keywords": "электронная почта ответственного"}, - {"name": "Должность специалиста по ЗИ/администратора", "var": "administratorPosition", "cell": "", "keywords": "должность специалиста по защите информации|должность.*администрат"}, - {"name": "ФИО специалиста по ЗИ/администратора", "var": "administratorFio", "cell": "", "keywords": "фио специалиста по защите информации|фио.*администрат"}, - {"name": "Право владения зданием", "var": "buildingRight", "cell": "", "keywords": "право владения зданием"}, - {"name": "Сумма прибыли за год", "var": "profit", "cell": "", "keywords": "сумма прибыли"}, - {"name": "Сумма налога с прибыли", "var": "profitTax", "cell": "", "keywords": "сумма налога с прибыли"}, - {"name": "Доменное имя и внешний IP", "var": "domainName", "cell": "", "keywords": "доменное имя и внешний сетевой адрес"}, - {"name": "Сайт организации", "var": "site_name", "cell": "", "keywords": "сайт организации"}, - {"name": "Должность ответственного за сайт", "var": "site_responsible_position", "cell": "", "keywords": "должность ответственного за сайт"}, - {"name": "ФИО ответственного за сайт", "var": "site_responsible_fio", "cell": "", "keywords": "фио ответственного за сайт"}, - {"name": "Разработчик сайта", "var": "site_service_provider", "cell": "", "keywords": "организации, которая разрабатывала и размещала корпоративный сайт"}, - {"name": "ИНН разработчика сайта", "var": "site_service_provider_inn", "cell": "", "keywords": "инн организации, которая разрабатывала"}, - {"name": "Размещение сайта", "var": "site_hosting", "cell": "", "keywords": "размещение сайта"}, - {"name": "Адрес расположения серверов", "var": "site_hosting_address", "cell": "", "keywords": "адрес расположения серверов"}, - {"name": "Облачная платформа", "var": "cloud_platform", "cell": "", "keywords": "облачную платформу"}, - {"name": "Аренда выделенного сервера", "var": "cloud_dedicated_server", "cell": "", "keywords": "выделенный сервер"}, - {"name": "Аренда виртуального ЦОД", "var": "cloud_vdc", "cell": "", "keywords": "виртуальный дата-центр"}, - {"name": "Серверы в дата-центре", "var": "cloud_datacenter", "cell": "", "keywords": "сервера в дата-центре"}, - {"name": "Средства контейнеризации", "var": "cloud_container", "cell": "", "keywords": "контейнеризации"}, - {"name": "Собственная серверная (ЦОД)", "var": "cloud_own_server", "cell": "", "keywords": "собственная серверная"}, - {"name": "Общее количество компьютеров", "var": "computers_total", "cell": "", "keywords": "общее количество компьютеров"}, - {"name": "Компьютеры, подключённые к объектам КИИ", "var": "computers_kii", "cell": "", "keywords": "компьютеров подключенных к объектам кии"}, - {"name": "Центр мониторинга", "var": "monitoring_center", "cell": "", "keywords": "к какому центру подключены"}, - {"name": "Детали подключения к центру мониторинга", "var": "monitoring_details", "cell": "", "keywords": "детали подключения"}, - {"name": "Дополнительная информация", "var": "additionalInfo", "cell": "", "keywords": "дополнительная информация"} + { + "name": "Полное наименование организации", + "var": "fullName", + "cell": "", + "keywords": "полное наименование организации" + }, + { + "name": "Сокращённое наименование организации", + "var": "shortName", + "cell": "", + "keywords": "сокращенное наименование организации" + }, + { + "name": "Юридический адрес", + "var": "addressLegal", + "cell": "", + "keywords": "адрес организации \\(юридический\\)" + }, + { + "name": "Фактический адрес", + "var": "addressActual", + "cell": "", + "keywords": "адрес организации \\(фактический\\)" + }, + { + "name": "Электронная почта", + "var": "email", + "cell": "", + "keywords": "электронная почта" + }, + { + "name": "Телефон", + "var": "phone", + "cell": "", + "keywords": "телефон" + }, + { + "name": "ИНН", + "var": "inn", + "cell": "", + "keywords": "инн" + }, + { + "name": "ОГРН", + "var": "ogrn", + "cell": "", + "keywords": "огрн" + }, + { + "name": "Дата получения ОГРН", + "var": "ogrnDate", + "cell": "", + "keywords": "дата получения огрн|дата.*огрн" + }, + { + "name": "КПП", + "var": "kpp", + "cell": "", + "keywords": "кпп" + }, + { + "name": "Основной ОКВЭД", + "var": "okved", + "cell": "", + "keywords": "основной оквэд" + }, + { + "name": "Дополнительные ОКВЭД", + "var": "okvedExtra", + "cell": "", + "keywords": "дополнительные оквэд" + }, + { + "name": "Должность руководителя", + "var": "chiefPosition", + "cell": "", + "keywords": "должность руководителя" + }, + { + "name": "ФИО руководителя", + "var": "chiefFio", + "cell": "", + "keywords": "фио руководителя" + }, + { + "name": "Должность ответственного лица (безопасность ЗОКИИ)", + "var": "responsiblePosition", + "cell": "", + "keywords": "должность ответственного лица" + }, + { + "name": "ФИО ответственного лица (безопасность ЗОКИИ)", + "var": "responsibleFio", + "cell": "", + "keywords": "фио ответственного лица" + }, + { + "name": "Подразделение по безопасности ОКИИ", + "var": "ispdnDepartment", + "cell": "", + "keywords": "структур.*подраздел" + }, + { + "name": "Рабочий телефон ответственного", + "var": "ispdnPhone", + "cell": "", + "keywords": "рабочий телефон ответственного|мобильный телефон ответственного" + }, + { + "name": "Электронная почта ответственного", + "var": "ispdnEmail", + "cell": "", + "keywords": "электронная почта ответственного" + }, + { + "name": "Должность специалиста по ЗИ/администратора", + "var": "administratorPosition", + "cell": "", + "keywords": "должность специалиста по защите информации|должность.*администрат" + }, + { + "name": "ФИО специалиста по ЗИ/администратора", + "var": "administratorFio", + "cell": "", + "keywords": "фио специалиста по защите информации|фио.*администрат" + }, + { + "name": "Право владения зданием", + "var": "buildingRight", + "cell": "", + "keywords": "право владения зданием" + }, + { + "name": "Сумма прибыли за год", + "var": "profit", + "cell": "", + "keywords": "сумма прибыли" + }, + { + "name": "Сумма налога с прибыли", + "var": "profitTax", + "cell": "", + "keywords": "сумма налога с прибыли" + }, + { + "name": "Доменное имя и внешний IP", + "var": "domainName", + "cell": "", + "keywords": "доменное имя и внешний сетевой адрес" + }, + { + "name": "Сайт организации", + "var": "site_name", + "cell": "", + "keywords": "сайт организации" + }, + { + "name": "Должность ответственного за сайт", + "var": "site_responsible_position", + "cell": "", + "keywords": "должность ответственного за сайт" + }, + { + "name": "ФИО ответственного за сайт", + "var": "site_responsible_fio", + "cell": "", + "keywords": "фио ответственного за сайт" + }, + { + "name": "Разработчик сайта", + "var": "site_service_provider", + "cell": "", + "keywords": "организации, которая разрабатывала и размещала корпоративный сайт" + }, + { + "name": "ИНН разработчика сайта", + "var": "site_service_provider_inn", + "cell": "", + "keywords": "инн организации, которая разрабатывала" + }, + { + "name": "Размещение сайта", + "var": "site_hosting", + "cell": "", + "keywords": "размещение сайта" + }, + { + "name": "Адрес расположения серверов", + "var": "site_hosting_address", + "cell": "", + "keywords": "адрес расположения серверов" + }, + { + "name": "Облачная платформа", + "var": "cloud_platform", + "cell": "", + "keywords": "облачную платформу" + }, + { + "name": "Аренда выделенного сервера", + "var": "cloud_dedicated_server", + "cell": "", + "keywords": "выделенный сервер" + }, + { + "name": "Аренда виртуального ЦОД", + "var": "cloud_vdc", + "cell": "", + "keywords": "виртуальный дата-центр" + }, + { + "name": "Серверы в дата-центре", + "var": "cloud_datacenter", + "cell": "", + "keywords": "сервера в дата-центре" + }, + { + "name": "Средства контейнеризации", + "var": "cloud_container", + "cell": "", + "keywords": "контейнеризации" + }, + { + "name": "Собственная серверная (ЦОД)", + "var": "cloud_own_server", + "cell": "", + "keywords": "собственная серверная" + }, + { + "name": "Общее количество компьютеров", + "var": "computers_total", + "cell": "", + "keywords": "общее количество компьютеров" + }, + { + "name": "Компьютеры, подключённые к объектам КИИ", + "var": "computers_kii", + "cell": "", + "keywords": "компьютеров подключенных к объектам кии" + }, + { + "name": "Центр мониторинга", + "var": "monitoring_center", + "cell": "", + "keywords": "к какому центру подключены" + }, + { + "name": "Детали подключения к центру мониторинга", + "var": "monitoring_details", + "cell": "", + "keywords": "детали подключения" + }, + { + "name": "Дополнительная информация", + "var": "additionalInfo", + "cell": "", + "keywords": "дополнительная информация" + }, + { + "name": "Физическая охрана (ЧОП, сторожа, охранники)", + "var": "physicalGuard", + "cell": "", + "keywords": "физическая охрана" + }, + { + "name": "Пожарная сигнализация", + "var": "physicalFireAlarm", + "cell": "", + "keywords": "пожарная сигнализация" + }, + { + "name": "Тревожная кнопка", + "var": "physicalPanicButton", + "cell": "", + "keywords": "тревожная кнопка" + }, + { + "name": "Решётки на окнах", + "var": "physicalBars", + "cell": "", + "keywords": "решетки на окнах" + }, + { + "name": "Металлические двери", + "var": "physicalMetalDoors", + "cell": "", + "keywords": "металлические двери" + }, + { + "name": "Система видеонаблюдения", + "var": "physicalVideoSurveillance", + "cell": "", + "keywords": "система видеонаблюдения" + }, + { + "name": "Видеодомофон", + "var": "physicalVideoIntercom", + "cell": "", + "keywords": "видеодомофон" + }, + { + "name": "Турникет на входе", + "var": "physicalTurnstile", + "cell": "", + "keywords": "турникет на входе" + }, + { + "name": "Журнал учёта посетителей", + "var": "physicalVisitorLog", + "cell": "", + "keywords": "журнал учета посетителей|журнал учёта посетителей" + } ] -} +} \ No newline at end of file diff --git a/dokogen/importer.py b/dokogen/importer.py index 9449319..8199b59 100644 --- a/dokogen/importer.py +++ b/dokogen/importer.py @@ -174,6 +174,21 @@ def import_187fz(filepath: str, log_fn: Optional[Callable] = None, settings_path finally: wb.close() + # Ответы раздела «Физическая безопасность» (да/нет) — собираем в словарь, + # чтобы текст организационных мер генерировался с учётом реальных средств. + ps_keys = [ + 'physicalGuard', 'physicalFireAlarm', 'physicalPanicButton', + 'physicalBars', 'physicalMetalDoors', 'physicalVideoSurveillance', + 'physicalVideoIntercom', 'physicalTurnstile', 'physicalVisitorLog', + ] + ps = {} + for k in ps_keys: + v = str(data.get(k) or '').strip() + if v: + ps[k] = v + if ps: + data['physicalSecurity'] = ps + # Копирование полей ИСПДн в админа, если админ не заполнен for src, dst in [('ispdnFio', 'administratorFio'), ('ispdnFio', 'adminFio'), ('ispdnPosition', 'administratorPosition'), ('ispdnPosition', 'adminPosition'), diff --git a/dokogen/models.py b/dokogen/models.py index 19bee90..fb2ac2e 100644 --- a/dokogen/models.py +++ b/dokogen/models.py @@ -152,6 +152,11 @@ class Company: # Наименование структурного подразделения по безопасности security_department: str = "" + # Ответы раздела «Физическая безопасность» опросника (да/нет): + # охрана, пожарная сигнализация, тревожная кнопка, решётки, металлические двери, + # видеонаблюдение, видеодомофон, турникет, журнал посетителей. + physical_security: Dict[str, str] = field(default_factory=dict) + def update_declensions(self, inflect_func): """Обновить склонения полного названия""" if self.full_name: diff --git a/dokogen/ui.py b/dokogen/ui.py index f918fcb..36a79d1 100644 --- a/dokogen/ui.py +++ b/dokogen/ui.py @@ -4446,6 +4446,10 @@ class DokoGenApp: # Автоопределение города из адреса после импорта self._on_address_changed() + # Ответы по физической безопасности (для автогенерации орг. мер) + if data.get('physicalSecurity'): + self.model.physical_security = dict(data['physicalSecurity']) + # Должностные лица (маппинг) officials_map = { 'chief_position': 'chiefPosition', diff --git a/dokogen/variables.py b/dokogen/variables.py index 8d4f174..e0b89da 100644 --- a/dokogen/variables.py +++ b/dokogen/variables.py @@ -357,7 +357,10 @@ def _build_loop_data(company: Company, is_list: List) -> Dict[str, List[Dict]]: 'incidents': getattr(isys, 'incidents', '') or '—', 'criteria_values': getattr(isys, 'criteria_values', '') or '—', 'criteria_justification': getattr(isys, 'criteria_justification', '') or '—', - 'org_measures': getattr(isys, 'org_measures', '') or '—', + # Орг. меры: если не заполнены вручную — автогенерация по опроснику + # (с учётом ответов раздела «Физическая безопасность»). + 'org_measures': (getattr(isys, 'org_measures', '') or '') + or _build_org_measures_text(company, isys), 'tech_measures': getattr(isys, 'tech_measures', '') or '—', }) loops['information_systems'] = items @@ -505,6 +508,56 @@ def _calc_criterion_8_9(company, isys, num): return text, cat +def _build_org_measures_text(company, isys=None): + """Формирует текст организационных мер из словаря org_measures.json + с учётом ответов раздела «Физическая безопасность» опросника. + + Если в опроснике указано «нет» (охрана, сигнализация, тревожная кнопка, + видеонаблюдение, металлические двери и т.п.) — соответствующие пункты + из текста убираются. Пункты, не привязанные к средствам, остаются всегда. + """ + import os as _os + items = _load_json('org_measures.json') + if not isinstance(items, list): + items = [] + ps = getattr(company, 'physical_security', None) or {} + + def _no(*keys): + """True, если хотя бы по одному ключу явно указано «нет»/«не имеется».""" + for k in keys: + v = str(ps.get(k) or '').strip().lower() + if v in ('нет', 'не имеется', 'нет,', '0', 'false'): + return True + return False + + rules = [ + # (подстрока пункта, ключи physical_security, при которых пункт УБИРАЕМ) + ('Физическая охрана периметра', ('physicalGuard', 'physicalTurnstile', 'physicalVisitorLog')), + ('Имеется система видеонаблюдения', ('physicalVideoSurveillance',)), + ('Здания не имеют окон', ('physicalMetalDoors',)), + ('охранно-пожарная сигнализация и тревожная кнопка', ('physicalFireAlarm', 'physicalPanicButton')), + ('охранно-пожарная сигнализация', ('physicalFireAlarm',)), + ('тревожная кнопка', ('physicalPanicButton',)), + ('турникетом на проходной', ('physicalTurnstile',)), + ('СКУД', ('physicalTurnstile',)), + ('учет посетителей', ('physicalVisitorLog',)), + ] + + out = [] + for line in items: + line = str(line).strip() + if not line: + continue + drop = False + for sub, keys in rules: + if sub in line and _no(*keys): + drop = True + break + if not drop: + out.append(line) + return '\n'.join(out) if out else '—' + + def _build_categorization_indicators(company, is_list): """Строки таблицы показателей критериев значимости для шаблона «Сведения о результатах категорирования» (цикл categorization_indicators).