diff --git a/.dockerignore b/.dockerignore
index f9ec1cf..7f22714 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -19,5 +19,5 @@ docs/
docker-compose.yaml
Dockerfile
venv
-tests
*.json
+tests/*
diff --git a/.gitignore b/.gitignore
index 1ac11f5..f0252a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,7 @@
__pycache__/
*.py[cod]
*$py.class
-vault
config.json
curator.yml
data
+tests/single-node/config/wazuh_indexer_ssl_certs/*
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7f83419..2286b89 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.3.0
+ rev: v4.5.0
hooks:
- id: check-yaml
args: [--allow-multiple-documents]
@@ -10,17 +10,14 @@ repos:
- id: check-merge-conflict
- id: mixed-line-ending
args: [--fix=lf]
+
- repo: https://github.com/ambv/black
- rev: 22.6.0
- hooks:
- - id: black
-- repo: https://github.com/ambv/black
- rev: 22.6.0
+ rev: 24.1.1
hooks:
- id: black
language_version: python3.8
- repo: https://github.com/pre-commit/pygrep-hooks
- rev: v1.9.0
+ rev: v1.10.0
hooks:
- id: python-use-type-annotations
- id: python-check-blanket-noqa
@@ -29,22 +26,19 @@ repos:
- id: rst-backticks
- id: text-unicode-replacement-char
- repo: https://github.com/jumanjihouse/pre-commit-hooks
- rev: 2.1.6
+ rev: 3.0.0
hooks:
- id: bundler-audit
- id: fasterer
- id: forbid-binary
- id: git-check
- - id: markdownlint
- id: reek
- - id: require-ascii
- exclude: '.github'
- id: script-must-have-extension
- id: script-must-not-have-extension
- id: shellcheck
- id: shfmt
- repo: https://github.com/jorisroovers/gitlint
- rev: 'v0.17.0'
+ rev: 'v0.19.1'
hooks:
- id: gitlint
- repo: local
@@ -56,14 +50,6 @@ repos:
entry: flake8
types: [python]
- repo: https://github.com/Lucas-C/pre-commit-hooks-safety
- rev: 'v1.3.0'
+ rev: 'v1.3.3'
hooks:
- id: python-safety-dependencies-check
-- repo: https://github.com/PyCQA/bandit
- rev: '1.7.4'
- hooks:
- - id: bandit
-- repo: https://github.com/petalmd/dockerfile-pre-commit
- rev: 'v1.0'
- hooks:
- - id: dockerlint
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..07ef8ae
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+.PHONY: help
+help: ## Help for usage
+ @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
+
+run-local-dev: ## Run Wazuh cluster with prometheus and exporter.
+ docker compose -f tests/single-node/generate-indexer-certs.yml run --rm generator
+ docker compose -f docker-compose.yml up -d --build
+
+destroy: ## Destroy docker compose stack and cleanup
+ docker compose down --remove-orphans --rmi local -v
+ rm -rf tests/single-node/config/wazuh_indexer_ssl_certs/*
+test: ## Run unit tests
+ pytest -v --cov=. --cov-report xml --cov-report html -n auto --capture=sys -x --tb=long
diff --git a/README.md b/README.md
index e07f879..1e8d391 100644
--- a/README.md
+++ b/README.md
@@ -48,4 +48,3 @@ kubectl apply -f deployment.yaml -n wazuh
## Support project
-
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..dd8d22f
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,154 @@
+# Wazuh App Copyright (C) 2017, Wazuh Inc. (License GPLv2)
+version: '3.9' # optional since Compose v1.27.0
+services:
+ prometheus:
+ container_name: prometheus
+ image: prom/prometheus
+ user: "65534"
+ ports:
+ - "9090:9090"
+ depends_on:
+ - exporter
+ volumes:
+ - prometheus:/prometheus
+ - ./tests/config/prometheus/:/etc/prometheus/
+ exporter:
+ build:
+ context: .
+ image: exporter
+ restart: always
+ environment:
+ - WAZUH_API_HOST=wazuh.manager
+ - WAZUH_API_PORT=55000
+ - WAZUH_API_USERNAME=wazuh-wui
+ - WAZUH_API_PASSWORD=MyS3cr37P450r.*-
+ ports:
+ - 5000:5000
+ wazuh-minideb-agent:
+ image: opennix/wazuh-agent:${AGENT_VERSION:-4.7.1}
+ hostname: wazuh-agent
+ restart: always
+ environment:
+ - JOIN_MANAGER_MASTER_HOST=wazuh.manager
+ - JOIN_MANAGER_WORKER_HOST=wazuh.manager
+ - JOIN_MANAGER_USER=wazuh-wui
+ - JOIN_MANAGER_PASSWORD=MyS3cr37P450r.*-
+ depends_on:
+ wazuh.manager:
+ condition: service_healthy
+ wazuh.manager:
+ image: wazuh/wazuh-manager:${WAZUH_CLUSTER_VERSION:-4.7.0}
+ hostname: wazuh.manager
+ restart: always
+ ulimits:
+ memlock:
+ soft: -1
+ hard: -1
+ nofile:
+ soft: 655360
+ hard: 655360
+ ports:
+ - "1514:1514"
+ - "1515:1515"
+ - "514:514/udp"
+ - "55000:55000"
+ environment:
+ - INDEXER_URL=https://wazuh.indexer:9200
+ - INDEXER_USERNAME=admin
+ - INDEXER_PASSWORD=SecretPassword
+ - FILEBEAT_SSL_VERIFICATION_MODE=full
+ - SSL_CERTIFICATE_AUTHORITIES=/etc/ssl/root-ca.pem
+ - SSL_CERTIFICATE=/etc/ssl/filebeat.pem
+ - SSL_KEY=/etc/ssl/filebeat.key
+ - API_USERNAME=wazuh-wui
+ - API_PASSWORD=MyS3cr37P450r.*-
+ volumes:
+ - wazuh_api_configuration:/var/ossec/api/configuration
+ - wazuh_etc:/var/ossec/etc
+ - wazuh_logs:/var/ossec/logs
+ - wazuh_queue:/var/ossec/queue
+ - wazuh_var_multigroups:/var/ossec/var/multigroups
+ - wazuh_integrations:/var/ossec/integrations
+ - wazuh_active_response:/var/ossec/active-response/bin
+ - wazuh_agentless:/var/ossec/agentless
+ - wazuh_wodles:/var/ossec/wodles
+ - filebeat_etc:/etc/filebeat
+ - filebeat_var:/var/lib/filebeat
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key
+ - ./tests/single-node/config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf
+ healthcheck:
+ test: curl -k --silent https://wazuh.indexer:9200 >/dev/null; if [[ $$? == 52 ]]; then echo 0; else echo 1; fi
+ interval: 30s
+ timeout: 10s
+ retries: 10
+ wazuh.indexer:
+ image: wazuh/wazuh-indexer:${WAZUH_CLUSTER_VERSION:-4.7.0}
+ hostname: wazuh.indexer
+ restart: always
+ ports:
+ - "9200:9200"
+ environment:
+ - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
+ ulimits:
+ memlock:
+ soft: -1
+ hard: -1
+ nofile:
+ soft: 65536
+ hard: 65536
+ volumes:
+ - wazuh-indexer-data:/var/lib/wazuh-indexer
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/certs/root-ca.pem
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/certs/wazuh.indexer.key
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/certs/wazuh.indexer.pem
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/certs/admin.pem
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/certs/admin-key.pem
+ - ./tests/single-node/config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/opensearch.yml
+ - ./tests/single-node/config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/opensearch-security/internal_users.yml
+
+ wazuh.dashboard:
+ image: wazuh/wazuh-dashboard:${WAZUH_CLUSTER_VERSION:-4.7.0}
+ hostname: wazuh.dashboard
+ restart: always
+ ports:
+ - 443:5601
+ environment:
+ - INDEXER_USERNAME=admin
+ - INDEXER_PASSWORD=SecretPassword
+ - WAZUH_API_URL=https://wazuh.manager
+ - DASHBOARD_USERNAME=kibanaserver
+ - DASHBOARD_PASSWORD=kibanaserver
+ - API_USERNAME=wazuh-wui
+ - API_PASSWORD=MyS3cr37P450r.*-
+ volumes:
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem
+ - ./tests/single-node/config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem
+ - ./tests/single-node/config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml
+ - ./tests/single-node/config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml
+ - wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config
+ - wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom
+ depends_on:
+ - wazuh.indexer
+ links:
+ - wazuh.indexer:wazuh.indexer
+ - wazuh.manager:wazuh.manager
+
+volumes:
+ wazuh_api_configuration:
+ wazuh_etc:
+ wazuh_logs:
+ wazuh_queue:
+ wazuh_var_multigroups:
+ wazuh_integrations:
+ wazuh_active_response:
+ wazuh_agentless:
+ wazuh_wodles:
+ filebeat_etc:
+ filebeat_var:
+ wazuh-indexer-data:
+ wazuh-dashboard-config:
+ wazuh-dashboard-custom:
+ prometheus:
diff --git a/main.py b/main.py
index 7b5b789..36cb668 100644
--- a/main.py
+++ b/main.py
@@ -1,22 +1,4 @@
#!/usr/bin/env python
-# Copyright (c) 2021. Yuriy Medvedev
-# All rights reserved.
-# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
-# following conditions are met: 1. Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials
-# provided with the distribution. 3. All advertising materials mentioning features or use of this software must
-# display the following acknowledgement: This product includes software developed by the Yuriy Medvedev. 4.Neither
-# the name of the Yuriy Medvedev nor the names of its contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY Yuriy Medvedev ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL Yuriy Medvedev BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import sys
import logging
@@ -62,6 +44,7 @@ def __init__(self):
logger.info("Start collector")
@staticmethod
+ # skipcq: PY-R1000
def collect():
wazuh_connection = wazuh.Wazuh(
protocol=protocol,
@@ -90,19 +73,16 @@ def collect():
metric = Metric("wazuh_agent_status", "Total Wazuh agents by status", "summary")
# Wazuh >= v4.4
+
if "connection" in agents["agent_status"]:
agents_path = agents["agent_status"]["connection"]
# Legacy Wazuh support (< v4.4)
else:
agents_path = agents["agent_status"]
-
- metric.add_sample(
- "wazuh_active_agents",
- value=agents_path["active"],
- labels={}
- )
+
+ metric.add_sample("wazuh_active_agents", value=agents_path["active"], labels={})
metric.add_sample(
- "wazuh_disconnected_agents",
+ "wazuh_disconnected_agents",
value=agents_path["disconnected"],
labels={},
)
@@ -112,15 +92,9 @@ def collect():
labels={},
)
metric.add_sample(
- "wazuh_pending_agents",
- value=agents_path["pending"],
- labels={}
- )
- metric.add_sample(
- "wazuh_total_agents",
- value=agents_path["total"],
- labels={}
+ "wazuh_pending_agents", value=agents_path["pending"], labels={}
)
+ metric.add_sample("wazuh_total_agents", value=agents_path["total"], labels={})
yield metric
metric = InfoMetricFamily("wazuh_agent_version", "Wazuh agent versions")
for version in agents["agent_version"]:
@@ -140,7 +114,6 @@ def collect():
f"last_registered_agent metric has been skipped please check agent."
f"Full agent trace {version}"
)
- pass
else:
for key, value in version["os"].items():
node_name = version["node_name"]
@@ -171,9 +144,7 @@ def collect():
yield metric
metric = InfoMetricFamily("nodes_healthcheck", "Wazuh nodes healthcheck")
nodes = wazuh_connection.wazuh_get_nodes_healtchecks(auth)
- if nodes is None:
- pass
- else:
+ if nodes is not None:
for node in nodes:
for key, value in node["info"].items():
metric.add_metric(
@@ -246,11 +217,12 @@ def collect():
value=remote_state["discarded_count"],
labels={"manager_stats_remote": "discarded_count"},
)
- metric.add_sample(
- "queued_msgs",
- value=remote_state["queued_msgs"],
- labels={"manager_stats_remote": "queued_msgs"},
- )
+ if info.get("api_version") < "4.7.0":
+ metric.add_sample(
+ "queued_msgs",
+ value=remote_state["queued_msgs"],
+ labels={"manager_stats_remote": "queued_msgs"},
+ )
metric.add_sample(
"recv_bytes",
value=remote_state["recv_bytes"],
@@ -285,91 +257,92 @@ def collect():
value=analysisd_stat["syscheck_events_decoded"],
labels={"analysisd_stats": "syscheck_events_decoded"},
)
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["syscheck_edps"],
- labels={"analysisd_stats": "syscheck_edps"},
- )
+ if info.get("api_version") < "4.7.0":
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["syscheck_edps"],
+ labels={"analysisd_stats": "syscheck_edps"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["syscollector_edps"],
+ labels={"analysisd_stats": "syscollector_edps"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["rootcheck_edps"],
+ labels={"analysisd_stats": "rootcheck_edps"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["sca_edps"],
+ labels={"analysisd_stats": "sca_edps"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["hostinfo_events_decoded"],
+ labels={"analysisd_stats": "hostinfo_events_decoded"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["hostinfo_edps"],
+ labels={"analysisd_stats": "hostinfo_edps"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["winevt_edps"],
+ labels={"analysisd_stats": "winevt_edps"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["dbsync_mdps"],
+ labels={"analysisd_stats": "dbsync_mdps"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["other_events_edps"],
+ labels={"analysisd_stats": "other_events_edps"},
+ )
+ metric.add_sample(
+ "analysisd_stats",
+ value=analysisd_stat["events_edps"],
+ labels={"analysisd_stats": "events_edps"},
+ )
metric.add_sample(
"analysisd_stats",
value=analysisd_stat["syscollector_events_decoded"],
labels={"analysisd_stats": "syscollector_events_decoded"},
)
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["syscollector_edps"],
- labels={"analysisd_stats": "syscollector_edps"},
- )
metric.add_sample(
"analysisd_stats",
value=analysisd_stat["rootcheck_events_decoded"],
labels={"analysisd_stats": "rootcheck_events_decoded"},
)
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["rootcheck_edps"],
- labels={"analysisd_stats": "rootcheck_edps"},
- )
metric.add_sample(
"analysisd_stats",
value=analysisd_stat["sca_events_decoded"],
labels={"analysisd_stats": "sca_events_decoded"},
)
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["sca_edps"],
- labels={"analysisd_stats": "sca_edps"},
- )
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["hostinfo_events_decoded"],
- labels={"analysisd_stats": "hostinfo_events_decoded"},
- )
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["hostinfo_edps"],
- labels={"analysisd_stats": "hostinfo_edps"},
- )
metric.add_sample(
"analysisd_stats",
value=analysisd_stat["winevt_events_decoded"],
labels={"analysisd_stats": "winevt_events_decoded"},
)
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["winevt_edps"],
- labels={"analysisd_stats": "winevt_edps"},
- )
metric.add_sample(
"analysisd_stats",
value=analysisd_stat["dbsync_messages_dispatched"],
labels={"analysisd_stats": "dbsync_messages_dispatched"},
)
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["dbsync_mdps"],
- labels={"analysisd_stats": "dbsync_mdps"},
- )
metric.add_sample(
"analysisd_stats",
value=analysisd_stat["other_events_decoded"],
labels={"analysisd_stats": "other_events_decoded"},
)
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["other_events_edps"],
- labels={"analysisd_stats": "other_events_edps"},
- )
metric.add_sample(
"analysisd_stats",
value=analysisd_stat["events_processed"],
labels={"analysisd_stats": "events_processed"},
)
- metric.add_sample(
- "analysisd_stats",
- value=analysisd_stat["events_edps"],
- labels={"analysisd_stats": "events_edps"},
- )
metric.add_sample(
"analysisd_stats",
value=analysisd_stat["events_received"],
diff --git a/requirements.txt b/requirements.txt
index f8c2c7c..edf246f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-urllib3==1.26.18
-prometheus_client==0.14.1
+urllib3==2.1.0
+prometheus_client==0.19.0
requests==2.31.0
-json-logging
+json-logging==1.3.0
diff --git a/tests/config/grafana/grafana.config b/tests/config/grafana/grafana.config
new file mode 100644
index 0000000..2e2decb
--- /dev/null
+++ b/tests/config/grafana/grafana.config
@@ -0,0 +1,2 @@
+GF_SECURITY_ADMIN_PASSWORD=admin
+GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-piechart-panel,camptocamp-prometheus-alertmanager-datasource,vonage-status-panel
diff --git a/tests/config/grafana/provisioning/datasources/datasource.yaml b/tests/config/grafana/provisioning/datasources/datasource.yaml
new file mode 100644
index 0000000..83c8450
--- /dev/null
+++ b/tests/config/grafana/provisioning/datasources/datasource.yaml
@@ -0,0 +1,10 @@
+
+# config file version
+apiVersion: 1
+
+# Provisioning Grafana
+datasources:
+ - name: Prometheus
+ type: prometheus
+ access: proxy
+ url: http://prometheus:9090
diff --git a/tests/config/prometheus/prometheus.yml b/tests/config/prometheus/prometheus.yml
new file mode 100644
index 0000000..8a6e43f
--- /dev/null
+++ b/tests/config/prometheus/prometheus.yml
@@ -0,0 +1,9 @@
+global:
+ scrape_interval: 15s
+ evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
+ scrape_timeout: 15s
+
+scrape_configs:
+ - job_name: 'exporter'
+ static_configs:
+ - targets: ['exporter:5000']
diff --git a/tests/single-node/config/certs.yml b/tests/single-node/config/certs.yml
new file mode 100755
index 0000000..c3e017b
--- /dev/null
+++ b/tests/single-node/config/certs.yml
@@ -0,0 +1,16 @@
+nodes:
+ # Wazuh indexer server nodes
+ indexer:
+ - name: wazuh.indexer
+ ip: wazuh.indexer
+
+ # Wazuh server nodes
+ # Use node_type only with more than one Wazuh manager
+ server:
+ - name: wazuh.manager
+ ip: wazuh.manager
+
+ # Wazuh dashboard node
+ dashboard:
+ - name: wazuh.dashboard
+ ip: wazuh.dashboard
diff --git a/tests/single-node/config/wazuh_cluster/wazuh_manager.conf b/tests/single-node/config/wazuh_cluster/wazuh_manager.conf
new file mode 100644
index 0000000..0cf738f
--- /dev/null
+++ b/tests/single-node/config/wazuh_cluster/wazuh_manager.conf
@@ -0,0 +1,374 @@
+
+
+ yes
+ yes
+ no
+ no
+ no
+ smtp.example.wazuh.com
+ wazuh@example.wazuh.com
+ recipient@example.wazuh.com
+ 12
+ alerts.log
+ 10m
+ 0
+
+
+
+ 3
+ 12
+
+
+
+
+ plain
+
+
+
+ secure
+ 1514
+ tcp
+ 131072
+
+
+
+
+ no
+ yes
+ yes
+ yes
+ yes
+ yes
+ yes
+ yes
+
+
+ 43200
+
+ etc/rootcheck/rootkit_files.txt
+ etc/rootcheck/rootkit_trojans.txt
+
+ yes
+
+
+
+ yes
+ 1800
+ 1d
+ yes
+
+ wodles/java
+ wodles/ciscat
+
+
+
+
+ yes
+ yes
+ /var/log/osquery/osqueryd.results.log
+ /etc/osquery/osquery.conf
+ yes
+
+
+
+
+ no
+ 1h
+ yes
+ yes
+ yes
+ yes
+ yes
+ yes
+ yes
+
+
+
+ 10
+
+
+
+
+ yes
+ yes
+ 12h
+ yes
+
+
+
+ no
+ 5m
+ 6h
+ yes
+
+
+
+ no
+ trusty
+ xenial
+ bionic
+ focal
+ jammy
+ 1h
+
+
+
+
+ no
+ buster
+ bullseye
+ bookworm
+ 1h
+
+
+
+
+ no
+ 5
+ 6
+ 7
+ 8
+ 9
+ 1h
+
+
+
+
+ no
+ amazon-linux
+ amazon-linux-2
+ amazon-linux-2023
+ 1h
+
+
+
+
+ no
+ 11-server
+ 11-desktop
+ 12-server
+ 12-desktop
+ 15-server
+ 15-desktop
+ 1h
+
+
+
+
+ no
+ 1h
+
+
+
+
+ no
+ 8
+ 9
+ 1h
+
+
+
+
+ yes
+ 1h
+
+
+
+
+ yes
+ 1h
+
+
+
+
+
+
+ no
+
+
+ 43200
+
+ yes
+
+
+ yes
+
+
+ no
+
+
+ /etc,/usr/bin,/usr/sbin
+ /bin,/sbin,/boot
+
+
+ /etc/mtab
+ /etc/hosts.deny
+ /etc/mail/statistics
+ /etc/random-seed
+ /etc/random.seed
+ /etc/adjtime
+ /etc/httpd/logs
+ /etc/utmpx
+ /etc/wtmpx
+ /etc/cups/certs
+ /etc/dumpdates
+ /etc/svc/volatile
+
+
+ .log$|.swp$
+
+
+ /etc/ssl/private.key
+
+ yes
+ yes
+ yes
+ yes
+
+
+ 10
+
+
+ 100
+
+
+
+ yes
+ 5m
+ 1h
+ 10
+
+
+
+
+
+ 127.0.0.1
+ ^localhost.localdomain$
+
+
+
+ disable-account
+ disable-account
+ yes
+
+
+
+ restart-wazuh
+ restart-wazuh
+
+
+
+ firewall-drop
+ firewall-drop
+ yes
+
+
+
+ host-deny
+ host-deny
+ yes
+
+
+
+ route-null
+ route-null
+ yes
+
+
+
+ win_route-null
+ route-null.exe
+ yes
+
+
+
+ netsh
+ netsh.exe
+ yes
+
+
+
+
+
+
+ command
+ df -P
+ 360
+
+
+
+ full_command
+ netstat -tulpn | sed 's/\([[:alnum:]]\+\)\ \+[[:digit:]]\+\ \+[[:digit:]]\+\ \+\(.*\):\([[:digit:]]*\)\ \+\([0-9\.\:\*]\+\).\+\ \([[:digit:]]*\/[[:alnum:]\-]*\).*/\1 \2 == \3 == \4 \5/' | sort -k 4 -g | sed 's/ == \(.*\) ==/:\1/' | sed 1,2d
+ netstat listening ports
+ 360
+
+
+
+ full_command
+ last -n 20
+ 360
+
+
+
+
+ ruleset/decoders
+ ruleset/rules
+ 0215-policy_rules.xml
+ etc/lists/audit-keys
+ etc/lists/amazon/aws-eventnames
+ etc/lists/security-eventchannel
+
+
+ etc/decoders
+ etc/rules
+
+
+
+ yes
+ 1
+ 64
+ 15m
+
+
+
+
+ no
+ 1515
+ no
+ yes
+ no
+ HIGH:!ADH:!EXP:!MD5:!RC4:!3DES:!CAMELLIA:@STRENGTH
+
+ no
+ etc/sslmanager.cert
+ etc/sslmanager.key
+ no
+
+
+
+ wazuh
+ node01
+ master
+ aa093264ef885029653eea20dfcf51ae
+ 1516
+ 0.0.0.0
+
+ wazuh.manager
+
+ no
+ yes
+
+
+
+
+
+
+ syslog
+ /var/ossec/logs/active-responses.log
+
+
+
diff --git a/tests/single-node/config/wazuh_dashboard/opensearch_dashboards.yml b/tests/single-node/config/wazuh_dashboard/opensearch_dashboards.yml
new file mode 100644
index 0000000..2a9cdba
--- /dev/null
+++ b/tests/single-node/config/wazuh_dashboard/opensearch_dashboards.yml
@@ -0,0 +1,12 @@
+server.host: 0.0.0.0
+server.port: 5601
+opensearch.hosts: https://wazuh.indexer:9200
+opensearch.ssl.verificationMode: certificate
+opensearch.requestHeadersWhitelist: ["securitytenant","Authorization"]
+opensearch_security.multitenancy.enabled: false
+opensearch_security.readonly_mode.roles: ["kibana_read_only"]
+server.ssl.enabled: true
+server.ssl.key: "/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem"
+server.ssl.certificate: "/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem"
+opensearch.ssl.certificateAuthorities: ["/usr/share/wazuh-dashboard/certs/root-ca.pem"]
+uiSettings.overrides.defaultRoute: /app/wazuh
diff --git a/tests/single-node/config/wazuh_dashboard/wazuh.yml b/tests/single-node/config/wazuh_dashboard/wazuh.yml
new file mode 100644
index 0000000..ef42915
--- /dev/null
+++ b/tests/single-node/config/wazuh_dashboard/wazuh.yml
@@ -0,0 +1,7 @@
+hosts:
+ - 1513629884013:
+ url: "https://wazuh.manager"
+ port: 55000
+ username: wazuh-wui
+ password: "MyS3cr37P450r.*-"
+ run_as: false
diff --git a/tests/single-node/config/wazuh_indexer/internal_users.yml b/tests/single-node/config/wazuh_indexer/internal_users.yml
new file mode 100644
index 0000000..d9f05b3
--- /dev/null
+++ b/tests/single-node/config/wazuh_indexer/internal_users.yml
@@ -0,0 +1,56 @@
+---
+# This is the internal user database
+# The hash value is a bcrypt hash and can be generated with plugin/tools/hash.sh
+
+_meta:
+ type: "internalusers"
+ config_version: 2
+
+# Define your internal users here
+
+## Demo users
+
+admin:
+ hash: "$2y$12$K/SpwjtB.wOHJ/Nc6GVRDuc1h0rM1DfvziFRNPtk27P.c4yDr9njO"
+ reserved: true
+ backend_roles:
+ - "admin"
+ description: "Demo admin user"
+
+kibanaserver:
+ hash: "$2a$12$4AcgAt3xwOWadA5s5blL6ev39OXDNhmOesEoo33eZtrq2N0YrU3H."
+ reserved: true
+ description: "Demo kibanaserver user"
+
+kibanaro:
+ hash: "$2a$12$JJSXNfTowz7Uu5ttXfeYpeYE0arACvcwlPBStB1F.MI7f0U9Z4DGC"
+ reserved: false
+ backend_roles:
+ - "kibanauser"
+ - "readall"
+ attributes:
+ attribute1: "value1"
+ attribute2: "value2"
+ attribute3: "value3"
+ description: "Demo kibanaro user"
+
+logstash:
+ hash: "$2a$12$u1ShR4l4uBS3Uv59Pa2y5.1uQuZBrZtmNfqB3iM/.jL0XoV9sghS2"
+ reserved: false
+ backend_roles:
+ - "logstash"
+ description: "Demo logstash user"
+
+readall:
+ hash: "$2a$12$ae4ycwzwvLtZxwZ82RmiEunBbIPiAmGZduBAjKN0TXdwQFtCwARz2"
+ reserved: false
+ backend_roles:
+ - "readall"
+ description: "Demo readall user"
+
+snapshotrestore:
+ hash: "$2y$12$DpwmetHKwgYnorbgdvORCenv4NAK8cPUg8AI6pxLCuWf/ALc0.v7W"
+ reserved: false
+ backend_roles:
+ - "snapshotrestore"
+ description: "Demo snapshotrestore user"
diff --git a/tests/single-node/config/wazuh_indexer/wazuh.indexer.yml b/tests/single-node/config/wazuh_indexer/wazuh.indexer.yml
new file mode 100644
index 0000000..afcd0ff
--- /dev/null
+++ b/tests/single-node/config/wazuh_indexer/wazuh.indexer.yml
@@ -0,0 +1,30 @@
+network.host: "0.0.0.0"
+node.name: "wazuh.indexer"
+path.data: /var/lib/wazuh-indexer
+path.logs: /var/log/wazuh-indexer
+discovery.type: single-node
+http.port: 9200-9299
+transport.tcp.port: 9300-9399
+compatibility.override_main_response_version: true
+plugins.security.ssl.http.pemcert_filepath: /usr/share/wazuh-indexer/certs/wazuh.indexer.pem
+plugins.security.ssl.http.pemkey_filepath: /usr/share/wazuh-indexer/certs/wazuh.indexer.key
+plugins.security.ssl.http.pemtrustedcas_filepath: /usr/share/wazuh-indexer/certs/root-ca.pem
+plugins.security.ssl.transport.pemcert_filepath: /usr/share/wazuh-indexer/certs/wazuh.indexer.pem
+plugins.security.ssl.transport.pemkey_filepath: /usr/share/wazuh-indexer/certs/wazuh.indexer.key
+plugins.security.ssl.transport.pemtrustedcas_filepath: /usr/share/wazuh-indexer/certs/root-ca.pem
+plugins.security.ssl.http.enabled: true
+plugins.security.ssl.transport.enforce_hostname_verification: false
+plugins.security.ssl.transport.resolve_hostname: false
+plugins.security.authcz.admin_dn:
+- "CN=admin,OU=Wazuh,O=Wazuh,L=California,C=US"
+plugins.security.check_snapshot_restore_write_privileges: true
+plugins.security.enable_snapshot_restore_privilege: true
+plugins.security.nodes_dn:
+- "CN=wazuh.indexer,OU=Wazuh,O=Wazuh,L=California,C=US"
+plugins.security.restapi.roles_enabled:
+- "all_access"
+- "security_rest_api_access"
+plugins.security.system_indices.enabled: true
+plugins.security.system_indices.indices: [".opendistro-alerting-config", ".opendistro-alerting-alert*", ".opendistro-anomaly-results*", ".opendistro-anomaly-detector*", ".opendistro-anomaly-checkpoints", ".opendistro-anomaly-detection-state", ".opendistro-reports-*", ".opendistro-notifications-*", ".opendistro-notebooks", ".opensearch-observability", ".opendistro-asynchronous-search-response*", ".replication-metadata-store"]
+plugins.security.allow_default_init_securityindex: true
+cluster.routing.allocation.disk.threshold_enabled: false
diff --git a/tests/single-node/generate-indexer-certs.yml b/tests/single-node/generate-indexer-certs.yml
new file mode 100644
index 0000000..d10151f
--- /dev/null
+++ b/tests/single-node/generate-indexer-certs.yml
@@ -0,0 +1,10 @@
+# Wazuh App Copyright (C) 2017, Wazuh Inc. (License GPLv2)
+version: '3'
+
+services:
+ generator:
+ image: wazuh/wazuh-certs-generator:0.0.1
+ hostname: wazuh-certs-generator
+ volumes:
+ - ./config/wazuh_indexer_ssl_certs/:/certificates/
+ - ./config/certs.yml:/config/certs.yml
diff --git a/wazuh/__init__.py b/wazuh/__init__.py
index fba0057..bb5d2ba 100644
--- a/wazuh/__init__.py
+++ b/wazuh/__init__.py
@@ -237,7 +237,6 @@ def wazuh_get_agents_overview(self, requests_headers):
# skipcq: PTC-W6001
def wazuh_get_nodes_healtchecks(self, requests_headers):
-
response = requests.get(
f"{self.url}/cluster/healthcheck",
headers=requests_headers,
@@ -257,7 +256,6 @@ def wazuh_get_nodes_healtchecks(self, requests_headers):
# skipcq: PTC-W6001
def wazuh_get_last_scan_syscheck(self, requests_headers, agent_id):
-
response = requests.get(
f"{self.url}/syscheck/{agent_id}",
headers=requests_headers,