OpenSearch and Wazuh Integration - Building a Comprehensive Security Analytics Platform
The integration of OpenSearch with Wazuh creates a powerful, open-source security information and event management (SIEM) platform. This comprehensive guide explores the architecture, implementation details, and best practices for deploying this solution at scale.
Table of Contents
Architecture Overview
The OpenSearch-Wazuh stack combines the search and analytics capabilities of OpenSearch with Wazuh’s security monitoring and threat detection features. This integration provides real-time visibility into security events across your infrastructure.
graph TB subgraph "Data Sources" subgraph "Endpoints" Linux[Linux Servers] Windows[Windows Servers] Network[Network Devices] Cloud[Cloud Resources] Apps[Applications] end end
subgraph "Collection Layer" subgraph "Wazuh Agents" LA[Linux Agent] WA[Windows Agent] AL[Agentless] end
subgraph "Log Collectors" Syslog[Syslog Collector] Beats[Beats/Logstash] API[API Collectors] end end
subgraph "Processing Layer" subgraph "Wazuh Manager Cluster" WM1[Wazuh Manager 1<br/>(Master)] WM2[Wazuh Manager 2<br/>(Worker)] WM3[Wazuh Manager 3<br/>(Worker)]
subgraph "Manager Components" Analysisd[Analysis Engine] Remoted[Remote Daemon] Monitord[Monitor Daemon] Logcollector[Log Collector] Integratord[Integration Daemon] end end
WazuhAPI[Wazuh API] Filebeat[Filebeat] end
subgraph "Storage Layer" subgraph "OpenSearch Cluster" OS1[OpenSearch Node 1<br/>(Master Eligible)] OS2[OpenSearch Node 2<br/>(Master Eligible)] OS3[OpenSearch Node 3<br/>(Master Eligible)] OS4[OpenSearch Node 4<br/>(Data)] OS5[OpenSearch Node 5<br/>(Data)] OS6[OpenSearch Node 6<br/>(Ingest)] end end
subgraph "Visualization Layer" OSD[OpenSearch Dashboards] WazuhApp[Wazuh App Plugin] Kibana[Alternative: Kibana] end
subgraph "Security Layer" Certs[Certificate Authority] LDAP[LDAP/AD Integration] RBAC[Role-Based Access] end
Linux --> LA Windows --> WA Network --> Syslog Cloud --> API Apps --> Beats
LA --> Remoted WA --> Remoted AL --> Remoted Syslog --> Logcollector Beats --> OS6 API --> Integratord
Remoted --> Analysisd Logcollector --> Analysisd Integratord --> Analysisd
Analysisd --> Monitord Monitord --> Filebeat
WM1 -.->|Cluster Sync| WM2 WM1 -.->|Cluster Sync| WM3
Filebeat --> OS6
OS1 -.->|Cluster| OS2 OS2 -.->|Cluster| OS3 OS3 -.->|Cluster| OS4 OS4 -.->|Cluster| OS5 OS5 -.->|Cluster| OS6
OS1 --> OSD WazuhAPI --> WazuhApp WazuhApp --> OSD
Certs --> WM1 Certs --> OS1 LDAP --> OSD RBAC --> WazuhApp
style WM1 fill:#f96,stroke:#333,stroke-width:4px style OS1 fill:#9f9,stroke:#333,stroke-width:4px style OSD fill:#99f,stroke:#333,stroke-width:4px
Component Responsibilities
- Wazuh Agents: Collect logs, monitor file integrity, detect rootkits, and perform vulnerability scanning
- Wazuh Manager: Process and analyze security events, manage agents, and coordinate responses
- OpenSearch: Store and index security data for fast retrieval and analysis
- OpenSearch Dashboards: Visualize security data and provide interactive dashboards
- Wazuh App: Extend OpenSearch Dashboards with Wazuh-specific features
Data Flow Diagram
Understanding how data flows through the system is crucial for troubleshooting and optimization:
sequenceDiagram participant Agent as Wazuh Agent participant Manager as Wazuh Manager participant Filebeat as Filebeat participant OpenSearch as OpenSearch participant Dashboard as OpenSearch Dashboards participant User as Security Analyst
Note over Agent,User: Real-time Event Collection and Processing
Agent->>Agent: Collect logs/events Agent->>Agent: Local analysis
Agent->>Manager: Send events (1514/tcp) Note over Agent,Manager: Encrypted with pre-shared key
Manager->>Manager: Decode & normalize Manager->>Manager: Rule evaluation Manager->>Manager: Threat detection
alt Alert triggered Manager->>Manager: Generate alert Manager->>Manager: Enrich with context end
Manager->>Manager: Store in local queue Manager->>Filebeat: Read alerts.json
Filebeat->>Filebeat: Parse JSON Filebeat->>OpenSearch: Bulk index (9200/tcp) Note over Filebeat,OpenSearch: TLS encrypted
OpenSearch->>OpenSearch: Index documents OpenSearch->>OpenSearch: Update mappings
User->>Dashboard: Access UI (5601/tcp) Dashboard->>OpenSearch: Query data OpenSearch->>Dashboard: Return results Dashboard->>User: Display visualizations
opt Real-time monitoring loop Every 5 seconds Dashboard->>OpenSearch: Refresh query OpenSearch->>Dashboard: Updated data Dashboard->>User: Update display end end
opt Active Response User->>Dashboard: Trigger response Dashboard->>Manager: API call (55000/tcp) Manager->>Agent: Execute command Agent->>Agent: Perform action Agent->>Manager: Report result end
Data Processing Pipeline
# Pipeline stages with processing detailspipeline: - stage: collection components: - wazuh_agent: functions: - log_collection - file_integrity_monitoring - system_calls_monitoring - command_monitoring output: raw_events
- stage: normalization components: - wazuh_manager: functions: - decode_events - extract_fields - normalize_timestamps - enrich_metadata output: normalized_events
- stage: analysis components: - analysis_engine: functions: - rule_matching - correlation - threat_intelligence - anomaly_detection output: alerts
- stage: indexing components: - opensearch: functions: - document_parsing - field_mapping - indexing - replication output: searchable_data
- stage: visualization components: - dashboards: functions: - query_execution - aggregation - visualization - reporting output: insights
Security Certificate Chain
Security is paramount in a SIEM deployment. Here’s how the certificate chain ensures secure communication:
graph TB subgraph "Certificate Authority Infrastructure" RootCA[Root CA<br/>CN=Wazuh Root CA] IntermediateCA[Intermediate CA<br/>CN=Wazuh Intermediate CA] end
subgraph "Server Certificates" subgraph "Wazuh Certificates" WazuhAPI[Wazuh API<br/>CN=wazuh-api.domain.com] WazuhAuth[Wazuh Authd<br/>CN=wazuh-authd.domain.com] WazuhCluster[Wazuh Cluster<br/>CN=wazuh-cluster.domain.com] end
subgraph "OpenSearch Certificates" OSNode[Node Certificates<br/>CN=os-node-*.domain.com] OSAdmin[Admin Certificate<br/>CN=os-admin.domain.com] OSTransport[Transport Certificate<br/>CN=os-transport.domain.com] OSHTTP[HTTP Certificate<br/>CN=os-http.domain.com] end
subgraph "Dashboard Certificates" OSDash[OpenSearch Dashboards<br/>CN=dashboards.domain.com] WazuhApp[Wazuh App<br/>CN=wazuh-app.domain.com] end end
subgraph "Client Certificates" FilebeatCert[Filebeat Client<br/>CN=filebeat.domain.com] AgentCert[Agent Certificates<br/>CN=agent-*.domain.com] UserCert[User Certificates<br/>CN=user@domain.com] end
RootCA --> IntermediateCA
IntermediateCA --> WazuhAPI IntermediateCA --> WazuhAuth IntermediateCA --> WazuhCluster
IntermediateCA --> OSNode IntermediateCA --> OSAdmin IntermediateCA --> OSTransport IntermediateCA --> OSHTTP
IntermediateCA --> OSDash IntermediateCA --> WazuhApp
IntermediateCA --> FilebeatCert IntermediateCA --> AgentCert IntermediateCA --> UserCert
style RootCA fill:#f96,stroke:#333,stroke-width:4px style IntermediateCA fill:#ff9,stroke:#333,stroke-width:2px style OSNode fill:#9f9,stroke:#333,stroke-width:2px
Certificate Generation Script
#!/bin/bash# Generate complete certificate chain for Wazuh-OpenSearch deployment
set -e
# ConfigurationCERT_DIR="/etc/wazuh-certificates"DAYS_VALID=3650KEY_SIZE=4096COUNTRY="US"STATE="California"CITY="San Francisco"ORG="Security Organization"OU="Security Operations"
# Create certificate directorymkdir -p ${CERT_DIR}/{ca,server,client}
# Generate Root CAecho "Generating Root CA..."openssl genrsa -out ${CERT_DIR}/ca/root-ca-key.pem ${KEY_SIZE}openssl req -new -x509 -sha256 -days ${DAYS_VALID} \ -key ${CERT_DIR}/ca/root-ca-key.pem \ -out ${CERT_DIR}/ca/root-ca.pem \ -subj "/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=${OU}/CN=Wazuh Root CA"
# Generate Intermediate CAecho "Generating Intermediate CA..."openssl genrsa -out ${CERT_DIR}/ca/intermediate-ca-key.pem ${KEY_SIZE}openssl req -new -sha256 \ -key ${CERT_DIR}/ca/intermediate-ca-key.pem \ -out ${CERT_DIR}/ca/intermediate-ca.csr \ -subj "/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=${OU}/CN=Wazuh Intermediate CA"
# Sign Intermediate CAopenssl x509 -req -days ${DAYS_VALID} -sha256 \ -in ${CERT_DIR}/ca/intermediate-ca.csr \ -CA ${CERT_DIR}/ca/root-ca.pem \ -CAkey ${CERT_DIR}/ca/root-ca-key.pem \ -CAcreateserial \ -out ${CERT_DIR}/ca/intermediate-ca.pem \ -extensions v3_intermediate_ca \ -extfile <(cat <<EOF[v3_intermediate_ca]subjectKeyIdentifier = hashauthorityKeyIdentifier = keyid:always,issuerbasicConstraints = critical, CA:true, pathlen:0keyUsage = critical, digitalSignature, cRLSign, keyCertSignEOF)
# Create certificate chaincat ${CERT_DIR}/ca/intermediate-ca.pem ${CERT_DIR}/ca/root-ca.pem > ${CERT_DIR}/ca/ca-chain.pem
# Function to generate server certificatesgenerate_server_cert() { local name=$1 local cn=$2 local san=$3
echo "Generating certificate for ${name}..."
# Generate private key openssl genrsa -out ${CERT_DIR}/server/${name}-key.pem ${KEY_SIZE}
# Generate CSR openssl req -new -sha256 \ -key ${CERT_DIR}/server/${name}-key.pem \ -out ${CERT_DIR}/server/${name}.csr \ -subj "/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=${OU}/CN=${cn}"
# Sign certificate openssl x509 -req -days ${DAYS_VALID} -sha256 \ -in ${CERT_DIR}/server/${name}.csr \ -CA ${CERT_DIR}/ca/intermediate-ca.pem \ -CAkey ${CERT_DIR}/ca/intermediate-ca-key.pem \ -CAcreateserial \ -out ${CERT_DIR}/server/${name}.pem \ -extensions v3_server \ -extfile <(cat <<EOF[v3_server]subjectKeyIdentifier = hashauthorityKeyIdentifier = keyid,issuerbasicConstraints = CA:FALSEkeyUsage = critical, digitalSignature, keyEnciphermentextendedKeyUsage = serverAuth, clientAuthsubjectAltName = ${san}EOF)
# Create full chain cat ${CERT_DIR}/server/${name}.pem ${CERT_DIR}/ca/ca-chain.pem > ${CERT_DIR}/server/${name}-chain.pem}
# Generate OpenSearch node certificatesfor i in {1..6}; do generate_server_cert "opensearch-node${i}" \ "opensearch-node${i}.domain.com" \ "DNS:opensearch-node${i}.domain.com,DNS:opensearch-node${i},IP:10.0.1.${i}"done
# Generate OpenSearch admin certificategenerate_server_cert "opensearch-admin" \ "opensearch-admin.domain.com" \ "DNS:opensearch-admin.domain.com,DNS:localhost,IP:127.0.0.1"
# Generate Wazuh certificatesgenerate_server_cert "wazuh-manager" \ "wazuh-manager.domain.com" \ "DNS:wazuh-manager.domain.com,DNS:wazuh,IP:10.0.2.1"
generate_server_cert "wazuh-dashboard" \ "wazuh-dashboard.domain.com" \ "DNS:wazuh-dashboard.domain.com,DNS:dashboard,IP:10.0.2.2"
# Set appropriate permissionschmod 400 ${CERT_DIR}/ca/*-key.pemchmod 400 ${CERT_DIR}/server/*-key.pemchmod 444 ${CERT_DIR}/ca/*.pemchmod 444 ${CERT_DIR}/server/*.pem
echo "Certificate generation complete!"
Deployment Architecture
Production Deployment Topology
graph TB subgraph "DMZ" LB[Load Balancer<br/>HAProxy/Nginx] WAF[Web Application Firewall] end
subgraph "Application Tier" subgraph "Wazuh Managers" WM1[Wazuh Manager 1<br/>Master Node<br/>10.0.2.1] WM2[Wazuh Manager 2<br/>Worker Node<br/>10.0.2.2] WM3[Wazuh Manager 3<br/>Worker Node<br/>10.0.2.3] end
subgraph "OpenSearch Dashboards" OSD1[Dashboard 1<br/>10.0.3.1] OSD2[Dashboard 2<br/>10.0.3.2] end end
subgraph "Data Tier" subgraph "OpenSearch Cluster" subgraph "Master Nodes" OSM1[Master 1<br/>10.0.4.1] OSM2[Master 2<br/>10.0.4.2] OSM3[Master 3<br/>10.0.4.3] end
subgraph "Data Nodes" OSD1_data[Data 1<br/>10.0.4.4] OSD2_data[Data 2<br/>10.0.4.5] OSD3_data[Data 3<br/>10.0.4.6] OSD4_data[Data 4<br/>10.0.4.7] end
subgraph "Ingest Nodes" OSI1[Ingest 1<br/>10.0.4.8] OSI2[Ingest 2<br/>10.0.4.9] end end end
subgraph "Storage Tier" NFS[NFS Storage<br/>Snapshots] S3[S3 Compatible<br/>Long-term Storage] end
subgraph "Monitoring" Prometheus[Prometheus] Grafana[Grafana] AlertManager[AlertManager] end
LB --> WAF WAF --> OSD1 WAF --> OSD2
OSD1 --> OSM1 OSD2 --> OSM1
WM1 -.->|Cluster| WM2 WM2 -.->|Cluster| WM3
WM1 --> OSI1 WM2 --> OSI2 WM3 --> OSI1
OSM1 -.->|Coordination| OSM2 OSM2 -.->|Coordination| OSM3
OSI1 --> OSD1_data OSI2 --> OSD2_data
OSD1_data -.->|Replication| OSD2_data OSD2_data -.->|Replication| OSD3_data OSD3_data -.->|Replication| OSD4_data
OSD1_data --> NFS OSD1_data --> S3
Prometheus --> WM1 Prometheus --> OSM1 Prometheus --> Grafana Grafana --> AlertManager
style LB fill:#f96,stroke:#333,stroke-width:2px style WM1 fill:#9f9,stroke:#333,stroke-width:2px style OSM1 fill:#99f,stroke:#333,stroke-width:2px
Installation and Configuration
OpenSearch Cluster Setup
# opensearch.yml - Master node configurationcluster.name: wazuh-security-clusternode.name: opensearch-master-1node.roles: [master]
network.host: 10.0.4.1discovery.seed_hosts: - 10.0.4.1 - 10.0.4.2 - 10.0.4.3cluster.initial_master_nodes: - opensearch-master-1 - opensearch-master-2 - opensearch-master-3
# Security settingsplugins.security.ssl.transport.pemcert_filepath: certificates/opensearch-node1.pemplugins.security.ssl.transport.pemkey_filepath: certificates/opensearch-node1-key.pemplugins.security.ssl.transport.pemtrustedcas_filepath: certificates/ca-chain.pemplugins.security.ssl.transport.enforce_hostname_verification: trueplugins.security.ssl.transport.resolve_hostname: true
plugins.security.ssl.http.enabled: trueplugins.security.ssl.http.pemcert_filepath: certificates/opensearch-node1.pemplugins.security.ssl.http.pemkey_filepath: certificates/opensearch-node1-key.pemplugins.security.ssl.http.pemtrustedcas_filepath: certificates/ca-chain.pem
plugins.security.allow_unsafe_democertificates: falseplugins.security.allow_default_init_securityindex: falseplugins.security.authcz.admin_dn: - "CN=opensearch-admin.domain.com,OU=Security Operations,O=Security Organization,L=San Francisco,ST=California,C=US"
plugins.security.audit.type: internal_opensearchplugins.security.enable_snapshot_restore_privilege: trueplugins.security.check_snapshot_restore_write_privileges: trueplugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]
# Performance tuningindices.memory.index_buffer_size: 20%indices.queries.cache.size: 15%indices.fielddata.cache.size: 30%thread_pool.search.size: 50thread_pool.search.queue_size: 1000thread_pool.write.size: 30thread_pool.write.queue_size: 500
# Cluster routingcluster.routing.allocation.disk.threshold_enabled: truecluster.routing.allocation.disk.watermark.low: 85%cluster.routing.allocation.disk.watermark.high: 90%cluster.routing.allocation.disk.watermark.flood_stage: 95%
Wazuh Manager Configuration
<!-- ossec.conf - Wazuh Manager configuration --><ossec_config> <global> <jsonout_output>yes</jsonout_output> <alerts_log>yes</alerts_log> <logall>no</logall> <logall_json>no</logall_json> <email_notification>no</email_notification> <smtp_server>smtp.domain.com</smtp_server> <email_from>wazuh@domain.com</email_from> <email_to>security@domain.com</email_to> <email_maxperhour>12</email_maxperhour> <queue_size>131072</queue_size> </global>
<cluster> <name>wazuh-cluster</name> <node_name>wazuh-master</node_name> <node_type>master</node_type> <key>5f4dcc3b5aa765d61d8327deb882cf99</key> <port>1516</port> <bind_addr>0.0.0.0</bind_addr> <nodes> <node>10.0.2.1</node> <node>10.0.2.2</node> <node>10.0.2.3</node> </nodes> <hidden>no</hidden> <disabled>no</disabled> </cluster>
<remote> <connection>secure</connection> <port>1514</port> <protocol>tcp</protocol> <queue_size>131072</queue_size> </remote>
<alerts> <log_alert_level>3</log_alert_level> <email_alert_level>7</email_alert_level> </alerts>
<command> <name>firewall-drop</name> <executable>firewall-drop</executable> <timeout_allowed>yes</timeout_allowed> </command>
<active-response> <command>firewall-drop</command> <location>local</location> <level>7</level> <timeout>600</timeout> </active-response>
<!-- OpenSearch output configuration --> <integration> <name>opensearch</name> <enabled>yes</enabled> <url>https://10.0.4.8:9200</url> <username>wazuh_indexer</username> <password>SecurePassword123!</password> <indices> <alerts>wazuh-alerts-*</alerts> <archives>wazuh-archives-*</archives> </indices> <ssl> <certificate>/etc/wazuh/certificates/wazuh-manager.pem</certificate> <key>/etc/wazuh/certificates/wazuh-manager-key.pem</key> <ca>/etc/wazuh/certificates/ca-chain.pem</ca> </ssl> </integration></ossec_config>
Index Lifecycle Management
graph LR subgraph "Index Lifecycle" Hot[Hot Phase<br/>0-7 days<br/>Primary shards] Warm[Warm Phase<br/>7-30 days<br/>Shrink & merge] Cold[Cold Phase<br/>30-90 days<br/>Readonly] Delete[Delete Phase<br/>>90 days] end
subgraph "Storage Tiers" SSD[SSD Storage<br/>High IOPS] HDD[HDD Storage<br/>High capacity] S3[S3 Storage<br/>Archive] end
Hot --> Warm Warm --> Cold Cold --> Delete
Hot -.-> SSD Warm -.-> HDD Cold -.-> S3
style Hot fill:#f96,stroke:#333,stroke-width:2px style SSD fill:#9f9,stroke:#333,stroke-width:2px
// Index lifecycle policy{ "policy": { "phases": { "hot": { "min_age": "0ms", "actions": { "rollover": { "max_primary_shard_size": "50GB", "max_age": "7d" }, "set_priority": { "priority": 100 } } }, "warm": { "min_age": "7d", "actions": { "shrink": { "number_of_shards": 1 }, "forcemerge": { "max_num_segments": 1 }, "set_priority": { "priority": 50 }, "allocate": { "node_type": "warm" } } }, "cold": { "min_age": "30d", "actions": { "set_priority": { "priority": 0 }, "freeze": {}, "allocate": { "node_type": "cold" }, "searchable_snapshot": { "snapshot_repository": "s3_repository" } } }, "delete": { "min_age": "90d", "actions": { "delete": {} } } } }}
Performance Optimization
Query Performance Tuning
graph TB subgraph "Query Optimization" subgraph "Index Design" Mapping[Optimized Mappings] Sharding[Shard Strategy] Replicas[Replica Count] end
subgraph "Query Patterns" Filters[Use Filters] Aggregations[Efficient Aggregations] Scripts[Avoid Scripts] end
subgraph "Caching" QueryCache[Query Cache] FieldCache[Field Data Cache] RequestCache[Request Cache] end end
Mapping --> Performance[Query Performance] Sharding --> Performance Replicas --> Performance
Filters --> Performance Aggregations --> Performance Scripts --> Performance
QueryCache --> Performance FieldCache --> Performance RequestCache --> Performance
style Performance fill:#9f9,stroke:#333,stroke-width:2px
Index Template Optimization
// Optimized index template for Wazuh alerts{ "index_patterns": ["wazuh-alerts-*"], "priority": 100, "template": { "settings": { "number_of_shards": 3, "number_of_replicas": 1, "index.refresh_interval": "10s", "index.translog.durability": "async", "index.translog.sync_interval": "10s", "index.codec": "best_compression", "index.merge.scheduler.max_thread_count": 2, "index.merge.policy.max_merged_segment": "5gb" }, "mappings": { "properties": { "@timestamp": { "type": "date", "format": "date_time_no_millis" }, "agent": { "properties": { "id": { "type": "keyword" }, "name": { "type": "keyword" }, "ip": { "type": "ip" } } }, "rule": { "properties": { "id": { "type": "keyword" }, "level": { "type": "short" }, "description": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }, "data": { "type": "object", "enabled": true } } } }}
Security Hardening
Security Architecture Layers
graph TB subgraph "Security Layers" subgraph "Network Security" FW[Firewall Rules] VLAN[VLAN Segmentation] VPN[VPN Access] end
subgraph "Application Security" TLS[TLS Encryption] Auth[Authentication] Authz[Authorization] end
subgraph "Data Security" EncRest[Encryption at Rest] EncTransit[Encryption in Transit] DataMask[Data Masking] end
subgraph "Operational Security" Audit[Audit Logging] Monitor[Security Monitoring] Response[Incident Response] end end
FW --> SecureStack[Secure Stack] VLAN --> SecureStack VPN --> SecureStack
TLS --> SecureStack Auth --> SecureStack Authz --> SecureStack
EncRest --> SecureStack EncTransit --> SecureStack DataMask --> SecureStack
Audit --> SecureStack Monitor --> SecureStack Response --> SecureStack
style SecureStack fill:#f96,stroke:#333,stroke-width:2px
Security Configuration
_meta: type: "config" config_version: 2
config: dynamic: http: anonymous_auth_enabled: false xff: enabled: true internalProxies: '10\\.0\\.0\\.0/8' remoteIpHeader: "x-forwarded-for"
authc: internal_auth: description: "Internal users" http_enabled: true transport_enabled: true order: 0 http_authenticator: type: basic challenge: true authentication_backend: type: internal
ldap_auth: description: "LDAP authentication" http_enabled: true transport_enabled: true order: 1 http_authenticator: type: basic challenge: false authentication_backend: type: ldap config: enable_ssl: true enable_start_tls: false enable_ssl_client_auth: false verify_hostnames: true hosts: - ldap.domain.com:636 bind_dn: "cn=admin,dc=domain,dc=com" password: "ldap_password" userbase: "ou=users,dc=domain,dc=com" usersearch: "(sAMAccountName={0})" username_attribute: "sAMAccountName"
authz: roles_from_myldap: description: "LDAP authorization" http_enabled: true transport_enabled: true authorization_backend: type: ldap config: enable_ssl: true enable_start_tls: false enable_ssl_client_auth: false verify_hostnames: true hosts: - ldap.domain.com:636 bind_dn: "cn=admin,dc=domain,dc=com" password: "ldap_password" rolebase: "ou=groups,dc=domain,dc=com" rolesearch: "(member={0})" userroleattribute: null userrolename: "memberOf" rolename: "cn" resolve_nested_roles: true skip_users: - "kibanaserver" - "admin"
Monitoring and Alerting
Monitoring Architecture
graph TB subgraph "Metrics Collection" WazuhMetrics[Wazuh Metrics] OSMetrics[OpenSearch Metrics] NodeMetrics[Node Exporter] ProcessMetrics[Process Exporter] end
subgraph "Processing" Prometheus[Prometheus Server] AlertManager[Alert Manager] end
subgraph "Visualization" Grafana[Grafana] StatusPage[Status Page] end
subgraph "Alerting Channels" Email[Email] Slack[Slack] PagerDuty[PagerDuty] Webhook[Webhooks] end
WazuhMetrics --> Prometheus OSMetrics --> Prometheus NodeMetrics --> Prometheus ProcessMetrics --> Prometheus
Prometheus --> AlertManager Prometheus --> Grafana
AlertManager --> Email AlertManager --> Slack AlertManager --> PagerDuty AlertManager --> Webhook
Grafana --> StatusPage
style Prometheus fill:#f96,stroke:#333,stroke-width:2px style Grafana fill:#9f9,stroke:#333,stroke-width:2px
Key Performance Indicators
# Prometheus alert rulesgroups: - name: wazuh_alerts interval: 30s rules: - alert: WazuhManagerDown expr: up{job="wazuh-manager"} == 0 for: 5m labels: severity: critical annotations: summary: "Wazuh Manager is down" description: "Wazuh Manager {{ $labels.instance }} has been down for more than 5 minutes."
- alert: HighAlertRate expr: rate(wazuh_alerts_total[5m]) > 100 for: 10m labels: severity: warning annotations: summary: "High alert rate detected" description: "Alert rate is {{ $value }} alerts/sec"
- name: opensearch_alerts interval: 30s rules: - alert: OpenSearchClusterRed expr: opensearch_cluster_health_status{color="red"} == 1 for: 5m labels: severity: critical annotations: summary: "OpenSearch cluster is RED" description: "OpenSearch cluster health is RED for more than 5 minutes"
- alert: HighJVMMemoryUsage expr: opensearch_jvm_memory_used_bytes / opensearch_jvm_memory_max_bytes > 0.9 for: 10m labels: severity: warning annotations: summary: "High JVM memory usage" description: "JVM memory usage is {{ $value | humanizePercentage }}"
Disaster Recovery
Backup and Recovery Strategy
graph TB subgraph "Backup Components" subgraph "Configuration" WazuhConf[Wazuh Config] OSConf[OpenSearch Config] Rules[Custom Rules] Decoders[Custom Decoders] end
subgraph "Data" Indices[OpenSearch Indices] Snapshots[Snapshots] Logs[Raw Logs] end
subgraph "State" AgentKeys[Agent Keys] ClusterState[Cluster State] UserData[User Data] end end
subgraph "Backup Storage" Local[Local Backup] Remote[Remote Storage] Cloud[Cloud Storage] end
subgraph "Recovery Process" Restore[Restore Process] Validate[Validation] Failover[Failover] end
WazuhConf --> Local OSConf --> Local Rules --> Local Decoders --> Local
Indices --> Snapshots Snapshots --> Remote Logs --> Cloud
AgentKeys --> Local ClusterState --> Remote UserData --> Remote
Local --> Restore Remote --> Restore Cloud --> Restore
Restore --> Validate Validate --> Failover
style Snapshots fill:#f96,stroke:#333,stroke-width:2px style Restore fill:#9f9,stroke:#333,stroke-width:2px
Automated Backup Script
#!/bin/bash# Automated backup script for Wazuh-OpenSearch stack
set -e
# ConfigurationBACKUP_DIR="/backup"S3_BUCKET="s3://wazuh-backups"RETENTION_DAYS=30DATE=$(date +%Y%m%d-%H%M%S)
# Create backup directoriesmkdir -p ${BACKUP_DIR}/{wazuh,opensearch,config}/${DATE}
# Backup Wazuh configurationecho "Backing up Wazuh configuration..."tar czf ${BACKUP_DIR}/wazuh/${DATE}/wazuh-config.tar.gz \ /var/ossec/etc \ /var/ossec/rules \ /var/ossec/decoders \ /var/ossec/lists
# Backup Wazuh agent keysecho "Backing up agent keys..."cp /var/ossec/etc/client.keys ${BACKUP_DIR}/wazuh/${DATE}/
# Backup OpenSearch configurationecho "Backing up OpenSearch configuration..."tar czf ${BACKUP_DIR}/opensearch/${DATE}/opensearch-config.tar.gz \ /etc/opensearch \ /usr/share/opensearch/config
# Create OpenSearch snapshotecho "Creating OpenSearch snapshot..."curl -X PUT "https://localhost:9200/_snapshot/backup_repo/${DATE}?wait_for_completion=true" \ -H 'Content-Type: application/json' \ -u admin:admin \ --cacert /etc/opensearch/ca.pem \ -d '{ "indices": "wazuh-*", "include_global_state": true, "metadata": { "taken_by": "automated_backup", "taken_because": "scheduled_backup" } }'
# Sync to S3echo "Syncing to S3..."aws s3 sync ${BACKUP_DIR}/ ${S3_BUCKET}/ --exclude "*.tmp"
# Clean up old local backupsecho "Cleaning up old backups..."find ${BACKUP_DIR} -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} \;
# Verify backupecho "Verifying backup..."if aws s3 ls ${S3_BUCKET}/${DATE}/ > /dev/null 2>&1; then echo "Backup completed successfully"else echo "Backup verification failed" exit 1fi
# Send notificationcurl -X POST https://slack.webhook.url \ -H 'Content-Type: application/json' \ -d "{\"text\":\"Wazuh-OpenSearch backup completed successfully for ${DATE}\"}"
Troubleshooting Guide
Common Issues and Solutions
Component | Issue | Symptoms | Solution |
---|---|---|---|
Wazuh Agent | Connection Failed | Unable to connect to manager | Check firewall rules, verify authd service, regenerate agent key |
OpenSearch | Cluster Red Status | Unassigned shards | Check disk space, verify node connectivity, force shard allocation |
Filebeat | Pipeline Blocked | High memory usage | Increase queue size, check OpenSearch performance |
Dashboard | Login Failed | Authentication error | Verify certificates, check user permissions, review auth logs |
Integration | No Data Flow | Empty indices | Check Filebeat configuration, verify index patterns |
Debug Commands
# Wazuh Manager debugging/var/ossec/bin/wazuh-control info/var/ossec/bin/wazuh-control statustail -f /var/ossec/logs/ossec.log
# Check cluster status/var/ossec/bin/cluster_control -l
# OpenSearch cluster healthcurl -X GET "https://localhost:9200/_cluster/health?pretty" \ -u admin:admin --cacert /etc/opensearch/ca.pem
# Check indicescurl -X GET "https://localhost:9200/_cat/indices?v" \ -u admin:admin --cacert /etc/opensearch/ca.pem
# Filebeat statussystemctl status filebeatfilebeat test configfilebeat test output
# Certificate validationopenssl x509 -in /path/to/cert.pem -text -nooutopenssl verify -CAfile ca.pem cert.pem
Best Practices
Deployment Checklist
-
Infrastructure Requirements
- Adequate CPU and memory resources
- SSD storage for hot data
- Network bandwidth for replication
- Backup storage capacity
-
Security Hardening
- TLS encryption enabled everywhere
- Strong authentication configured
- Role-based access control implemented
- Audit logging enabled
- Regular security updates
-
Performance Optimization
- Appropriate shard sizing (20-50GB)
- Index lifecycle policies configured
- Query optimization implemented
- Monitoring and alerting active
-
Operational Readiness
- Backup and recovery tested
- Disaster recovery plan documented
- Runbooks created
- Team trained
- Support contracts in place
Scaling Considerations
graph LR subgraph "Scaling Dimensions" Vertical[Vertical Scaling<br/>More resources] Horizontal[Horizontal Scaling<br/>More nodes] Functional[Functional Scaling<br/>Dedicated roles] end
subgraph "Scaling Triggers" CPU[CPU > 80%] Memory[Memory > 85%] Storage[Storage > 85%] Latency[Query Latency > 1s] end
CPU --> Vertical Memory --> Vertical Storage --> Horizontal Latency --> Functional
style Horizontal fill:#9f9,stroke:#333,stroke-width:2px
Conclusion
The integration of OpenSearch with Wazuh creates a powerful, scalable, and secure SIEM platform capable of handling enterprise-scale security monitoring requirements. The architecture provides:
- Scalability: Horizontal scaling capabilities for both processing and storage
- High Availability: Clustered components with automatic failover
- Security: End-to-end encryption and comprehensive access control
- Performance: Optimized data flow and query performance
- Flexibility: Customizable rules, decoders, and dashboards
By following the architectural patterns, security practices, and operational procedures outlined in this guide, organizations can build a robust security analytics platform that provides real-time visibility into their security posture while maintaining the performance and reliability required for production environments.