Стадия жизненного цикла модуля: Experimental
У модуля есть требования для установки

Модуль security-events-manager выполняет сбор, обработку и отправку событий безопасности, извлекаемых из логов приложений и инфраструктурных компонентов.

Событие безопасности — это строго структурированная запись о значимом с точки зрения информационной безопасности (ИБ) действии или факте, например:

  • неуспешная аутентификация (в любой сервис);
  • подозрительный доступ к API;
  • критичные изменения ресурсов.

Цель модуля — получить логовые записи, распознать в них события безопасности, привести события к единому формату и отправить через настроенные приёмники.

В основе функциональности модуля:

  • концепция событий безопасности;
  • механизм сбора логовых записей из разных сервисов с помощью вспомогательного модуля log-shipper;
  • механизм обработки (парсинга) и извлечения событий безопасности;
  • механизм преобразования в единый формат и обогащения дополнительными данными;
  • механизм фильтрации и отправки событий безопасности.

Для преобразования логовой записи в событие безопасности, сохраняемое во внешнем источнике, данные проходят следующие этапы обработки:

  flowchart LR
  %% --- СТИЛИ УЗЛОВ (Черный текст + Четкие границы) ---
  classDef step fill:#ffffff,stroke:#000000,color:#000000,stroke-width:2px;
  classDef source fill:#f1f5f9,stroke:#000000,color:#000000,stroke-width:2px;
  classDef storage fill:#ffffff,stroke:#000000,color:#000000,stroke-width:2px;

  %% --- ПОТОК ---
  A(["fa:fa-server Источник логов <br/>(сервис)"]):::source ==> LS

  subgraph LS [<b><font color='black'>log-shipper</font></b>]
    direction TB
    ls1[Определение записей с потенциальными<br/>событиями безопасности]:::step --> ls2[Отправка в security-events-shipper]:::step
  end

  LS ==> SES

  subgraph SES [<b><font color='black'>security-events-shipper</font></b>]
    direction LR

    subgraph P [<b><font color='black'>Обработка</font></b>]
      direction TB
      p1["Обработка логов (парсинг)"]:::step --> p2[Извлечение событий безопасности]:::step
    end

    P ==> E

    subgraph E [<b><font color='black'>Преобразование</font></b>]
      direction TB
      e1[Приведение в единый формат]:::step --> e2[Обогащение данными]:::step
    end

    E ==> F

    subgraph F [<b><font color='black'>Фильтрация</font></b>]
      direction TB
      f1[Фильтрация <br/> по source и severity]:::step --> f2[Отправка в приёмник]:::step
    end
  end

  %% --- БЛОК 3: ХРАНИЛИЩА ---
  SES ==> ST

  subgraph ST [<b><font color='black'>Целевые хранилища</font></b>]
    direction TB
    S1[("fa:fa-chart-area Loki")]:::storage
    S2[("fa:fa-search Elastic")]:::storage
    S3[("fa:fa-bolt ClickHouse")]:::storage
    S1 ~~~ S2 ~~~ S3
  end

  %% --- ЦВЕТОВАЯ ГРУППИРОВКА (СВЕТЛАЯ) ---
  style LS fill:#e0e7ff,stroke:#1a237e,stroke-width:2px,color:#000000
  style SES fill:#f5f3ff,stroke:#4a148c,stroke-width:2px,color:#000000
  style ST fill:#f0fdfa,stroke:#004d40,stroke-dasharray: 5 5,stroke-width:2px,color:#000000
  
  style P fill:none,stroke:#4a148c,stroke-dasharray: 3 3
  style E fill:none,stroke:#4a148c,stroke-dasharray: 3 3
  style F fill:none,stroke:#4a148c,stroke-dasharray: 3 3

  %% --- ТЕМНЫЕ ЖЕСТКИЕ СТРЕЛКИ ---
  linkStyle default stroke:#000000,stroke-width:2px;
  linkStyle 0,2,4,6,8,9,10 stroke:#000000,stroke-width:3px;

Пример итогового события:

{
  "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

Архитектура решения

Модуль выполняет три этапа работы:

  1. Сбор:
    • сбор логов из источников подов и файлов узлов;
    • первичный отбор записей, потенциально содержащих события безопасности.
  2. Обработка и обогащение:
    • парсинг и извлечение полезных полей;
    • преобразование в единую модель и обогащение контекстом.
  3. Доставка:
    • фильтрация по политике и отправка в настроенные приёмники.

На этапе доставки поддерживается отправка в несколько типов систем хранения и аналитики (например, Loki, Elasticsearch, Kafka, Splunk, Vector, File).

Этапы обработки

Сбор логов

Логи в модуль 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 имеет формат массива объектов. Для каждого объекта настраиваются:

  1. имя источника логов — поле source;
  2. тип и параметры источника логов — поле input;
  3. правила первичного отбора записей — поле 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
...

Преобразование и обогащение события безопасности

Поскольку событие безопасности имеет фиксированную структуру, распознанную логовую запись необходимо преобразовать в целевую модель события. Для этого используются два механизма:

  1. Преобразование полей (transform) — перенос значений из полей лога в поля события безопасности;
  2. Обогащение (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 — статические данные (подстановка фиксированного значения).

enrich применяется после transform; при конфликте целевого поля значение из enrich перезаписывает результат transform.

Фильтрация и отправка событий безопасности

После формирования события безопасности необходимо определить, в какие приёмники его отправлять. Для этого требуется:

  1. настроить приёмники событий безопасности;
  2. настроить правила отправки событий в приёмники.

Настройка приёмника

Приёмники настраиваются через ресурс 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

Стандартные настройки модуля

Если настройки модуля явно не заданы, то в кластере размещаются следующие объекты:

  1. ClusterSecurityEventConfig — отвечает за настройку отправки событий безопасности в приёмники. Стандартно используются следующие настройки:

    apiVersion: security.deckhouse.io/v1alpha1
    kind: ClusterSecurityEventConfig
    metadata:
      name: default
    spec:
      defaultSeverityThreshold: Medium
      destinations:
        - cluster-loki
      enabledSourcesMasks:
        - podSecurityEventShipper/*
        - clusterSecurityEventShipper/*

    На конфигурирование этих параметров отвечает настройка модуля securityEventConfig.

  2. 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.