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 Buy Me A Coffee - 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,