Available in: EE
The module lifecycle stage: Experimental
The module has requirements for installation
The security-events-manager module collects, processes, and delivers security events extracted from logs of applications and infrastructure components.
A security event is a strictly structured record of an action or fact that is significant from an information security perspective, for example:
- failed authentication (in any service);
- suspicious API access;
- critical resource changes.
The module goal is to receive log records, detect security events in them, convert events to a unified format, and send them to centralized storage.
The module functionality is based on:
- the security events concept;
- a mechanism for collecting log records from different services through the auxiliary
log-shippermodule; - a mechanism for processing (parsing) logs and extracting security events;
- a mechanism for normalization to a unified format and enrichment with additional data;
- a mechanism for filtering and delivering security events.
To transform a log record into a security event stored in an external system, data goes through the following processing stages:
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 Log Source <br/>(service)"]):::source ==> LS
subgraph LS [<b><font color='black'>log-shipper</font></b>]
direction TB
ls1[Identify records potentially<br/>containing security events]:::step --> ls2[Send to 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'>Processing</font></b>]
direction TB
p1["Log processing (parsing)"]:::step --> p2[Security event extraction]:::step
end
P ==> E
subgraph E [<b><font color='black'>Transformation</font></b>]
direction TB
e1[Normalize to unified format]:::step --> e2[Data enrichment]:::step
end
E ==> F
subgraph F [<b><font color='black'>Filtering</font></b>]
direction TB
f1[Filter by <br/> source and severity]:::step --> f2[Route to storage]:::step
end
end
SES ==> ST
subgraph ST [<b><font color='black'>Target Storage</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:#1a1a1a,stroke-width:2px;
linkStyle 0,2,4,6,8,9,10 stroke:#000000,stroke-width:3px;
Example of a security event:
{
"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"
}
}Event content may differ by source, but the structure must be uniform. The event model is described in SecurityEvent.
The event description for a specific source is defined by SecurityEventDefinition.
This resource defines required and optional fields, as well as category and severity.
Example:
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 # default - true
- name: source.component
required: true
- name: metadata.extra.ka_target_name
required: false
- name: metadata
required: falseSolution architecture
The module performs three work stages:
- Collection:
- collection of logs from pod sources and node files;
- primary selection of records that may contain security events.
- Processing and enrichment:
- parsing and extraction of useful fields;
- transformation to a unified model and context enrichment.
- Delivery:
- policy-based filtering and delivery to configured storages.
At the delivery stage, sending to multiple storage and analytics system types is supported (for example, Loki, Elasticsearch, Kafka, Splunk, Vector, File).
Processing stages
Log collection
Logs are delivered to the security-events-manager module through the auxiliary log-shipper module.
A two-tier scheme is used:
- the
log-shippermodule performs preliminary selection of log records using simple comparison operations (In,NotIn,Regex,NotRegex,Exists,DoesNotExist) and forwards them to the gateway; - the
security-events-managermodule (gateway) performs field recognition (parsing, serialization), further processing, and delivery.
Because log parsing is resource-intensive, it is performed only for records pre-selected as potentially containing security events, not for all incoming logs. Therefore, the initial selection stage does not perform deep field-value filtering that requires full content parsing.
Log collection and several subsequent stages are configured through PodSecurityEventShipper and ClusterSecurityEventShipper resources (depending on the source type).
Cluster log sources are sources not bound to a specific namespace, for example node files.
Because these resources configure multiple processing stages, the examples below show only the relevant manifest fragments.
Example (manifest fragment):
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: runtime-audit-engine
namespace: d8-runtime-audit-engine
spec:
# Log source configuration.
- source: runtime-audit-engine
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: runtime-audit-engine
...
# Select records potentially containing a security event.
produces:
- eventCode: K8S_POD_CREATED
# Log example: 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
# Log example: 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:
# Log source configuration.
- source: kube-audit
input:
type: File
files:
- /var/log/kube-audit/audit.log
...
# Select records potentially containing a security event.
produces:
- eventCode: UNAUTHORIZED_ACCESS
# Log example: ... "message":"Unauthorized","reason":"Unauthorized","code":401 ...
extract:
field: message
operator: Regex
values:
- ".*\"code\":401.*"
...Manifests may configure multiple sources because spec is an array of objects.
For each item you configure:
- log source name —
sourcefield; - log source type and parameters —
inputfield; - preliminary record selection rules —
producesfield.
Example source log for the selection stage:
{
"time": "2026-05-10T14:21:03Z",
"kind": "Event",
"source": "kube-apiserver",
"level": "Metadata",
"message": "Unauthorized",
"reason": "Unauthorized",
"code": 401,
"requestURI": "/api/v1/namespaces/default/secrets",
"user": "system:serviceaccount:default:demo",
"sourceIPs": [
"206.123.145.70"
]
}Processing (parsing), security event extraction
After logs are delivered to the gateway component, security-events-manager performs parsing and security event extraction.
Log parsing is configured through fields of PodSecurityEventShipper and ClusterSecurityEventShipper objects. The parser field is responsible for this configuration.
The parser field specifies which container logs should be parsed (name) and by which method (nested parser field).
Supported parser types:
JSON— parse JSON logs;Regex— parse with regular expressions;Grok— parse with Grok patterns.
You can additionally define whether to keep the original log entry (drop_raw).
Example:
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: runtime-audit-engine
namespace: d8-runtime-audit-engine
spec:
# Log source configuration.
- source: runtime-audit-engine
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: runtime-audit-engine
# Log parsing configuration.
parser:
- name: falco
parser:
type: JSON
drop_raw: false
...If complex parsing is required, parsing rules can be moved into dedicated resources: SecurityEventLoggingTransformationRules (SELTR) and ClusterSecurityEventLoggingTransformationRules (CSELTR).
These resources define how logs should be parsed in the same manner.
Example:
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:
# First successful pattern wins.
patterns:
# Invalid user zju_yd from 206.123.145.70 port 33124
- '%{AUTHLOGTIMESTAMP:ts} %{HOSTNAME:host} %{WORD:program}\[%{INT:pid}\]: %{DATA:action} %{USER} from %{SRCIP} port %{INT:src_port}'
# Connection closed by invalid user gb 206.123.145.57 port 49356 [preauth]
- '%{AUTHLOGTIMESTAMP:ts} %{HOSTNAME:host} %{WORD:program}\[%{INT:pid}\]: %{DATA:action} %{USER} %{SRCIP} port %{INT:src_port} \[%{DATA:context}\]'
# Connection closed by authenticating user root 206.123.145.52 port 60078 [preauth]
- '%{AUTHLOGTIMESTAMP:ts} %{HOSTNAME:host} %{WORD:program}\[%{INT:pid}\]: %{DATA:action} %{USER} %{SRCIP} port %{INT:src_port} \[%{DATA:context}\]'
# Fallback: keep the raw sshd message in `msg`
- '%{AUTHLOGTIMESTAMP:ts} %{HOSTNAME:host} %{WORD:program}\[%{INT:pid}\]: %{GREEDYDATA:msg}'
customPatterns:
# Matches: "Mar 6 01:08:21" (double space before 1-digit day is allowed)
- key: AUTHLOGTIMESTAMP
value: '[A-Z][a-z]{2}\s+\d{1,2}\s+\d{2}:\d{2}:\d{2}'
# Minimal set of patterns (avoid dependency on a specific built-in grok pattern set)
- 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: IntWhen using SELTR or CSELTR, PodSecurityEventShipper and ClusterSecurityEventShipper must reference the parser rule resource name via parserRef:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventShipper
metadata:
name: auth-log
spec:
# Log source configuration.
- source: auth-log
input:
type: File
files:
- /var/log/auth.log
# Log parsing configuration.
parserRef: auth-log
...Transformation and enrichment of a security event
Because a security event has a fixed structure, a parsed log record must be transformed into the target event model. Two mechanisms are used:
- Field transformation (
Transform) — map values from log fields to security event fields; - Enrichment (
Enrich) — add new fields to the security event.
Both mechanisms are configured via same-name fields inside produces blocks of PodSecurityEventShipper and ClusterSecurityEventShipper.
Example:
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: user-authn
namespace: d8-user-authn
spec:
# Log source configuration.
- source: user-authn
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: dex
...
produces:
# Select records that may contain a security event.
- eventCode: USER_LOGIN_SUCCESS
# Log example: {"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.*"
# Map log fields to security event fields.
transform:
# actor
- key: actor.id
value: username
# metadata
- key: metadata.actor.preferredUsername
value: preferred_username
- key: metadata.actor.email
value: email
- key: metadata.actor.groups
value: groups
# Enrich fields with additional data.
enrich:
- target: actor.type
source: Static
value: UserIn addition to per-event transformation and enrichment, global transformation and enrichment can be configured.
This is useful when logs from one service are homogeneous and contain common fields for all events.
Global rules are configured in producesDefaults, whose structure is similar to produces.
Example:
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: user-authn
namespace: d8-user-authn
spec:
# Log source configuration.
- source: user-authn
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: dex
...
# Global transformation and enrichment configuration.
producesDefaults:
transform:
- key: timestamp
value: time
- key: metadata.actor.sourceIPs
value: client_remote_addr
enrich:
- target: actor.type
source: Static
value: User
...
produces:
# Select records that may contain a security event.
- eventCode: USER_LOGIN_SUCCESS
extract:
field: message
operator: Regex
values:
- ".*login successful.*"
# Map log fields to security event fields.
transform:
# actor
- key: actor.id
value: username
# metadata
- key: metadata.actor.preferredUsername
value: preferred_username
- key: metadata.actor.email
value: email
- key: metadata.actor.groups
value: groups
# Enrich fields with additional data.
enrich:
- target: actor.type
source: Static
value: User
...For transformation, a key-value structure is used where the key is the target security event field and the value is the source log field.
Enrichment uses an extensible data source model.
Each enrichment item contains — target — target event field, source — data source, value — source value.
Currently supported source:
Static— static data (fixed value substitution).
Enrich is applied after Transform; if target fields conflict, the value from Enrich overwrites the Transform result.
Filtering and delivery of security events
After a security event is formed, you must define where it should be delivered. For this, you need to:
- configure security event storages;
- configure event delivery rules to storages.
Storage configuration
Storages are configured via ClusterSecurityEventDestination.
Storage types are aligned with the log-shipper ecosystem.
For in-cluster security event storage, automatic Loki destination configuration is available when the corresponding module option is enabled.
Example:
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...Delivery rule configuration
When configuring delivery rules, you need to define:
- which source events are sent;
- minimum severity level for sending;
- target storages.
For this, use ClusterSecurityEventConfig.
The resource defines sources (exact names or masks), minimum severity, and an array of storages (resources of type ClusterSecurityEventDestination) that receive selected events.
Example:
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
# OR
# enabledSourcesMasks:
# - clusterSecurityEventShipper/kube-audit/*
# - podSecurityEventShipper/*
destinations:
- cluster-lokiDefault module settings
If module settings are not explicitly specified, the following objects are created in the cluster:
-
ClusterSecurityEventConfig— configures security event delivery to destinations. The following settings are used by default:apiVersion: security.deckhouse.io/v1alpha1 kind: ClusterSecurityEventConfig metadata: name: default spec: defaultSeverityThreshold: Medium destinations: - cluster-loki enabledSourcesMasks: - podSecurityEventShipper/* - clusterSecurityEventShipper/*Configuration of these parameters is controlled by module setting
securityEventConfig. -
ClusterSecurityEventDestination— configures security event storage. By default, an object is generated that allows sending security events to the in-clusterlokiservice:apiVersion: security.deckhouse.io/v1alpha1 kind: ClusterSecurityEventDestination metadata: name: cluster-loki spec: type: Loki loki: auth: strategy: Bearer token: <token> # Filled automatically endpoint: https://loki.d8-monitoring:3100You can disable generation of the default CSED via the dedicated parameter
clusterSecurityEventDestination.clusterLoki.