Доступно в редакциях: EE
Стадия жизненного цикла модуля: Experimental
У модуля есть требования для установки
Модуль security-events-manager выполняет сбор, обработку и отправку событий безопасности, извлекаемых из логов приложений и инфраструктурных компонентов.
Событие безопасности — это строго структурированная запись о значимом с точки зрения информационной безопасности (ИБ) действии или факте, например:
- неуспешная аутентификация (в любой сервис);
- подозрительный доступ к API;
- критичные изменения ресурсов.
Цель модуля — получить логовые записи, распознать в них события безопасности, привести события к единому формату и отправить через настроенные приёмники.
В основе функциональности модуля:
- концепция событий безопасности;
- механизм сбора логовых записей из разных сервисов с помощью вспомогательного модуля
log-shipper; - механизм обработки (парсинга) и извлечения событий безопасности;
- механизм преобразования в единый формат и обогащения дополнительными данными;
- механизм фильтрации и отправки событий безопасности.
Для преобразования логовой записи в событие безопасности, сохраняемое во внешнем источнике, данные проходят следующие этапы обработки:

Пример итогового события:
{
"id": "2f0de5c2-2e58-4d3f-b4fe-5ec6f1935b9f",
"timestamp": "2026-05-10T14:21:03Z",
"source": {
"component": "kube-apiserver"
},
"event": {
"code": "UNAUTHORIZED_ACCESS",
"category": "Rbac",
"severity": "High",
"outcome": "Failure"
},
"eventMetadata": {
"cluster": "prod-cluster",
"sourceIPs": [
"206.123.145.70"
]
},
"actor": {
"id": "system:serviceaccount:default:demo",
"type": "ServiceAccount"
},
"object": {
"id": "/api/v1/namespaces/default/secrets",
"type": "KubernetesResource"
}
}Контент события может отличаться в зависимости от источника, но структура должна быть однородной. Модель события описана в SecurityEvent.
Описание события для конкретного источника задаётся ресурсом SecurityEventDefinition.
В этом ресурсе определяются обязательные и дополнительные поля, а также категория и уровень критичности.
Пример:
apiVersion: security.deckhouse.io/v1alpha1
kind: SecurityEventDefinition
metadata:
name: k8s-pod-created
spec:
code: K8S_POD_CREATED
category: Runtime
severity: Low
description: >
Kubernetes pod created
source: runtime-audit-engine
fields:
- name: event.code
required: true # Значение по умолчанию — true.
- name: source.component
required: true
- name: metadata.extra.ka_target_name
required: false
- name: metadata
required: falseАрхитектура решения
Модуль выполняет три этапа работы:
- Сбор:
- сбор логов из источников подов и файлов узлов;
- первичный отбор записей, потенциально содержащих события безопасности.
- Обработка и обогащение:
- парсинг и извлечение полезных полей;
- преобразование в единую модель и обогащение контекстом.
- Доставка:
- фильтрация по политике и отправка в настроенные приёмники.
На этапе доставки поддерживается отправка в несколько типов систем хранения и аналитики (например, Loki, Elasticsearch, Kafka, Splunk, Vector, File, Socket).
Этапы обработки
Сбор логов
Логи в модуль security-events-manager поступают с помощью вспомогательного модуля log-shipper.
Применяется двухуровневая схема:
- модуль
log-shipperвыполняет предварительный отбор логовых записей с помощью простых операций сравнения (In,NotIn,Regex,NotRegex,Exists,DoesNotExist) и передаёт их в шлюз; - модуль
security-events-manager(шлюз) выполняет распознавание полей (парсинг, сериализация), последующую обработку и отправку.
Поскольку парсинг логов является ресурсоёмкой операцией, он выполняется только для записей, заранее отобранных как потенциально содержащие события безопасности, а не для всех входящих логов. Поэтому на этапе первичного отбора не выполняется глубокая фильтрация по значениям полей, требующая полноценного парсинга содержимого.
Настройка сбора логов и нескольких следующих этапов выполняется через ресурсы PodSecurityEventShipper и ClusterSecurityEventShipper (в зависимости от типа источника).
Кластерным источником логов являются источники, не привязанные к конкретному неймспейсу, например файлы узла.
Поскольку эти ресурсы используются для настройки нескольких этапов обработки, в примерах ниже показаны только соответствующие фрагменты манифестов.
Пример (фрагмент манифеста):
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: runtime-audit-engine
namespace: d8-runtime-audit-engine
spec:
# Настройка источников логов.
- source: runtime-audit-engine
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: runtime-audit-engine
...
# Отбор записей, потенциально содержащих событие безопасности.
produces:
- eventCode: K8S_POD_CREATED
# Пример лога: Informational K8s Pod Created (user=system:serviceaccount:kube-system:replicaset-controller pod=example-7d6894dbd9-92hgx ns=d8-system resource=pods ... .
extract:
field: message
operator: Regex
values:
- ".*K8s Pod Created.*"
- eventCode: K8S_POD_DELETED
# Пример лога: Informational K8s Pod Deleted (user=kubernetes-admin pod=example-7d6894dbd9-92hgx ns=d8-system resource=pods ... .
extract:
field: message
operator: Regex
values:
- ".*K8s Pod Deleted.*"
...apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventShipper
metadata:
name: kube-audit
spec:
# Настройка источников логов.
- source: kube-audit
input:
type: File
files:
- /var/log/kube-audit/audit.log
...
# Отбор записей, потенциально содержащих событие безопасности.
produces:
- eventCode: UNAUTHORIZED_ACCESS
# Пример лога: ... "message":"Unauthorized","reason":"Unauthorized","code":401 ... .
extract:
field: message
operator: Regex
values:
- ".*\"code\":401.*"
...В манифестах возможна настройка нескольких источников, поскольку поле spec имеет формат массива объектов.
Для каждого объекта настраиваются:
- имя источника логов — поле
source; - тип и параметры источника логов — поле
input; - правила первичного отбора записей — поле
produces.
Обработка (парсинг), извлечение событий безопасности
После поступления логов в шлюз модуль security-events-manager выполняет парсинг и извлечение событий безопасности.
Настройка распознавания логов выполняется через поля объектов PodSecurityEventShipper и ClusterSecurityEventShipper. За настройку отвечает поле parser.
В поле parser указывается, логи какого контейнера необходимо распознавать (поле name) и каким способом (вложенное поле parser).
Поддерживаются следующие типы парсеров:
JSON— парсинг логов в формате JSON;Regex— парсинг логов по регулярному выражению;Grok— парсинг логов по Grok-шаблонам.
Дополнительно можно указать требуется ли сохранять исходные поля логовой записи (drop_raw).
Пример:
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: runtime-audit-engine
namespace: d8-runtime-audit-engine
spec:
# Настройка источников логов.
- source: runtime-audit-engine
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: runtime-audit-engine
# Настройка парсинга логов.
parser:
- name: falco
parser:
type: JSON
drop_raw: false
...Если требуется сложный парсинг, можно вынести правила распознавания в отдельные ресурсы SecurityEventLoggingTransformationRules (SELTR) и ClusterSecurityEventLoggingTransformationRules (CSELTR).
В этих ресурсах аналогичным образом задаётся, как именно необходимо парсить логи.
Пример:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventLoggingTransformationRules
metadata:
name: auth-log
spec:
type: File
file:
paths:
- /var/log/auth.log
transform:
parser:
type: Grok
grok:
# Применяется первый успешно сработавший шаблон.
patterns:
# Недопустимый пользователь zju_yd с 206.123.145.70 порт 33124.
- '%{AUTHLOGTIMESTAMP:ts} %{HOSTNAME:host} %{WORD:program}\[%{INT:pid}\]: %{DATA:action} %{USER} from %{SRCIP} port %{INT:src_port}'
# Соединение закрыто недопустимым пользователем gb 206.123.145.57 порт 49356 [preauth].
- '%{AUTHLOGTIMESTAMP:ts} %{HOSTNAME:host} %{WORD:program}\[%{INT:pid}\]: %{DATA:action} %{USER} %{SRCIP} port %{INT:src_port} \[%{DATA:context}\]'
# Соединение закрыто аутентифицирующимся пользователем root 206.123.145.52 порт 60078 [preauth].
- '%{AUTHLOGTIMESTAMP:ts} %{HOSTNAME:host} %{WORD:program}\[%{INT:pid}\]: %{DATA:action} %{USER} %{SRCIP} port %{INT:src_port} \[%{DATA:context}\]'
# Запасной вариант: сохранить исходное сообщение sshd в `msg`.
- '%{AUTHLOGTIMESTAMP:ts} %{HOSTNAME:host} %{WORD:program}\[%{INT:pid}\]: %{GREEDYDATA:msg}'
customPatterns:
# Соответствует формату "Mar 6 01:08:21" (допускается двойной пробел перед однозначным днём).
- key: AUTHLOGTIMESTAMP
value: '[A-Z][a-z]{2}\s+\d{1,2}\s+\d{2}:\d{2}:\d{2}'
# Минимальный набор шаблонов (без зависимости от конкретного встроенного набора grok).
- key: HOSTNAME
value: '[0-9A-Za-z][0-9A-Za-z._-]+'
- key: WORD
value: '[A-Za-z0-9_]+'
- key: INT
value: '[0-9]+'
- key: IPV4
value: '(?:\d{1,3}\.){3}\d{1,3}'
- key: DATA
value: '.*?'
- key: GREEDYDATA
value: '.*'
- key: USER
value: '(?<user>.*?)'
- key: SRCIP
value: '(?<src_ip>(?:\d{1,3}\.){3}\d{1,3})'
fields:
- name: pid
type: Int
- name: src_port
type: IntПри использовании SELTR или CSELTR в ресурсах PodSecurityEventShipper и ClusterSecurityEventShipper необходимо указать в поле parserRef имя ресурса, из которого берутся настройки распознавания:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventShipper
metadata:
name: auth-log
spec:
# Настройка источников логов.
- source: auth-log
input:
type: File
files:
- /var/log/auth.log
# Настройка парсинга логов.
parserRef: auth-log
...Преобразование и обогащение события безопасности
Поскольку событие безопасности имеет фиксированную структуру, распознанную логовую запись необходимо преобразовать в целевую модель события. Для этого используются два механизма:
- Преобразование полей (
transform) — перенос значений из полей лога в поля события безопасности; - Обогащение (
Enrich) — добавление новых полей в событие безопасности.
Оба механизма настраиваются одноимёнными полями в блоке produces ресурсов PodSecurityEventShipper и ClusterSecurityEventShipper.
Пример:
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: user-authn
namespace: d8-user-authn
spec:
# Настройка источников логов.
- source: user-authn
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: dex
...
produces:
# Отбор записей, потенциально содержащих событие безопасности.
- eventCode: USER_LOGIN_SUCCESS
# Пример лога: {"time":"2026-02-16T08:24:16.296841124Z","level":"INFO","msg":"login successful","connector_id":"local","username":"testuser","preferred_username":"","email":"test.user@example.ru","groups":["admins"],"client_remote_addr":"109.191.184.154","request_id":"712c95ff-94c2-41af-ac60-766a78218ceb"}.
extract:
field: message
operator: Regex
values:
- ".*login successful.*"
# Настройка трансформации полей лога в поля событий безопасности.
transform:
# Субъект.
- key: actor.id
value: username
# Метаданные.
- key: metadata.actor.preferredUsername
value: preferred_username
- key: metadata.actor.email
value: email
- key: metadata.actor.groups
value: groups
# Обогащение полей дополнительными данными.
enrich:
- target: actor.type
source: Static
value: UserПомимо трансформации и обогащения конкретного события, возможно задать глобальные трансформации и обогащения.
Это полезно, когда записи одного сервиса однотипны и содержат общие поля для всех событий.
Глобальные правила настраиваются в поле producesDefaults, структура которого аналогична produces.
Пример:
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: user-authn
namespace: d8-user-authn
spec:
# Настройка источников логов.
- source: user-authn
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: dex
...
# Настройка глобальных трансформаций и обогащений.
producesDefaults:
transform:
- key: timestamp
value: time
- key: metadata.actor.sourceIPs
value: client_remote_addr
enrich:
- target: actor.type
source: Static
value: User
...
produces:
# Отбор записей, потенциально содержащих событие безопасности.
- eventCode: USER_LOGIN_SUCCESS
extract:
field: message
operator: Regex
values:
- ".*login successful.*"
# Настройка трансформации полей лога в поля событий безопасности.
transform:
# Субъект.
- key: actor.id
value: username
# Метаданные.
- key: metadata.actor.preferredUsername
value: preferred_username
- key: metadata.actor.email
value: email
- key: metadata.actor.groups
value: groups
# Обогащение полей дополнительными данными.
enrich:
- target: actor.type
source: Static
value: User
...Для трансформации используется структура «ключ-значение», где ключ — целевое поле события безопасности, значение — поле исходного лога.
Обогащение использует расширяемую модель источников данных.
Каждый элемент обогащения содержит поля — target — целевое поле события, source — источник данных, value — значение из источника.
На текущий момент поддержаны источники:
Static— статические данные (подстановка фиксированного значения);Plugin— получение данных во время выполнения через сайдкарenrichment-cacheв поде gateway (см. Плагины обогащения).
enrich применяется после transform; при конфликте целевого поля значение из enrich перезаписывает результат transform.
Плагины обогащения
Обогащение через плагины (source: Plugin) заполняет поля события, отсутствующие в исходном логе, во время выполнения.
Каждый плагин — это HTTP-эндпоинт, который получает GET-запрос с query-параметрами,
произведёнными от полей события, и возвращает JSON-объект с запрошенными значениями.
Плагины регистрируются как кастомные ресурсы ClusterSecurityEventEnrichmentPlugin (CSEP). Поддерживаются два типа плагинов:
-
Internal— обслуживается встроенным сайдкаромenrichment-cacheв поде шлюза. Модуль поставляет три Internal-плагина:k8s-pod-info,k8s-container-info,k8s-nodeuser-info. Internal-плагины нельзя создавать или изменять пользователям. -
External— обслуживается пользовательским HTTP-сервисом в любом неймспейсе. Пользователи создаютExternal-ресурсы CSEP для регистрации собственных enrichment-эндпоинтов.
Обогащение не фатально: если получение значения не удалось (отсутствуют входные поля, нет совпадения, HTTP-ошибка), целевое поле остаётся незаполненным, а событие не отбрасывается.
Чтобы получить список доступных плагинов, выполните:
kubectl get clustersecurityeventenrichmentpluginsКаждый ресурс CSEP объявляет входные аргументы плагина (spec.args) и поля, которые
он возвращает (spec.returns.fields). Когда ShipperEnrichRule ссылается на плагин,
value должно совпадать с одним из returns.fields[].name, а ключи args —
с spec.args[].name.
Во время выполнения контроллер генерирует Lua V2 transform, который делает HTTP GET-запрос к эндпоинту плагина для каждого события:
- Internal-плагины:
GET http://127.0.0.1:9261/api/v1/enrich?plugin=<name>&<args>(loopback-only enrichment-листенер сайдкараenrichment-cache) - External-плагины:
GET <spec.endpoint.url>?<args>
Ответ — плоский JSON-объект; поле value определяет, какой ключ извлечь из ответа.
Встроенные Internal-плагины
Модуль поставляет три Internal-плагина.
k8s-pod-info {.anchored}
Получает поля пода (serviceAccountName, name, namespace) по имени пода и
неймспейсу из in-memory кеша подов сайдкара enrichment-cache (без обращения к
API-серверу на каждое событие).
Обязательные входные параметры:
| Параметр | Описание |
|---|---|
pod_name |
Путь к полю события, содержащему имя пода (например, k8s.pod.name). |
namespace |
Путь к полю события, содержащему неймспейс (например, k8s.namespace.name). |
Доступные выходные значения (value):
| Значение | Описание |
|---|---|
serviceAccountName |
Поле пода spec.serviceAccountName, отформатированное как system:serviceaccount:<namespace>:<name>. |
name |
Имя пода. |
namespace |
Неймспейс пода. |
Пример элемента массива enrich:
- target: actor.id
source: Plugin
plugin: k8s-pod-info
value: serviceAccountName
args:
- key: pod_name
value: k8s.pod.name
- key: namespace
value: k8s.namespace.namek8s-container-info {.anchored}
Получает поля пода (serviceAccountName, name, namespace) по container runtime ID.
Префиксы рантайма (containerd://, docker://, cri-o:// и др.) удаляются автоматически.
Обязательный входной параметр:
| Параметр | Описание |
|---|---|
container_id |
Путь к полю события, содержащему container ID (например, container.id). |
Доступные выходные значения (value):
| Значение | Описание |
|---|---|
serviceAccountName |
Поле пода spec.serviceAccountName, отформатированное как system:serviceaccount:<namespace>:<name>. |
name |
Имя пода. |
namespace |
Неймспейс пода. |
Пример элемента массива enrich:
- target: actor.id
source: Plugin
plugin: k8s-container-info
value: serviceAccountName
args:
- key: container_id
value: container.idk8s-nodeuser-info {.anchored}
Определяет имя статического пользователя (объект nodeusers.deckhouse.io) по его
системному UID. Поиск отображает spec.uid в metadata.name из in-memory кеша
NodeUser сайдкара enrichment-cache (без обращения к API-серверу на каждое событие).
Обязательный входной параметр:
| Параметр | Описание |
|---|---|
uid |
Путь к полю события, содержащему системный UID (например, output_fields.user.uid). |
Доступные выходные значения (value):
| Значение | Описание |
|---|---|
username |
metadata.name объекта NodeUser — имя (логин) статического пользователя. |
Пример элемента массива enrich:
- target: actor.name
source: Plugin
plugin: k8s-nodeuser-info
value: username
args:
- key: uid
value: output_fields.user.uidПользовательские External-плагины
Пользователи могут создавать External-ресурсы CSEP для регистрации собственных
enrichment-эндпоинтов. External-плагин — это HTTP-сервис, развёрнутый в любом
неймспейсе. Ресурс CSEP объявляет URL эндпоинта, входные аргументы и возвращаемые поля.
Пример ресурса External-плагина:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventEnrichmentPlugin
metadata:
name: my-custom-enricher
spec:
type: External
description: "Resolve employee info by badge ID"
endpoint:
url: http://my-enricher.my-namespace.svc:8080/lookup
args:
- name: badge_id
required: true
description: "Event field path containing the employee badge ID"
returns:
fields:
- name: username
type: String
description: "Employee username"
- name: department
type: String
description: "Employee department"Пример элемента массива enrich, ссылающегося на External-плагин:
- target: actor.name
source: Plugin
plugin: my-custom-enricher
value: username
args:
- key: badge_id
value: output_fields.user.badge_idHTTP API-контракт
Каждый плагин (Internal или External) должен соответствовать единому HTTP API-контракту:
-
Запрос:
GET <endpoint>?<arg1>=<val1>&<arg2>=<val2> -
Ответ:
200 OKс JSON-телом, содержащим объявленные return-поля:{ "username": "jdoe", "department": "security" } -
Не найдено:
404— целевое поле остаётся незаполненным, событие не отбрасывается. -
Ошибка:
500— ошибка логируется, целевое поле остаётся незаполненным.
Тип содержимого ответа должен быть application/json.
Фильтрация и отправка событий безопасности
После формирования события безопасности необходимо определить, в какие приёмники его отправлять. Для этого требуется:
- настроить приёмники событий безопасности;
- настроить правила отправки событий в приёмники.
Настройка приёмника
Приёмники настраиваются через ресурс ClusterSecurityEventDestination.
В качестве приёмников используются типы, доступные в экосистеме log-shipper.
Для хранения событий безопасности внутри кластера предусмотрена автоматическая настройка приёмника Loki при включении соответствующей опции модуля.
Пример:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: cluster-loki
spec:
type: Loki
loki:
auth:
strategy: Bearer
token: <EXAMPLE>
endpoint: https://loki.d8-monitoring:3100
tls:
verifyCertificate: true
verifyHostname: true
ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...Настройка правил отправки событий в приёмники
При настройке правил отправки необходимо определить:
- события из каких источников отправляются;
- минимальный уровень severity для отправки;
- целевые приёмники.
Для этого используется ресурс ClusterSecurityEventConfig.
В ресурсе указываются источники (в формате точных имён или масок), минимальный severity, и массив приёмников (ресурсы ClusterSecurityEventDestination), в каждый из которых отправляются отобранные события.
Пример:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventConfig
metadata:
name: default
spec:
defaultSeverityThreshold: Low
enabledSources:
- clusterSecurityEventShipper/kube-audit/kube-audit
- podSecurityEventShipper/d8-runtime-audit-engine/runtime-audit-engine/falco
- podSecurityEventShipper/d8-user-authn/user-authn/dex
# Либо указать маски.
# enabledSourcesMasks:
# - clusterSecurityEventShipper/kube-audit/*
# - podSecurityEventShipper/*
destinations:
- cluster-lokiСтандартные настройки модуля
Если настройки модуля явно не заданы, то в кластере размещаются следующие объекты:
-
ClusterSecurityEventConfig— отвечает за настройку отправки событий безопасности в приёмники. Стандартно используются следующие настройки:apiVersion: security.deckhouse.io/v1alpha1 kind: ClusterSecurityEventConfig metadata: name: default spec: defaultSeverityThreshold: Medium destinations: - cluster-loki enabledSourcesMasks: - podSecurityEventShipper/* - clusterSecurityEventShipper/*На конфигурирование этих параметров отвечает настройка модуля
securityEventConfig. -
ClusterSecurityEventDestination— отвечает за настройку приёмника событий безопасности. Стандартно генерируется объект, с помощью которого возможно осуществить отправку событий безопасности в сервисloki, расположенный в кластере. Генерируется следующий объект:apiVersion: security.deckhouse.io/v1alpha1 kind: ClusterSecurityEventDestination metadata: name: cluster-loki spec: type: Loki loki: auth: strategy: Bearer token: <token> # Заполняется автоматически. endpoint: https://loki.d8-monitoring:3100Отключить генерацию стандартного CSED можно отдельным параметром
clusterSecurityEventDestination.clusterLoki.