ОКВЭД: полный справочник ОКВЭД2 (2770 записей) в едином формате «код название», resolve_okved без дефиса, импорт доп. ОКВЭД без переносов; угрозы: умный подбор — исключение неиспользуемых технологий (виртуализация, облако, мобильные, АСУ ТП, грид, суперкомпьютер, большие данные, беспроводные сети, контейнеры, smart-карты, ИИ), базовые угрозы локальных сетей
This commit is contained in:
+2770
-267
File diff suppressed because it is too large
Load Diff
@@ -42,8 +42,26 @@ BASE_KEYWORDS = [
|
||||
'вредоносн', 'несанкционированн', 'утечк', 'перехват', 'модификац',
|
||||
'уничтожен', 'отказ в обслуживании', 'нсд', 'биос', 'пароль',
|
||||
'криптографическ', 'шифрован', 'аутентификац',
|
||||
# базовые угрозы локальных сетей / клиент-серверных архитектур
|
||||
'доступ', 'данн', 'систем', 'конфигурац', 'целостност', 'информац',
|
||||
'программн', 'пользовател', 'авторизац', 'сеанс', 'журнал', 'реестр',
|
||||
'файл', 'память', 'буфер', 'ресурс', 'сервер', 'клиент', 'учётн',
|
||||
'учетн', 'идентификац', 'привилег', 'средств', 'сетев', 'локальн',
|
||||
]
|
||||
|
||||
# Технологии, которые по умолчанию НЕ используются на объекте.
|
||||
# Если в характеристиках объекта есть явные упоминания — группа возвращается.
|
||||
TECH_GROUPS = {
|
||||
'виртуализац': ['виртуал', 'гипервизор', 'контейнер'],
|
||||
'облако': ['облачн', 'облак'],
|
||||
'мобильн': ['мобильн', 'смартфон', 'планшет'],
|
||||
'грид': ['грид', 'суперкомпьютер'],
|
||||
'большие данные': ['больших данных', 'хранилищ'],
|
||||
'беспроводн': ['беспроводн', 'wi-fi', 'wifi'],
|
||||
'smart-карты': ['smart-карт', 'смарт-карт'],
|
||||
'машинное обучение': ['машинного обучения', 'искусственного интеллекта', 'нейросет'],
|
||||
}
|
||||
|
||||
# Объект имеет подключение к сети Интернет / сеть электросвязи
|
||||
INTERNET_KEYWORDS = [
|
||||
'удалённ', 'удаленн', 'сетев', 'фишинг', 'ddos', 'отказ в обслуживании',
|
||||
@@ -153,6 +171,21 @@ def suggest_threats_program(isys, threats=None, limit=None):
|
||||
is_asu = _is_asu(isys)
|
||||
is_network = _is_network(isys)
|
||||
|
||||
# --- Технологии, которые явно НЕ используются на объекте ---
|
||||
# Если в характеристиках объекта (описание, архитектура, ПО, сфера) нет
|
||||
# упоминаний технологии — угрозы этой группы исключаем.
|
||||
tech_context = ' '.join([
|
||||
str(getattr(isys, 'description', '') or ''),
|
||||
str(getattr(isys, 'architecture', '') or ''),
|
||||
str(getattr(isys, 'hw_sw', '') or ''),
|
||||
str(getattr(isys, 'os_sw', '') or ''),
|
||||
str(getattr(isys, 'app_sw', '') or ''),
|
||||
str(getattr(isys, 'object_type', '') or ''),
|
||||
str(getattr(isys, 'sphere', '') or ''),
|
||||
str(getattr(isys, 'net_category', '') or ''),
|
||||
str(getattr(isys, 'typical_object', '') or ''),
|
||||
]).lower()
|
||||
|
||||
# --- Слова-исключения (если встретились в названии угрозы — она неактуальна) ---
|
||||
exclude = []
|
||||
|
||||
@@ -167,6 +200,19 @@ def suggest_threats_program(isys, threats=None, limit=None):
|
||||
if is_asu:
|
||||
# АСУ: нет BIOS/виртуализации/браузера в привычном понимании
|
||||
exclude += ['биос', 'грид', 'гипервизор', 'виртуальн', 'браузер']
|
||||
else:
|
||||
# Не АСУ — исключаем угрозы АСУ ТП / технологических процессов
|
||||
exclude += ['технологическ', 'датчик', 'исполнительн', 'асутп', 'scada',
|
||||
'промышленн', 'контроллер', 'числовым программным управлением',
|
||||
'программируемых логических']
|
||||
|
||||
# Технологии, не упомянутые в характеристиках объекта → исключаем
|
||||
for tech_name, kws in TECH_GROUPS.items():
|
||||
if any(kw in tech_context for kw in kws):
|
||||
continue # технология используется — угрозы оставляем
|
||||
# Технология не упомянута — исключаем её угрозы
|
||||
for kw in kws:
|
||||
exclude.append(kw)
|
||||
|
||||
if not is_network and not is_asu:
|
||||
# Обычная ИС: неактуальны чисто сетевые/телеком-угрозы без указания
|
||||
|
||||
+5
-1
@@ -4546,7 +4546,11 @@ class DokoGenApp:
|
||||
extra = data['okvedExtra']
|
||||
if isinstance(extra, str):
|
||||
import re as _re
|
||||
parts = [p.strip() for p in _re.split(r'[;,\n]+', extra) if p.strip()]
|
||||
# Перенос строки внутри одной записи («27.32.2 Производство\nсиловых кабелей»)
|
||||
# не должен создавать вторую запись — сначала склеиваем переносы в пробел,
|
||||
# затем режем только по запятой / точке с запятой.
|
||||
extra = _re.sub(r'\s*[\n\r]+\s*', ' ', extra)
|
||||
parts = [p.strip() for p in _re.split(r'[;]+|\s*,\s*', extra) if p.strip()]
|
||||
else:
|
||||
parts = [str(p).strip() for p in extra if str(p).strip()]
|
||||
for p in parts:
|
||||
|
||||
+16
-10
@@ -161,15 +161,20 @@ def normalize_address(text):
|
||||
|
||||
|
||||
def resolve_okved(code, dadata_token=None):
|
||||
"""Код ОКВЭД → «код - название».
|
||||
"""Код ОКВЭД → «код название» (без дефиса), например «27.32.2 Производство силовых кабелей».
|
||||
|
||||
Принимает и голый код («27.32.2»), и строку с названием
|
||||
(«27.32.2 - Производство силовых кабелей» / «27.32.2 Производство силовых кабелей»).
|
||||
1) Ищем в словаре dictionaries/okved.json (строки вида «27.32.2 Название»).
|
||||
2) Если не нашли — запрашиваем DaData suggest okved2 (если есть токен).
|
||||
3) Иначе возвращаем код как есть.
|
||||
3) Иначе возвращаем нормализованную строку «код название» как есть.
|
||||
"""
|
||||
code = (code or '').strip()
|
||||
if not code:
|
||||
return ''
|
||||
# Извлекаем код из входной строки: «27.32.2 - Производство силовых кабелей» → «27.32.2»
|
||||
m = re.match(r'^\s*(\d+(?:\.\d+)*)', code)
|
||||
code_only = m.group(1) if m else code.split()[0].rstrip('.')
|
||||
# 1) Словарь
|
||||
try:
|
||||
import os, json
|
||||
@@ -178,12 +183,8 @@ def resolve_okved(code, dadata_token=None):
|
||||
items = json.load(f)
|
||||
for item in items:
|
||||
item = str(item).strip()
|
||||
# совпадение по началу: «27.32.2» или «27.32.2 - ...» / «27.32.2 ...»
|
||||
if item.split()[0].rstrip('.') == code.rstrip('.'):
|
||||
# нормализуем: «код - название»
|
||||
rest = item[len(item.split()[0]):].strip().lstrip('- ').strip()
|
||||
if rest:
|
||||
return f"{code} - {rest}"
|
||||
# совпадение по коду: «27.32.2» или «27.32.2 Название»
|
||||
if item.split()[0].rstrip('.') == code_only.rstrip('.'):
|
||||
return item
|
||||
except Exception:
|
||||
pass
|
||||
@@ -191,7 +192,7 @@ def resolve_okved(code, dadata_token=None):
|
||||
if dadata_token:
|
||||
try:
|
||||
js, err = _http_json('https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/okved2',
|
||||
data={'query': code, 'count': 1},
|
||||
data={'query': code_only, 'count': 1},
|
||||
headers={'Content-Type': 'application/json',
|
||||
'Authorization': f'Token {dadata_token}'})
|
||||
if not err and js:
|
||||
@@ -200,7 +201,12 @@ def resolve_okved(code, dadata_token=None):
|
||||
return sugg[0]['value']
|
||||
except Exception:
|
||||
pass
|
||||
return code
|
||||
# 3) Нормализуем вход: «27.32.2 - Название» → «27.32.2 Название» (без дефиса)
|
||||
rest = code[len(m.group(1)):].strip() if m else ''
|
||||
rest = rest.lstrip('- ').strip()
|
||||
if rest:
|
||||
return f"{code_only} {rest}"
|
||||
return code_only
|
||||
|
||||
|
||||
def _fmt_date(value):
|
||||
|
||||
Reference in New Issue
Block a user