From 9c059d1d4601530ae3185cd69eecbdd48a3b51c4 Mon Sep 17 00:00:00 2001 From: boxswapper Date: Tue, 9 Dec 2025 09:06:26 -0700 Subject: [PATCH] initial commit --- single-node/README.md | 24 ++ single-node/config/certs.yml | 16 + .../config/wazuh_cluster/entrypoint.sh | 85 ++++++ .../config/wazuh_cluster/wazuh_manager.conf | 288 ++++++++++++++++++ .../wazuh_dashboard/opensearch_dashboards.yml | 16 + single-node/config/wazuh_dashboard/wazuh.yml | 7 + .../config/wazuh_indexer/internal_users.yml | 56 ++++ .../config/wazuh_indexer/wazuh.indexer.yml | 30 ++ single-node/docker-compose.yml | 109 +++++++ single-node/generate-indexer-certs.yml | 10 + 10 files changed, 641 insertions(+) create mode 100644 single-node/README.md create mode 100755 single-node/config/certs.yml create mode 100755 single-node/config/wazuh_cluster/entrypoint.sh create mode 100644 single-node/config/wazuh_cluster/wazuh_manager.conf create mode 100644 single-node/config/wazuh_dashboard/opensearch_dashboards.yml create mode 100644 single-node/config/wazuh_dashboard/wazuh.yml create mode 100644 single-node/config/wazuh_indexer/internal_users.yml create mode 100644 single-node/config/wazuh_indexer/wazuh.indexer.yml create mode 100644 single-node/docker-compose.yml create mode 100644 single-node/generate-indexer-certs.yml diff --git a/single-node/README.md b/single-node/README.md new file mode 100644 index 0000000..1a93b6c --- /dev/null +++ b/single-node/README.md @@ -0,0 +1,24 @@ +# Deploy Wazuh Docker in single node configuration + +This deployment is defined in the `docker-compose.yml` file with one Wazuh manager containers, one Wazuh indexer containers, and one Wazuh dashboard container. It can be deployed by following these steps: + +1) Increase max_map_count on your host (Linux). This command must be run with root permissions: +``` +$ sysctl -w vm.max_map_count=262144 +``` +2) Run the certificate creation script: +``` +$ docker compose -f generate-indexer-certs.yml run --rm generator +``` +3) Start the environment with docker compose: + +- In the foregroud: +``` +$ docker compose up +``` +- In the background: +``` +$ docker compose up -d +``` + +The environment takes about 1 minute to get up (depending on your Docker host) for the first time since Wazuh Indexer must be started for the first time and the indexes and index patterns must be generated. diff --git a/single-node/config/certs.yml b/single-node/config/certs.yml new file mode 100755 index 0000000..c3e017b --- /dev/null +++ b/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/single-node/config/wazuh_cluster/entrypoint.sh b/single-node/config/wazuh_cluster/entrypoint.sh new file mode 100755 index 0000000..51f5331 --- /dev/null +++ b/single-node/config/wazuh_cluster/entrypoint.sh @@ -0,0 +1,85 @@ +#!/bin/bash +set -xe + +OSSEC_CONF="ossec.conf" + +# -------------------------- +# Defaults based on OSSEC_CONF +# -------------------------- +if [[ -z "$WAZUH_CLUSTER_KEY" ]]; then + WAZUH_CLUSTER_KEY=$(sed -n '//,/<\/cluster>/s/.*\(.*\)<\/key>.*/\1/p' "$OSSEC_CONF" | head -n1) +fi + +if [[ -z "$WAZUH_CLUSTER_PORT" ]]; then + WAZUH_CLUSTER_PORT=$(sed -n '//,/<\/cluster>/s/.*\(.*\)<\/port>.*/\1/p' "$OSSEC_CONF" | head -n1) +fi + +# Node type logic +if [[ -z "$WAZUH_NODE_TYPE" ]]; then + if [[ "$HOSTNAME" == "manager" || "$HOSTNAME" == "aio_node" ]]; then + WAZUH_NODE_TYPE="master" + else + WAZUH_NODE_TYPE="worker" + fi +fi + +# Default node name → HOSTNAME if not defined +WAZUH_NODE_NAME="${WAZUH_NODE_NAME:-$HOSTNAME}" + +# -------------------------- +# Replace Indexer Hosts +# -------------------------- +if [[ -n "$WAZUH_INDEXER_HOSTS" ]]; then + TMP_HOSTS=$(mktemp) + { + echo " " + for NODE in $WAZUH_INDEXER_HOSTS; do + IP="${NODE%:*}" + PORT="${NODE#*:}" + echo " https://$IP:$PORT" + done + echo " " + } > "$TMP_HOSTS"; + sed -i -e '//,/<\/indexer>/{ //,/<\/hosts>/{ //r '"$TMP_HOSTS" \ + -e 'd }}' "$OSSEC_CONF"; + rm -f "$TMP_HOSTS"; +fi + +# -------------------------- +# Cluster: node_name +# -------------------------- +sed -i "//,/<\/cluster>/ s|.*|$WAZUH_NODE_NAME|" "$OSSEC_CONF" + +# -------------------------- +# Cluster: node_type +# -------------------------- +sed -i "//,/<\/cluster>/ s|.*|$WAZUH_NODE_TYPE|" "$OSSEC_CONF" + +# -------------------------- +# Cluster: key +# -------------------------- +sed -i "//,/<\/cluster>/ s|.*|$WAZUH_CLUSTER_KEY|" "$OSSEC_CONF" + +# -------------------------- +# Cluster: port +# -------------------------- +sed -i "//,/<\/cluster>/ s|.*|$WAZUH_CLUSTER_PORT|" "$OSSEC_CONF" + +# -------------------------- +# Cluster: nodes list +# -------------------------- +if [[ -n "$WAZUH_CLUSTER_NODES" ]]; then + TMP_NODES=$(mktemp) + { + echo " " + for N in $WAZUH_CLUSTER_NODES; do + echo " $N" + done + echo " " + } > "$TMP_NODES"; + sed -i -e '//,/<\/cluster>/{ //,/<\/nodes>/{ //r '"$TMP_NODES" \ + -e 'd }}' "$OSSEC_CONF"; + rm -f "$TMP_NODES"; +fi + +echo "Wazuh manager config modified successfully." diff --git a/single-node/config/wazuh_cluster/wazuh_manager.conf b/single-node/config/wazuh_cluster/wazuh_manager.conf new file mode 100644 index 0000000..4f00c24 --- /dev/null +++ b/single-node/config/wazuh_cluster/wazuh_manager.conf @@ -0,0 +1,288 @@ + + + 15m + 0 + yes + + + + + plain + + + + secure + 1514 + tcp + 131072 + + + + + no + yes + yes + yes + yes + yes + + + 43200 + + yes + + /var/lib/containerd + /var/lib/docker/overlay2 + + + + + no + 1h + yes + yes + yes + yes + yes + yes + yes + yes + yes + yes + yes + + + + yes + 5m + 10 + + + + + yes + yes + 12h + + + + yes + 5m + 10 + + + + + yes + yes + 60m + + + + yes + + https://wazuh.indexer:9200 + + + + /etc/ssl/root-ca.pem + + /etc/ssl/filebeat.pem + /etc/ssl/filebeat.key + + + + + + no + + + 43200 + + + 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 + + + 50 + + + + yes + 5m + 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/lists/malicious-ioc/malicious-ip + etc/lists/malicious-ioc/malicious-domains + etc/lists/malicious-ioc/malware-hashes + + + etc/decoders + etc/rules + + + + + 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 + + + + + + + journald + journald + + + + audit + /var/log/audit/audit.log + + + + syslog + /var/ossec/logs/active-responses.log + + + \ No newline at end of file diff --git a/single-node/config/wazuh_dashboard/opensearch_dashboards.yml b/single-node/config/wazuh_dashboard/opensearch_dashboards.yml new file mode 100644 index 0000000..07c81ab --- /dev/null +++ b/single-node/config/wazuh_dashboard/opensearch_dashboards.yml @@ -0,0 +1,16 @@ +server.host: 0.0.0.0 +server.port: 5601 +opensearch.hosts: https://wazuh.indexer:9200 +opensearch.ssl.verificationMode: certificate +opensearch.requestHeadersAllowlist: ["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/wz-home +# Session expiration settings +opensearch_security.cookie.ttl: 900000 +opensearch_security.session.ttl: 900000 +opensearch_security.session.keepalive: true diff --git a/single-node/config/wazuh_dashboard/wazuh.yml b/single-node/config/wazuh_dashboard/wazuh.yml new file mode 100644 index 0000000..ef42915 --- /dev/null +++ b/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/single-node/config/wazuh_indexer/internal_users.yml b/single-node/config/wazuh_indexer/internal_users.yml new file mode 100644 index 0000000..d9f05b3 --- /dev/null +++ b/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/single-node/config/wazuh_indexer/wazuh.indexer.yml b/single-node/config/wazuh_indexer/wazuh.indexer.yml new file mode 100644 index 0000000..3fc295a --- /dev/null +++ b/single-node/config/wazuh_indexer/wazuh.indexer.yml @@ -0,0 +1,30 @@ +network.host: "0.0.0.0" +node.name: "wazuh.indexer" +cluster.name: "wazuh-cluster" +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 +plugins.security.ssl.http.pemcert_filepath: /usr/share/wazuh-indexer/config/certs/wazuh.indexer.pem +plugins.security.ssl.http.pemkey_filepath: /usr/share/wazuh-indexer/config/certs/wazuh.indexer.key +plugins.security.ssl.http.pemtrustedcas_filepath: /usr/share/wazuh-indexer/config/certs/root-ca.pem +plugins.security.ssl.transport.pemcert_filepath: /usr/share/wazuh-indexer/config/certs/wazuh.indexer.pem +plugins.security.ssl.transport.pemkey_filepath: /usr/share/wazuh-indexer/config/certs/wazuh.indexer.key +plugins.security.ssl.transport.pemtrustedcas_filepath: /usr/share/wazuh-indexer/config/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 \ No newline at end of file diff --git a/single-node/docker-compose.yml b/single-node/docker-compose.yml new file mode 100644 index 0000000..365ab29 --- /dev/null +++ b/single-node/docker-compose.yml @@ -0,0 +1,109 @@ +# Wazuh App Copyright (C) 2017, Wazuh Inc. (License GPLv2) +services: + wazuh.manager: + image: wazuh/wazuh-manager:5.0.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_active_response:/var/ossec/active-response/bin + - wazuh_wodles:/var/ossec/wodles + - filebeat_etc:/etc/filebeat + - filebeat_var:/var/lib/filebeat + - ./config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem + - ./config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem + - ./config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key + - ./config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf + + wazuh.indexer: + image: wazuh/wazuh-indexer:5.0.0 + hostname: wazuh.indexer + restart: always + ports: + - "9200:9200" + environment: + - "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + volumes: + - wazuh-indexer-data:/var/lib/wazuh-indexer + - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/config/certs/root-ca.pem + - ./config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.key + - ./config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.pem + - ./config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/config/certs/admin.pem + - ./config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/config/certs/admin-key.pem + - ./config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/config/opensearch.yml + - ./config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/config/opensearch-security/internal_users.yml + + wazuh.dashboard: + image: wazuh/wazuh-dashboard:5.0.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: + - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem + - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem + - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem + - ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml + - ./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_active_response: + wazuh_wodles: + filebeat_etc: + filebeat_var: + wazuh-indexer-data: + wazuh-dashboard-config: + wazuh-dashboard-custom: diff --git a/single-node/generate-indexer-certs.yml b/single-node/generate-indexer-certs.yml new file mode 100644 index 0000000..a941280 --- /dev/null +++ b/single-node/generate-indexer-certs.yml @@ -0,0 +1,10 @@ +# Wazuh App Copyright (C) 2017, Wazuh Inc. (License GPLv2) +services: + generator: + image: wazuh/wazuh-certs-generator:0.0.3 + hostname: wazuh-certs-generator + environment: + - CERT_TOOL_VERSION=4.14 + volumes: + - ./config/wazuh_indexer_ssl_certs/:/certificates/ + - ./config/certs.yml:/config/certs.yml