Аудитория: ИТ-администратор, интегратор при пилоте. Закрывает вопрос: №3 («как подключить наш KSC / нашу 1С, к чему цепляется коннектор?»). Сценарии: S3 — подключаем боевой KSC заказчика; S4 — добавляем новый тип источника.
Источник телеметрии подключается через один контракт — протокол Collector с единственным методом collect(tenant, since) → Iterable[TelemetryRecord]. На стенде источник читает CSV-выгрузку (fixture) — это «боевая сигнатура»: интерфейс ровно тот, что будет у реального коннектора. Чтобы подключить боевой KSC/1С/журналы, нужно реализовать тот же протокол и зарегистрировать его — приём, планировщик и статистика при этом не меняются. Сейчас поддержаны три типа источника: ksc_sql, odata_1c, syslog_evtx.
Весь контракт — один dataclass факта и один Protocol источника:
@dataclass(frozen=True)
class TelemetryRecord:
tabel_no: str # СЫРОЙ табельный — обезличивается на приёме, в БД не хранится
sys_code: str # код системы источника → приём резолвит в sys_id
activity_date: str # ISO-дата YYYY-MM-DD
tx_count: int # число транзакций за день
session_minutes: int # минуты активной сессии за день
raw_product: str = "" # СЫРОЕ имя ПО (для Recognition Parser, если sys_code пуст)
class Collector(Protocol):
source_type: str
def collect(self, tenant_id, since=None) -> Iterable[TelemetryRecord]: ...Что важно понимать администратору:
- Коннектор отдаёт сырьё (табельный, сырое имя ПО) — но не хранит его и **не
обезличивает**: обезличивание делает приём (см. статью 02).
- Коннектор не вычисляет «активный день»: он отдаёт
session_minutes, а приём сам решает
is_active_day по порогу. Источник поставляет факты, а не выводы.
since(необязательный) — отдавать записи начиная с даты; так делается инкрементальный сбор.
Реестр коннекторов (_REGISTRY) сопоставляет тип источника его реализации:
source_type | Что это в бою | Что отдаёт |
|---|---|---|
ksc_sql | Выгрузка из Kaspersky Security Center (SQL-экспорт инвентаря/активности) | По-станционная активность ПО |
odata_1c | 1С через интерфейс OData | Сеансы/активность в конфигурациях 1С |
syslog_evtx | syslog / Windows Event Log (evtx) | Запуски процессов, сессии |
Все три обслуживаются одним классом FixtureFileCollector(source_type) — он читает CSV по типу источника. Тип только выбирает источник; формат TelemetryRecord для всех одинаков. Объединение всех источников арендатора = его полный набор фактов (метод сбора у каждой системы один, без двойного учёта).
Какой источник обслуживает какую систему — задаётся полем collect_method системы по правилу: odata → odata_1c, syslog/evtx_log → syslog_evtx, остальное → ksc_sql. То есть «1С собирается через OData, антивирус через KSC» — это свойство системы в реестре, а не отдельная настройка коннектора.
Замена fixture на реальный коннектор — это реализация интерфейса, без правок ядра:
- Написать класс с тем же протоколом, например:
class KscSqlCollector:
source_type = "ksc_sql"
def collect(self, tenant_id, since=None):
# подключиться к боевому KSC заказчика (его строка подключения — из env/конфига),
# выполнить выгрузку, отдать TelemetryRecord на каждую строку дневной активности.
...- Зарегистрировать его вместо fixture в
_REGISTRY['ksc_sql'](точка подмены —get_collector). - Всё. Приём (
ingest_activity), планировщик, прогоны (экран/collectors),
обезличивание, идемпотентность — остаются как есть. Это и есть смысл «боевой сигнатуры»: контур уже боевой, меняется только «голова», достающая данные.
Тот же паттерн использован для выдачи лицензий (ProvisioningConnector): симулятор провижининга заменяется на реального агента установки без изменения статусной машины.- Добавить запись в
_REGISTRY(например,"scim": ScimCollector()). - Дополнить правило маршрутизации
collect_method → source_type, чтобы нужные системы вели
на новый тип.
- Добавить тип в список источников планировщика (
SOURCE_TYPES) — джобы =арендаторы × типы.
Так в Эпике 5 без правок ядра добавились odata_1c и syslog_evtx к исходному ksc_sql.
- HTTP-приём (если источник умеет слать сам):
POST /api/{tenant}/ingest/activity,
роль collector или it_admin. Тело — батч записей + source_type.
- Пулл по расписанию (коллектор сам забирает): контейнер
collector, планировщик
дёргает get_collector(source).collect(tenant) → тот же ingest_activity. Подробно — статья 04.
# сгенерировать фикстуры всех типов и посмотреть, что соберётся
docker compose -f docker-compose.phase1.yml up --build
docker logs licenziar-collector-1 # видны прогоны по (tenant × source)
curl http://localhost:8001/api/artek/ops-efficiency # covered/среднее — результат сбораНа экране /collectors видно прогоны каждого источника и сколько записей применено.
- Неизвестный `sys_code` → запись пропускается (
skippedUnknownSystem), если сырое имя
ПО не распозналось парсером. Если боевой источник шлёт свои коды — заполните raw_product, чтобы сработал фолбэк-распознаватель (см. статью 04, врезка).
- Источник без систем у арендатора отдаёт 0 записей — это норма. Пример: у РГГУ нет
лицензированной 1С, поэтому odata_1c для неё пуст. Не считайте это ошибкой сбора.
- Сырьё (табельный, raw_product) нельзя логировать на стороне коннектора — оно не должно
переживать момент приёма. Обезличивание — ответственность приёма, не источника.
Связанные статьи: 04 — Механизм сбора · 02 — ПДн и Vault.