2829 words
14 minutes
OpenSearch and Wazuh Integration - Building a Comprehensive Security Analytics Platform

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#

  1. Wazuh Agents: Collect logs, monitor file integrity, detect rootkits, and perform vulnerability scanning
  2. Wazuh Manager: Process and analyze security events, manage agents, and coordinate responses
  3. OpenSearch: Store and index security data for fast retrieval and analysis
  4. OpenSearch Dashboards: Visualize security data and provide interactive dashboards
  5. 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 details
pipeline:
- 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
# Configuration
CERT_DIR="/etc/wazuh-certificates"
DAYS_VALID=3650
KEY_SIZE=4096
COUNTRY="US"
STATE="California"
CITY="San Francisco"
ORG="Security Organization"
OU="Security Operations"
# Create certificate directory
mkdir -p ${CERT_DIR}/{ca,server,client}
# Generate Root CA
echo "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 CA
echo "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 CA
openssl 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 = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOF
)
# Create certificate chain
cat ${CERT_DIR}/ca/intermediate-ca.pem ${CERT_DIR}/ca/root-ca.pem > ${CERT_DIR}/ca/ca-chain.pem
# Function to generate server certificates
generate_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 = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = ${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 certificates
for 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 certificate
generate_server_cert "opensearch-admin" \
"opensearch-admin.domain.com" \
"DNS:opensearch-admin.domain.com,DNS:localhost,IP:127.0.0.1"
# Generate Wazuh certificates
generate_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 permissions
chmod 400 ${CERT_DIR}/ca/*-key.pem
chmod 400 ${CERT_DIR}/server/*-key.pem
chmod 444 ${CERT_DIR}/ca/*.pem
chmod 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 configuration
cluster.name: wazuh-security-cluster
node.name: opensearch-master-1
node.roles: [master]
network.host: 10.0.4.1
discovery.seed_hosts:
- 10.0.4.1
- 10.0.4.2
- 10.0.4.3
cluster.initial_master_nodes:
- opensearch-master-1
- opensearch-master-2
- opensearch-master-3
# Security settings
plugins.security.ssl.transport.pemcert_filepath: certificates/opensearch-node1.pem
plugins.security.ssl.transport.pemkey_filepath: certificates/opensearch-node1-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: certificates/ca-chain.pem
plugins.security.ssl.transport.enforce_hostname_verification: true
plugins.security.ssl.transport.resolve_hostname: true
plugins.security.ssl.http.enabled: true
plugins.security.ssl.http.pemcert_filepath: certificates/opensearch-node1.pem
plugins.security.ssl.http.pemkey_filepath: certificates/opensearch-node1-key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: certificates/ca-chain.pem
plugins.security.allow_unsafe_democertificates: false
plugins.security.allow_default_init_securityindex: false
plugins.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_opensearch
plugins.security.enable_snapshot_restore_privilege: true
plugins.security.check_snapshot_restore_write_privileges: true
plugins.security.restapi.roles_enabled:
["all_access", "security_rest_api_access"]
# Performance tuning
indices.memory.index_buffer_size: 20%
indices.queries.cache.size: 15%
indices.fielddata.cache.size: 30%
thread_pool.search.size: 50
thread_pool.search.queue_size: 1000
thread_pool.write.size: 30
thread_pool.write.queue_size: 500
# Cluster routing
cluster.routing.allocation.disk.threshold_enabled: true
cluster.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#

opensearch-security-config.yml
_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 rules
groups:
- 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
# Configuration
BACKUP_DIR="/backup"
S3_BUCKET="s3://wazuh-backups"
RETENTION_DAYS=30
DATE=$(date +%Y%m%d-%H%M%S)
# Create backup directories
mkdir -p ${BACKUP_DIR}/{wazuh,opensearch,config}/${DATE}
# Backup Wazuh configuration
echo "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 keys
echo "Backing up agent keys..."
cp /var/ossec/etc/client.keys ${BACKUP_DIR}/wazuh/${DATE}/
# Backup OpenSearch configuration
echo "Backing up OpenSearch configuration..."
tar czf ${BACKUP_DIR}/opensearch/${DATE}/opensearch-config.tar.gz \
/etc/opensearch \
/usr/share/opensearch/config
# Create OpenSearch snapshot
echo "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 S3
echo "Syncing to S3..."
aws s3 sync ${BACKUP_DIR}/ ${S3_BUCKET}/ --exclude "*.tmp"
# Clean up old local backups
echo "Cleaning up old backups..."
find ${BACKUP_DIR} -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} \;
# Verify backup
echo "Verifying backup..."
if aws s3 ls ${S3_BUCKET}/${DATE}/ > /dev/null 2>&1; then
echo "Backup completed successfully"
else
echo "Backup verification failed"
exit 1
fi
# Send notification
curl -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#

ComponentIssueSymptomsSolution
Wazuh AgentConnection FailedUnable to connect to managerCheck firewall rules, verify authd service, regenerate agent key
OpenSearchCluster Red StatusUnassigned shardsCheck disk space, verify node connectivity, force shard allocation
FilebeatPipeline BlockedHigh memory usageIncrease queue size, check OpenSearch performance
DashboardLogin FailedAuthentication errorVerify certificates, check user permissions, review auth logs
IntegrationNo Data FlowEmpty indicesCheck Filebeat configuration, verify index patterns

Debug Commands#

Terminal window
# Wazuh Manager debugging
/var/ossec/bin/wazuh-control info
/var/ossec/bin/wazuh-control status
tail -f /var/ossec/logs/ossec.log
# Check cluster status
/var/ossec/bin/cluster_control -l
# OpenSearch cluster health
curl -X GET "https://localhost:9200/_cluster/health?pretty" \
-u admin:admin --cacert /etc/opensearch/ca.pem
# Check indices
curl -X GET "https://localhost:9200/_cat/indices?v" \
-u admin:admin --cacert /etc/opensearch/ca.pem
# Filebeat status
systemctl status filebeat
filebeat test config
filebeat test output
# Certificate validation
openssl x509 -in /path/to/cert.pem -text -noout
openssl 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:

  1. Scalability: Horizontal scaling capabilities for both processing and storage
  2. High Availability: Clustered components with automatic failover
  3. Security: End-to-end encryption and comprehensive access control
  4. Performance: Optimized data flow and query performance
  5. 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.

References#

OpenSearch and Wazuh Integration - Building a Comprehensive Security Analytics Platform
https://mranv.pages.dev/posts/opensearch-wazuh-integration-architecture/
Author
Anubhav Gain
Published at
2025-01-29
License
CC BY-NC-SA 4.0