Full-text search and analytics engine with OpenSearch Dashboards. Serves as a centralized SIEM platform when the siem attribute is enabled, receiving security events from Falco, OPA, APISIX, Audit, Trivy, and OTEL sources across one or more stacks.
| Attribute | Example | Description |
|---|---|---|
namespace REQ |
opensearch |
Kubernetes namespace for all OpenSearch resources |
admin_password REQ |
MyStr0ngP@ss |
Admin user password. Used by all sources (Falco, OPA, etc.) for authentication. Also used in the SIEM bootstrap job. |
siem |
true |
Master gate for SIEM functionality. When "true", enables the entire SIEM pipeline: index templates, dashboards, alerting monitors, ISM policies, and the bootstrap job. When not set, inbound security links still populate dunders but no SIEM files are generated. |
remote_host |
opensearch.sre.example.com |
Cross-stack endpoint. FQDN/IP for external access to this OpenSearch instance. Used by sources in other stacks (Falco, OPA, Trivy) to connect via APISIX route or load balancer on port 443 instead of internal svc on port 9200. |
When siem: "true", OpenSearch becomes a centralized Security Information and Event Management (SIEM) platform. Sources from the same stack or external stacks send security events, and the bootstrap job configures everything automatically.
falco-* index)opa* index)apisix-* index)audit-* index)trivy-* index)otel-* index)
| Link Type | Index Pattern | Alerting Monitor | Export Method |
|---|---|---|---|
falco-opensearch |
falco-* |
falco-critical-events | Falcosidekick (native output) |
opa-opensearch |
opa* |
opa-violation-events | OTEL sidecar (requires opa-otel link on OPA side) |
apisix-opensearch |
apisix-* |
apisix-error-events | OTEL collector |
audit-opensearch |
audit-* |
audit-privileged-events | OTEL collector |
trivy-opensearch |
trivy-* |
trivy-critical-vulnerabilities | Trivy exporter (direct to OpenSearch) |
otel-opensearch |
otel-* |
— | OTEL collector |
For each detected source link, the following files are generated (removed in post_gen if the link doesn't exist):
| File Pattern | Purpose |
|---|---|
| siem/index-template-{source}.json | OpenSearch index template with field mappings for the source |
| siem/alerting-{source}.json | OpenSearch alerting monitor definition (critical event detection) |
| siem/dashboards-{source}.ndjson | OpenSearch Dashboards saved objects (index pattern + visualizations + dashboard) |
| File | Purpose |
|---|---|
| siem/ism-policy.json | PCI DSS ISM retention policy (applied to all SIEM indices) |
| siem/dashboards-pci-360.ndjson | Global PCI-360 Overview dashboard (cross-stack, fixed IDs) |
| siem/dashboards-pci-overview.ndjson | Per-stack PCI Overview dashboard template |
| siem-bootstrap-job.yaml | ArgoCD PostSync Job that imports all SIEM resources into OpenSearch on every sync |
post_gen cleanup: If siem is not "true" or no SIEM source links exist, the entire k8s/deploy/base/siem/ directory and siem-bootstrap-job.yaml are removed. Per-source files (index-template, alerting, dashboard) are removed individually when their corresponding link doesn't exist.
Multiple stacks can send security events to a single centralized OpenSearch instance. Each external stack that links its Falco/OPA/APISIX/Audit/Trivy components creates a cross-stack connection.
pre_gen_project.py detects each inbound SIEM link:
if link.component.is_referenced:
# External source from another stack
stack_name = link.component.name.replace('-falco', '')
# e.g., "prod-falco" → stack_name = "prod"
__siem_stacks[stack_name].append("falco")
else:
# Local source (same stack)
__siem_local_sources.append("falco")
post_gen_project.py generates per-stack dashboard variants with prefixed IDs and titles to prevent collisions:
| Stack | Generated File | Dashboard ID | Title |
|---|---|---|---|
| sre (local) | dashboards-falco-sre.ndjson | sre-falco-pci-dashboard | sre - PCI - Runtime |
| prod (external) | dashboards-falco-prod.ndjson | prod-falco-pci-dashboard | prod - PCI - Runtime |
| staging (external) | dashboards-opa-staging.ndjson | staging-opa-pci-dashboard | staging - PCI - Policy |
No collision: Each stack's dashboards have unique IDs (prefixed with stack slug). The ?overwrite=true on import only overwrites the same stack's dashboards, not others. The global PCI-360 Overview has fixed IDs and is always safely overwritten.
ArgoCD PostSync hook (siem-bootstrap-job.yaml) runs on every sync and performs:
| Step | Action | API Endpoint |
|---|---|---|
| 1 | Wait for OpenSearch readiness (600s timeout) | init container: curl /_cluster/health |
| 2 | Create ISM retention policy (pci-dss-retention) |
PUT /_plugins/_ism/policies/ |
| 3 | Create index templates per source | PUT /_index_template/{source} |
| 4 | Apply ISM policy to existing indices | POST /_plugins/_ism/add/{source}-* |
| 5 | Create alerting monitors | POST /_plugins/_alerting/monitors |
| 6 | Create placeholder indices ({source}-init) if no indices exist yet |
PUT /{source}-init |
| 7 | Cleanup: Delete only our previously imported saved objects (extracts IDs from ndjson files + legacy ID list). Customer dashboards are never touched. | DELETE /api/saved_objects/{type}/{id} |
| 8 | Import dashboards (per-stack + global PCI-360) | POST /api/saved_objects/_import?overwrite=true |
| Link Type | Dunder | Impact |
|---|---|---|
prometheus-opensearch |
__prometheus |
Prometheus metrics exporter ServiceMonitor |
falco-opensearch |
__falco |
SIEM: index template, alerting, dashboard for Falco events |
opa-opensearch |
__opa |
SIEM: index template, alerting, dashboard for OPA violations |
apisix-opensearch |
__apisix_logs |
SIEM: index template, alerting, dashboard for API gateway logs |
audit-opensearch |
__audit |
SIEM: index template, alerting, dashboard for K8s audit logs |
trivy-opensearch |
__trivy |
SIEM: index template, alerting, dashboard for vulnerability scans |
otel-opensearch |
__otel |
SIEM: OTEL traces/logs/metrics ingestion |
opensearch-bucket |
__bucket |
MinIO bucket for snapshot/backup storage |
All source components (Falco, OPA, Trivy, etc.) use the same pattern to connect to OpenSearch:
link.component.is_external (true = external)
remote_host setup: Typically exposed via an APISIX route on the SRE/central cluster. The remote_host attribute is the FQDN that resolves to this route (e.g., opensearch.sre.stack-3.source-lab.io). Port 443 is used for HTTPS through the ingress controller.
| Step | Phase | What Happens |
|---|---|---|
| 1 | Template | Base ndjson files in siem/dashboards-{source}.ndjson define saved objects with fixed IDs |
| 2 | post_gen | Copies base ndjson per linked stack, prefixes IDs with stack slug (e.g., falco-pci-dashboard → pci-dss-stack-falco-pci-dashboard), renames titles, removes base files |
| 3 | Bootstrap Job | Deletes only our previously imported saved objects (by exact ID), then imports per-stack ndjson files + PCI-360 |
templates/opensearch/.../siem/dashboards-*.ndjsonWhen dashboard IDs change between template versions, ?overwrite=true only updates objects with the same ID — old IDs persist forever in .kibana_1. The bootstrap job now extracts all IDs from the ndjson files it will import (plus a hardcoded list of legacy IDs from older versions) and deletes only those exact objects before importing. Customer-created dashboards are never touched.
| ID Pattern | Example | Source |
|---|---|---|
| {stack}-pci-runtime | pci-dss-stack-pci-runtime | Falco |
| {stack}-pci-api-gw | pci-dss-stack-pci-api-gw | APISIX |
| {stack}-pci-policy | pci-dss-stack-pci-policy | OPA |
| {stack}-pci-audit | pci-dss-stack-pci-audit | K8s Audit |
| {stack}-pci-scan | pci-dss-stack-pci-scan | Trivy |
| {stack}-pci-overview | pci-dss-stack-pci-overview | Per-stack overview |
| pci-360-overview | pci-360-overview | Global cross-stack (fixed ID) |
ISM Lifecycle: hot (0–7d, rollover at 1d/30GB) → warm (7–90d, 1 replica, force-merged) → cold (90–365d, read-only, 0 replicas) → delete (365d+). New indices automatically pick up the ISM policy via ism_template patterns in the policy.
| Port | Service | Protocol |
|---|---|---|
| 9200 | OpenSearch REST API (internal) | HTTPS |
| 9300 | OpenSearch node-to-node transport | HTTPS |
| 5601 | OpenSearch Dashboards UI | HTTP |
| 443 | External access via APISIX route (cross-stack) | HTTPS |