The module lifecycle stage: Experimental
The module has requirements for installation
ClusterSecurityEventConfig with Loki (explicit allowlist)
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventConfig
metadata:
name: default
spec:
defaultSeverityThreshold: High
enabledSources:
- clusterSecurityEventShipper/kube-audit/kube-apiserver
destinations:
- cluster-lokiClusterSecurityEventConfig with glob masks
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventConfig
metadata:
name: default
spec:
defaultSeverityThreshold: High
enabledSourcesMasks:
- clusterSecurityEventShipper/kube-audit/*
- podSecurityEventShipper/*
destinations:
- cluster-lokiClusterSecurityEventDestination (Loki)
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: cluster-loki
spec:
type: Loki
loki:
endpoint: https://loki.d8-monitoring:3100
auth:
strategy: Bearer
token: EXAMPLE
tls:
verifyCertificate: false
verifyHostname: falseCredentials (
token,password) can also be referenced from a Secret usingtokenSecretRef/passwordSecretRefinstead of inline values. The Secret must be in thed8-security-events-managernamespace with the keyvaluein itsdatafield and labeledsecurity-events-manager.deckhouse.io/credential-secret: "true". Inline credential fields and their*SecretRefcounterparts are mutually exclusive.
SecurityEventDefinition
apiVersion: security.deckhouse.io/v1alpha1
kind: SecurityEventDefinition
metadata:
name: k8s-privilege-escalation
spec:
code: K8S_PRIV_ESC
category: Rbac
severity: High
description: "Attempt to create privileged pod or escalate permissions"
source: kube-apiserver
fields:
- name: metadata.extra.privileges
required: truePodSecurityEventShipper (KubernetesPods with inline parser)
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: my-audit
namespace: my-namespace
spec:
- source: my-audit-app
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: audit
parser:
- name: app
parser:
type: Regex
regex:
patterns:
- '^(?P<level>\w+)\s+(?P<msg>.+)$'
fields:
- name: level
type: String
produces:
- eventCode: K8S_PRIV_ESC
extract:
field: message
operator: Regex
values:
- '.*'
transform:
- key: event.severity
value: levelClusterSecurityEventShipper (File with parserRef)
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventShipper
metadata:
name: kube-audit
spec:
- source: kube-apiserver
input:
type: File
files:
- /var/log/kube-apiserver/audit.log
parserRef: audit-json
produces:
- eventCode: K8S_AUDIT_FAILWith a ClusterSecurityEventLoggingTransformationRules:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventLoggingTransformationRules
metadata:
name: audit-json
spec:
type: File
file:
paths:
- /var/log/kube-apiserver/audit.log
transform:
parser:
type: JSON
fields:
- name: stage
type: String
- name: responseStatus
type: Int
drop_raw: trueMultiple destinations (Loki + Splunk)
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: cluster-loki
spec:
type: Loki
loki:
endpoint: https://loki.example:3100
---
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: splunk-prod
spec:
type: SplunkHEC
splunkHEC:
endpoint: https://splunk.example:8088
token: YOUR_TOKEN
---
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventConfig
metadata:
name: default
spec:
defaultSeverityThreshold: Medium
enabledSourcesMasks:
- "*"
destinations:
- cluster-loki
- splunk-prodSecurityEventLoggingTransformationRules (reusable parser)
apiVersion: security.deckhouse.io/v1alpha1
kind: SecurityEventLoggingTransformationRules
metadata:
name: falco
namespace: kube-system
spec:
selector:
matchLabels:
app: runtime-audit-engine
containers:
- name: falco
parser:
type: JSON
fields:
- name: priority
type: String
- name: output
type: String
drop_raw: trueEnrichment via Plugin (k8s-pod-info)
A shipper can resolve a Pod field absent from the raw log by using enrich.source: Plugin.
For the plugin reference (required input parameters, available output values, and the
example enrich element template), see
Enrichment plugins.
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: app-audit
namespace: my-namespace
spec:
- source: my-audit-app
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: audit
parser:
- name: app
parser:
type: JSON
producesDefaults:
# k8s.pod.name / k8s.namespace.name are populated by the KubernetesPods input.
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.name
produces:
- eventCode: K8S_PRIV_ESC
extract:
field: message
operator: Regex
values:
- '.*'Container-ID mode
When the raw event carries a container runtime ID instead of pod name/namespace
(common in syscall/falco events), use the k8s-container-info plugin to resolve the
serviceAccountName, name, or namespace in one lookup:
apiVersion: security.deckhouse.io/v1alpha1
kind: PodSecurityEventShipper
metadata:
name: falco-audit
namespace: kube-system
spec:
- source: falco
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: falco
parser:
- name: falco
parser:
type: JSON
producesDefaults:
# container.id is populated by the parser from the falco JSON output.
enrich:
- target: actor.id
source: Plugin
plugin: k8s-container-info
value: serviceAccountName
args:
- key: container_id
value: container.id
produces:
- eventCode: K8S_PRIV_ESC
extract:
field: message
operator: Regex
values:
- '.*'Enrichment via Plugin (k8s-nodeuser-info)
A shipper can resolve a static-user username (nodeusers.deckhouse.io metadata.name)
from the system UID carried in the event by using enrich.source: Plugin with the
k8s-nodeuser-info plugin. For the plugin reference (required input parameters,
available output values, and the example enrich element template), see
Enrichment plugins.
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventShipper
metadata:
name: falco-nodeuser-enrich
spec:
- source: runtime-audit-engine
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: falco
parser:
- name: falco
parser:
type: JSON
producesDefaults:
# output_fields.user.uid is populated by the parser from the falco JSON output.
enrich:
- target: actor.name
source: Plugin
plugin: k8s-nodeuser-info
value: username
args:
- key: uid
value: output_fields.user.uid
produces:
- eventCode: K8S_SSH_LOGIN
extract:
field: message
operator: Regex
values:
- '.*'Enrichment via custom External plugin
Users can create External
ClusterSecurityEventEnrichmentPlugin
resources to register custom enrichment endpoints. Below is an example of an
External plugin that resolves employee info by badge ID.
First, create the CSEP resource:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventEnrichmentPlugin
metadata:
name: employee-info
spec:
type: External
description: "Resolve employee info by badge ID"
endpoint:
url: http://employee-enricher.hr-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"Then, reference it in a shipper’s enrich rule:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventShipper
metadata:
name: badge-enrich-example
spec:
- source: runtime-audit-engine
input:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: falco
parser:
- name: falco
parser:
type: JSON
producesDefaults:
# output_fields.user.badge_id is populated by the parser.
enrich:
- target: actor.name
source: Plugin
plugin: employee-info
value: username
args:
- key: badge_id
value: output_fields.user.badge_id
produces:
- eventCode: K8S_BADGE_LOGIN
extract:
field: message
operator: Regex
values:
- '.*'Buffer configuration
Production setup: Disk + Block (default)
The default buffer settings are designed for production — Disk buffer with Block overflow behavior ensures zero data loss of security events during temporary destination outages.
Module config (ModuleConfig):
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: security-events-manager
spec:
version: 1
settings:
gateway:
buffer:
type: Disk
whenFull: Block
maxSize: 512Mi
maxEvents: 500
logShipperBuffer:
type: Disk
whenFull: Block
maxSize: 257Mi # per node; must be > 256Mi, log-shipper's disk buffer minimum
maxEvents: 500Per-destination override in ClusterSecurityEventDestination (e.g., larger buffer for a remote Elasticsearch):
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: remote-elasticsearch
spec:
type: Elasticsearch
elasticsearch:
endpoint: https://es.example.com:9200
index: security-events
auth:
strategy: Bearer
tokenSecretRef:
name: es-token
buffer:
type: Disk
whenFull: Block
maxSize: 1Gi # larger buffer for unreliable remote destination
maxEvents: 500Test setup: Memory + DropNewest
For test/dev environments where data loss is acceptable and you want maximum speed without backpressure:
Module config:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: security-events-manager
spec:
version: 1
settings:
gateway:
buffer:
type: Memory
whenFull: DropNewest
maxSize: 50Mi
maxEvents: 500
logShipperBuffer:
type: Memory
whenFull: DropNewest
maxSize: 50Mi
maxEvents: 500Socket destination (CEF over syslog to SIEM)
Send security events in CEF format wrapped in RFC5424 syslog over TCP/TLS to a SIEM receiver:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: siem-syslog
spec:
type: Socket
socket:
address: "siem.example.com:6514"
mode: TCP
tls:
verifyCertificate: true
encoding:
codec: CEF
syslogWrapper: RFC5424
cef:
deviceVendor: MyCompany
deviceProduct: k8s-security
---
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventConfig
metadata:
name: default
spec:
destinations:
- siem-syslog
enabledSourcesMasks:
- "clusterSecurityEventShipper/*"
- "podSecurityEventShipper/*"
defaultSeverityThreshold: LowSocket destination (raw JSON over UDP)
Send events as JSON over UDP (fire-and-forget, no TLS):
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: udp-collector
spec:
type: Socket
socket:
address: "collector.example.com:514"
mode: UDPSocket destination (Unix socket for sidecar SIEM agent)
Send events to a local Unix domain socket (e.g. for a sidecar SIEM agent):
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: sidecar-siem
spec:
type: Socket
socket:
address: "/var/run/siem.sock"
mode: UnixPer-destination override:
apiVersion: security.deckhouse.io/v1alpha1
kind: ClusterSecurityEventDestination
metadata:
name: test-loki
spec:
type: Loki
loki:
endpoint: http://loki:3100
buffer:
type: Memory
whenFull: DropNewest
maxSize: 50Mi
maxEvents: 500