Setup erkennt Docker oder Podman und deployt entsprechend

- setup.sh erkennt Engine (Docker, Podman, podman-docker-Wrapper) und
  Compose-Werkzeug (docker compose, docker-compose, podman-compose, podman compose)
- Rootless Podman wird mit Hinweis abgelehnt (Ulimits, Port 443, Zertifikatsrechte)
- Als root: vm.max_map_count, firewalld-Port und podman-restart.service setzen
- Neue Befehle: up, down, ps, logs, info; WAZUH_SKIP_SYSCTL und CONTAINER_ENGINE
- Images voll qualifiziert (docker.io/..., localhost/...) wegen Podman-Short-Name-Policy
- Bind-Mounts mit :z fuer SELinux (RHEL)
- README: Abschnitt Red Hat / Podman, Befehle ueber setup.sh

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
duffyduck
2026-10-07 12:21:32 +02:00
co-authored by Claude Opus 5.5
parent 8ddceda9e2
commit 61232af61c
6 changed files with 223 additions and 61 deletions
+40 -10
View File
@@ -56,18 +56,43 @@ device changed“), mit dem Diff im Alarmtext.
## Installation ## Installation
Voraussetzungen: Docker und docker-compose, ca. 8 GB RAM frei, ca. 10 GB Platz für Images und Voraussetzungen: Docker **oder** Podman, ca. 8 GB RAM frei, ca. 10 GB Platz für Images und Daten.
Daten. Für den Indexer:
```bash `setup.sh` erkennt die Umgebung selbst (`./setup.sh info` zeigt, was erkannt wurde):
echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-wazuh.conf && sudo sysctl --system
``` | Erkannt | Verwendet |
|---|---|
| Docker | `docker compose` oder `docker-compose` |
| Podman (z. B. RHEL, auch mit podman-docker-Wrapper) | `podman-compose` oder `podman compose` |
| SELinux aktiv | Alle Bind-Mounts haben `:z`. Ohne SELinux wirkt das nicht. |
Als root (`sudo ./setup.sh ...`) passt das Skript das System zusätzlich an:
- `vm.max_map_count=262144` (dauerhaft in `/etc/sysctl.d/99-wazuh.conf`)
- firewalld: Port für das Dashboard freigeben
- Podman: `podman-restart.service` aktivieren, damit der Stack nach einem Reboot startet
Ohne root gibt es dafür nur Hinweise. Mit `WAZUH_SKIP_SYSCTL=1` bleibt der Kernel-Parameter
unangetastet. Mit `CONTAINER_ENGINE=docker|podman` lässt sich die Erkennung übersteuern.
```bash ```bash
./setup.sh # Passwörter (.env), TLS-Zertifikate, SSH-Key ssh/id_ed25519, Images bauen ./setup.sh # Passwörter (.env), TLS-Zertifikate, SSH-Key ssh/id_ed25519, Images bauen
nano hosts.yml # Hosts eintragen (siehe hosts.yml.example) nano hosts.yml # Hosts eintragen (siehe hosts.yml.example)
``` ```
### Red Hat / Podman
```bash
sudo dnf install -y podman openssh-clients
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm # RHEL 9
sudo dnf install -y podman-compose
sudo ./setup.sh # Podman bitte als root, alle weiteren Befehle ebenfalls mit sudo
```
Podman muss als root laufen. Rootless scheitert an den Ulimits der Wazuh-Container (memlock,
nofile), an Port 443 und an den Zertifikatsrechten. `setup.sh` bricht in diesem Fall mit einem
Hinweis ab.
### Zielhosts vorbereiten ### Zielhosts vorbereiten
Auf jedem Host wird ein Benutzer `wazuh-pull` angelegt. Er bekommt die Gruppen Auf jedem Host wird ein Benutzer `wazuh-pull` angelegt. Er bekommt die Gruppen
@@ -87,7 +112,7 @@ Das Skript erst ansehen, dann ausführen: `./setup.sh host-script`
```bash ```bash
./setup.sh keyscan # Host-Keys -> ssh/known_hosts, Fingerprints mit den Hosts vergleichen! ./setup.sh keyscan # Host-Keys -> ssh/known_hosts, Fingerprints mit den Hosts vergleichen!
./setup.sh test # prüft Login, Gruppen, Journal-/Datei-Leserechte ./setup.sh test # prüft Login, Gruppen, Journal-/Datei-Leserechte
docker-compose up -d ./setup.sh up # starten (down, ps, logs [dienst] analog)
./setup.sh passwords # Login fürs Dashboard: https://<server>/ (admin / ...) ./setup.sh passwords # Login fürs Dashboard: https://<server>/ (admin / ...)
``` ```
@@ -143,13 +168,18 @@ Ports 1514 und 1515 sind nicht nach außen veröffentlicht. Nur der Collector er
## Fehlersuche ## Fehlersuche
```bash ```bash
docker-compose logs -f sshpull.collector # Verbindungen/Reconnects pro Host ./setup.sh logs sshpull.collector # Verbindungen/Reconnects pro Host
docker-compose exec wazuh.manager grep -i agentless /var/ossec/logs/ossec.log ./setup.sh logs wazuh.manager | grep -i agentless
docker-compose exec wazuh.manager ls -la /remote-logs/web01/ # kommen Logs an?
``` ```
Für `exec` die passende Engine nehmen (`docker` oder `sudo podman`). Die Containernamen zeigt
`./setup.sh ps`, z. B.:
`sudo podman exec wazuh_wazuh.manager_1 ls -la /remote-logs/web01/`
- `journal=WARNUNG:nur-eigene-Logs…` bei `./setup.sh test`: Der Benutzer ist nicht in der - `journal=WARNUNG:nur-eigene-Logs…` bei `./setup.sh test`: Der Benutzer ist nicht in der
Gruppe `systemd-journal`. Danach neu einloggen bzw. den Collector neu starten. Gruppe `systemd-journal`. Danach neu einloggen bzw. den Collector neu starten.
- Podman: Hängt `./setup.sh up` bei „podman wait“, konnte ein Container nicht angelegt werden.
Die Ursache zeigt `sudo podman-compose --verbose up -d 2>&1 | grep -i error`.
- `Host key verification failed`: `./setup.sh keyscan` ausführen, oder in `hosts.yml` - `Host key verification failed`: `./setup.sh keyscan` ausführen, oder in `hosts.yml`
`ssh.host_key_checking: accept-new` setzen. `ssh.host_key_checking: accept-new` setzen.
- Agentless-Checks laufen das erste Mal kurz nach dem Start, danach alle `interval` Sekunden. - Agentless-Checks laufen das erste Mal kurz nach dem Start, danach alle `interval` Sekunden.
@@ -157,6 +187,6 @@ docker-compose exec wazuh.manager ls -la /remote-logs/web01/ # kommen Logs an?
laufen nacheinander. Bei vielen Hosts mit großen Pfaden (`/usr`) das `interval` großzügig laufen nacheinander. Bei vielen Hosts mit großen Pfaden (`/usr`) das `interval` großzügig
wählen. wählen.
- Baseline eines Hosts neu anlegen (z. B. nach einem gewollten Update): - Baseline eines Hosts neu anlegen (z. B. nach einem gewollten Update):
`docker-compose exec wazuh.manager rm /var/ossec/agentless/.sshpull/web01.json` `<docker|podman> exec wazuh_wazuh.manager_1 rm /var/ossec/agentless/.sshpull/web01.json`
- Ohne `sudo` sind root-only Dateien (z. B. `/etc/shadow`, Host-Keys) nur über Größe, Rechte - Ohne `sudo` sind root-only Dateien (z. B. `/etc/shadow`, Host-Keys) nur über Größe, Rechte
und Besitzer überwacht, nicht über den Inhalt. und Besitzer überwacht, nicht über den Inhalt.
+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:3.12-slim FROM docker.io/library/python:3.12-slim
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y --no-install-recommends openssh-client tzdata \ && apt-get install -y --no-install-recommends openssh-client tzdata \
+28 -24
View File
@@ -2,7 +2,11 @@
# + sshpull-collector: holt Logs per SSH von Hosts, auf die nur per SSH zugegriffen werden kann # + sshpull-collector: holt Logs per SSH von Hosts, auf die nur per SSH zugegriffen werden kann
# + Manager-Erweiterung: Agentless-Integritaets- und Befehls-Checks per SSH # + Manager-Erweiterung: Agentless-Integritaets- und Befehls-Checks per SSH
# #
# Vor dem ersten Start: ./setup.sh # Vor dem ersten Start: ./setup.sh (erkennt Docker/Podman selbst, danach ./setup.sh up)
#
# Kompatibel mit docker compose, docker-compose, podman-compose und "podman compose":
# - Images voll qualifiziert (docker.io/..., localhost/...) wegen Podman-Short-Name-Policy
# - Bind-Mounts mit ":z" fuer SELinux (RHEL/Fedora); ohne SELinux wirkungslos
services: services:
wazuh.manager: wazuh.manager:
@@ -11,7 +15,7 @@ services:
dockerfile: manager/Dockerfile dockerfile: manager/Dockerfile
args: args:
WAZUH_VERSION: ${WAZUH_VERSION} WAZUH_VERSION: ${WAZUH_VERSION}
image: sshpull/wazuh-manager:${WAZUH_VERSION} image: localhost/sshpull/wazuh-manager:${WAZUH_VERSION}
hostname: wazuh.manager hostname: wazuh.manager
restart: always restart: always
ulimits: ulimits:
@@ -49,17 +53,17 @@ services:
- wazuh_wodles:/var/ossec/wodles - wazuh_wodles:/var/ossec/wodles
- filebeat_etc:/etc/filebeat - filebeat_etc:/etc/filebeat
- filebeat_var:/var/lib/filebeat - filebeat_var:/var/lib/filebeat
- ./config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem:ro - ./config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem:ro,z
- ./config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem:ro - ./config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem:ro,z
- ./config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key:ro - ./config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key:ro,z
- ./config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf:ro - ./config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf:ro,z
# sshpull # sshpull
- ./hosts.yml:/sshpull/hosts.yml:ro - ./hosts.yml:/sshpull/hosts.yml:ro,z
- ./ssh:/sshpull/ssh:ro - ./ssh:/sshpull/ssh:ro,z
- remote_logs:/remote-logs:ro - remote_logs:/remote-logs:ro
wazuh.indexer: wazuh.indexer:
image: wazuh/wazuh-indexer:${WAZUH_VERSION} image: docker.io/wazuh/wazuh-indexer:${WAZUH_VERSION}
hostname: wazuh.indexer hostname: wazuh.indexer
restart: always restart: always
environment: environment:
@@ -73,16 +77,16 @@ services:
hard: 65536 hard: 65536
volumes: volumes:
- wazuh-indexer-data:/var/lib/wazuh-indexer - wazuh-indexer-data:/var/lib/wazuh-indexer
- ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/config/certs/root-ca.pem:ro - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/config/certs/root-ca.pem:ro,z
- ./config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.key:ro - ./config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.key:ro,z
- ./config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.pem:ro - ./config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.pem:ro,z
- ./config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/config/certs/admin.pem:ro - ./config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/config/certs/admin.pem:ro,z
- ./config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/config/certs/admin-key.pem:ro - ./config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/config/certs/admin-key.pem:ro,z
- ./config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/config/opensearch.yml:ro - ./config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/config/opensearch.yml:ro,z
- ./config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/config/opensearch-security/internal_users.yml:ro - ./config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/config/opensearch-security/internal_users.yml:ro,z
wazuh.dashboard: wazuh.dashboard:
image: wazuh/wazuh-dashboard:${WAZUH_VERSION} image: docker.io/wazuh/wazuh-dashboard:${WAZUH_VERSION}
hostname: wazuh.dashboard hostname: wazuh.dashboard
restart: always restart: always
ports: ports:
@@ -96,10 +100,10 @@ services:
- API_USERNAME=wazuh-wui - API_USERNAME=wazuh-wui
- API_PASSWORD=${API_PASSWORD} - API_PASSWORD=${API_PASSWORD}
volumes: volumes:
- ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem:ro - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem:ro,z
- ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem:ro - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem:ro,z
- ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem:ro - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem:ro,z
- ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml:ro - ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml:ro,z
- wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config - wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config
- wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom - wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom
depends_on: depends_on:
@@ -110,7 +114,7 @@ services:
build: build:
context: . context: .
dockerfile: collector/Dockerfile dockerfile: collector/Dockerfile
image: sshpull/collector:latest image: localhost/sshpull/collector:latest
hostname: sshpull.collector hostname: sshpull.collector
restart: always restart: always
environment: environment:
@@ -118,8 +122,8 @@ services:
- MANAGER_HOST=wazuh.manager - MANAGER_HOST=wazuh.manager
- MAX_LOG_MB=${COLLECTOR_MAX_LOG_MB} - MAX_LOG_MB=${COLLECTOR_MAX_LOG_MB}
volumes: volumes:
- ./hosts.yml:/sshpull/hosts.yml:ro - ./hosts.yml:/sshpull/hosts.yml:ro,z
- ./ssh:/ssh # rw, damit "keyscan" known_hosts schreiben kann - ./ssh:/ssh:z # rw, damit "keyscan" known_hosts schreiben kann
- remote_logs:/remote-logs - remote_logs:/remote-logs
- collector_state:/state - collector_state:/state
depends_on: depends_on:
+1 -1
View File
@@ -1,5 +1,5 @@
# Hosts, die per SSH ueberwacht werden. # Hosts, die per SSH ueberwacht werden.
# Nach Aenderungen: docker-compose up -d --force-recreate wazuh.manager sshpull.collector # Nach Aenderungen: ./setup.sh apply (Manager + Collector neu starten)
# #
# Pro Host gibt es drei Bausteine (alle optional, Defaults siehe unten): # Pro Host gibt es drei Bausteine (alle optional, Defaults siehe unten):
# logs Logs werden dauerhaft per SSH gestreamt (journald und/oder Dateien) # logs Logs werden dauerhaft per SSH gestreamt (journald und/oder Dateien)
+1 -1
View File
@@ -1,5 +1,5 @@
ARG WAZUH_VERSION=4.14.8 ARG WAZUH_VERSION=4.14.8
FROM wazuh/wazuh-manager:${WAZUH_VERSION} FROM docker.io/wazuh/wazuh-manager:${WAZUH_VERSION}
# openssh-clients: Agentless per SSH; diffutils: wazuh-agentlessd vergleicht Befehlsausgaben mit diff # openssh-clients: Agentless per SSH; diffutils: wazuh-agentlessd vergleicht Befehlsausgaben mit diff
RUN dnf install -y openssh-clients diffutils && dnf clean all && rm -rf /var/cache/dnf RUN dnf install -y openssh-clients diffutils && dnf clean all && rm -rf /var/cache/dnf
+152 -24
View File
@@ -1,7 +1,12 @@
#!/bin/bash #!/bin/bash
# Einrichtung und Hilfsbefehle fuer den Wazuh-SSH-Pull-Stack. # Einrichtung und Betrieb des Wazuh-SSH-Pull-Stacks.
# Erkennt selbst, ob Docker oder Podman vorhanden ist (RHEL: Podman), und das passende
# Compose-Werkzeug (docker compose, docker-compose, podman-compose, podman compose).
# #
# ./setup.sh Erstinstallation (Passwoerter, Zertifikate, SSH-Key, Images) # ./setup.sh Erstinstallation (Passwoerter, Zertifikate, SSH-Key, Images)
# ./setup.sh up Stack starten (+ Kernel-Parameter, Firewall, Autostart als root)
# ./setup.sh down Stack stoppen
# ./setup.sh ps | logs [dienst]
# ./setup.sh host-script Skript zum Vorbereiten eines Zielhosts ausgeben # ./setup.sh host-script Skript zum Vorbereiten eines Zielhosts ausgeben
# ./setup.sh host-script | ssh admin@host sudo sh # ./setup.sh host-script | ssh admin@host sudo sh
# Optionen: --sudo (NOPASSWD-sudo), --tunnel (fuer agent_tunnel), # Optionen: --sudo (NOPASSWD-sudo), --tunnel (fuer agent_tunnel),
@@ -10,15 +15,77 @@
# ./setup.sh test SSH-Zugriff und Rechte auf allen Hosts pruefen # ./setup.sh test SSH-Zugriff und Rechte auf allen Hosts pruefen
# ./setup.sh apply hosts.yml uebernehmen (Manager + Collector neu starten) # ./setup.sh apply hosts.yml uebernehmen (Manager + Collector neu starten)
# ./setup.sh passwords Zugangsdaten anzeigen # ./setup.sh passwords Zugangsdaten anzeigen
# ./setup.sh info Erkannte Umgebung anzeigen
#
# Mit Podman bitte als root ausfuehren (sudo ./setup.sh ...), siehe check_rootless.
# Erkennung uebersteuern: CONTAINER_ENGINE=docker|podman ./setup.sh ...
# Kernel-Parameter nicht anfassen: WAZUH_SKIP_SYSCTL=1 ./setup.sh ...
set -euo pipefail set -euo pipefail
cd "$(dirname "$0")" cd "$(dirname "$0")"
if docker compose version >/dev/null 2>&1; then DC=(docker compose); else DC=(docker-compose); fi
info() { echo -e "\e[1;32m==>\e[0m $*"; } info() { echo -e "\e[1;32m==>\e[0m $*"; }
warn() { echo -e "\e[1;33m!!\e[0m $*" >&2; } warn() { echo -e "\e[1;33m!!\e[0m $*" >&2; }
die() { echo -e "\e[1;31mFEHLER:\e[0m $*" >&2; exit 1; } die() { echo -e "\e[1;31mFEHLER:\e[0m $*" >&2; exit 1; }
is_root() { [ "$(id -u)" -eq 0 ]; }
ENGINE=""
DC=()
SELINUX=no
detect_runtime() {
[ -n "$ENGINE" ] && return
ENGINE="${CONTAINER_ENGINE:-}"
if [ -z "$ENGINE" ]; then
# Auf RHEL ist "docker" oft nur der podman-docker-Wrapper -> dann Podman nehmen
if command -v docker >/dev/null 2>&1 && ! docker --version 2>/dev/null | grep -qi podman; then
ENGINE=docker
elif command -v podman >/dev/null 2>&1; then
ENGINE=podman
else
die "Weder Docker noch Podman gefunden. RHEL: sudo dnf install -y podman"
fi
fi
case "$ENGINE" in
docker)
docker info >/dev/null 2>&1 || die "Docker-Daemon nicht erreichbar (laeuft dockerd? Benutzer in Gruppe docker?)"
if docker compose version >/dev/null 2>&1; then DC=(docker compose)
elif command -v docker-compose >/dev/null 2>&1; then DC=(docker-compose)
else die "Docker Compose fehlt (Paket docker-compose-plugin)"; fi
;;
podman)
check_rootless
if command -v podman-compose >/dev/null 2>&1; then DC=(podman-compose)
elif podman compose version >/dev/null 2>&1; then DC=(podman compose)
else
die "podman-compose fehlt. RHEL 9:
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf install -y podman-compose
oder: sudo pip3 install podman-compose"
fi
;;
*) die "CONTAINER_ENGINE muss docker oder podman sein" ;;
esac
if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" != "Disabled" ]; then
SELINUX=yes # docker-compose.yml nutzt ":z" auf allen Bind-Mounts
fi
}
check_rootless() {
# Rootless Podman scheitert hier an: memlock/nofile-Ulimits der Wazuh-Container,
# Port 443 (< 1024) und Zertifikaten, die im Container per chown an UIDs 999/1000 gehen.
if [ "$(podman info --format '{{.Host.Security.Rootless}}' 2>/dev/null)" = "true" ]; then
die "Podman laeuft rootless. Wazuh braucht erhoehte Ulimits und Port $(env_get DASHBOARD_PORT 2>/dev/null || echo 443).
Bitte als root ausfuehren: sudo ./setup.sh ${CMD:-}"
fi
}
# Docker oder Podman (gleiche CLI fuer run/images/info)
engine() { "$ENGINE" "$@"; }
compose() { "${DC[@]}" "$@"; }
genpw() { genpw() {
# Erfuellt die Wazuh-API-Richtlinie (Gross, klein, Ziffer, Sonderzeichen) und # Erfuellt die Wazuh-API-Richtlinie (Gross, klein, Ziffer, Sonderzeichen) und
# enthaelt keine Zeichen, die in den sed-Aufrufen der Wazuh-Images stoeren. # enthaelt keine Zeichen, die in den sed-Aufrufen der Wazuh-Images stoeren.
@@ -29,18 +96,64 @@ set_env() { # set_env KEY VALUE
if grep -q "^$1=" .env; then sed -i "s|^$1=.*|$1=$2|" .env; else echo "$1=$2" >> .env; fi if grep -q "^$1=" .env; then sed -i "s|^$1=.*|$1=$2|" .env; else echo "$1=$2" >> .env; fi
} }
env_get() { grep "^$1=" .env | cut -d= -f2-; } env_get() { grep "^$1=" .env 2>/dev/null | cut -d= -f2-; }
cmd_init() { tune_kernel() {
command -v docker >/dev/null || die "docker fehlt"
# --- Kernel-Parameter fuer den Indexer ---------------------------------
local mmc local mmc
mmc=$(cat /proc/sys/vm/max_map_count) mmc=$(cat /proc/sys/vm/max_map_count)
if [ "$mmc" -lt 262144 ]; then [ "$mmc" -ge 262144 ] && return
warn "vm.max_map_count ist $mmc (empfohlen 262144). Dauerhaft setzen mit:" [ "${WAZUH_SKIP_SYSCTL:-0}" = 1 ] && { warn "vm.max_map_count=$mmc, Anpassung uebersprungen (WAZUH_SKIP_SYSCTL=1)"; return; }
if is_root; then
info "Setze vm.max_map_count=262144 (dauerhaft in /etc/sysctl.d/99-wazuh.conf)"
echo 'vm.max_map_count=262144' > /etc/sysctl.d/99-wazuh.conf
sysctl -q -w vm.max_map_count=262144
else
warn "vm.max_map_count ist $mmc (benoetigt 262144). Als root setzen mit:"
warn " echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-wazuh.conf && sudo sysctl --system" warn " echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-wazuh.conf && sudo sysctl --system"
fi fi
}
open_firewall() {
local port
port=$(env_get DASHBOARD_PORT)
command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1 || return 0
if firewall-cmd --query-port="$port/tcp" >/dev/null 2>&1; then return 0; fi
if is_root; then
info "firewalld: oeffne Port $port/tcp fuer das Dashboard"
firewall-cmd -q --permanent --add-port="$port/tcp" && firewall-cmd -q --reload
else
warn "firewalld aktiv, Port $port/tcp nicht freigegeben: sudo firewall-cmd --permanent --add-port=$port/tcp && sudo firewall-cmd --reload"
fi
}
enable_autostart() {
# Docker startet "restart: always"-Container selbst; Podman hat keinen Daemon,
# dafuer gibt es podman-restart.service.
[ "$ENGINE" = podman ] || return 0
command -v systemctl >/dev/null 2>&1 || return 0
if systemctl is-enabled podman-restart.service >/dev/null 2>&1; then return 0; fi
if is_root; then
info "Aktiviere podman-restart.service (Container starten nach Reboot)"
systemctl enable -q podman-restart.service
else
warn "Autostart nach Reboot: sudo systemctl enable podman-restart.service"
fi
}
cmd_info() {
detect_runtime
echo "Engine: $ENGINE ($("$ENGINE" --version | head -1))"
echo "Compose: ${DC[*]}"
echo "SELinux: $SELINUX"
echo "root: $(is_root && echo ja || echo nein)"
echo "max_map: $(cat /proc/sys/vm/max_map_count)"
}
cmd_init() {
detect_runtime
info "Container-Umgebung: $ENGINE mit ${DC[*]} (SELinux: $SELINUX)"
command -v ssh-keygen >/dev/null || die "ssh-keygen fehlt (RHEL: dnf install openssh-clients)"
tune_kernel
# --- .env + Passwoerter ------------------------------------------------- # --- .env + Passwoerter -------------------------------------------------
[ -f .env ] || cp .env.example .env [ -f .env ] || cp .env.example .env
@@ -55,8 +168,8 @@ cmd_init() {
if [ ! -f config/wazuh_indexer/internal_users.yml ]; then if [ ! -f config/wazuh_indexer/internal_users.yml ]; then
info "Erzeuge Indexer-Benutzer (Passwort-Hashes)" info "Erzeuge Indexer-Benutzer (Passwort-Hashes)"
hash() { hash() {
docker run --rm -e JAVA_HOME=/usr/share/wazuh-indexer/jdk --entrypoint bash \ engine run --rm -e JAVA_HOME=/usr/share/wazuh-indexer/jdk --entrypoint bash \
"wazuh/wazuh-indexer:$version" \ "docker.io/wazuh/wazuh-indexer:$version" \
/usr/share/wazuh-indexer/plugins/opensearch-security/tools/hash.sh -p "$1" 2>/dev/null | tail -1 /usr/share/wazuh-indexer/plugins/opensearch-security/tools/hash.sh -p "$1" 2>/dev/null | tail -1
} }
local h_admin h_kibana local h_admin h_kibana
@@ -89,18 +202,18 @@ EOF
if [ ! -f config/wazuh_indexer_ssl_certs/root-ca.pem ]; then if [ ! -f config/wazuh_indexer_ssl_certs/root-ca.pem ]; then
info "Erzeuge TLS-Zertifikate" info "Erzeuge TLS-Zertifikate"
mkdir -p config/wazuh_indexer_ssl_certs mkdir -p config/wazuh_indexer_ssl_certs
docker run --rm \ engine run --rm \
-e CERT_TOOL_VERSION="${version%.*}" \ -e CERT_TOOL_VERSION="${version%.*}" \
-v "$PWD/config/wazuh_indexer_ssl_certs/:/certificates/" \ -v "$PWD/config/wazuh_indexer_ssl_certs/:/certificates/:z" \
-v "$PWD/config/certs.yml:/config/certs.yml:ro" \ -v "$PWD/config/certs.yml:/config/certs.yml:ro,z" \
wazuh/wazuh-certs-generator:0.0.4 docker.io/wazuh/wazuh-certs-generator:0.0.4
[ -f config/wazuh_indexer_ssl_certs/root-ca.pem ] || die "Zertifikate wurden nicht erzeugt" [ -f config/wazuh_indexer_ssl_certs/root-ca.pem ] || die "Zertifikate wurden nicht erzeugt"
fi fi
# --- SSH-Schluessel ---------------------------------------------------- # --- SSH-Schluessel ----------------------------------------------------
if [ ! -f ssh/id_ed25519 ]; then if [ ! -f ssh/id_ed25519 ]; then
info "Erzeuge SSH-Schluessel ssh/id_ed25519" info "Erzeuge SSH-Schluessel ssh/id_ed25519"
ssh-keygen -q -t ed25519 -N "" -C "wazuh-sshpull@$(hostname)" -f ssh/id_ed25519 ssh-keygen -q -t ed25519 -N "" -C "wazuh-sshpull@$(uname -n)" -f ssh/id_ed25519
fi fi
touch ssh/known_hosts touch ssh/known_hosts
chmod 600 ssh/id_ed25519 chmod 600 ssh/id_ed25519
@@ -108,7 +221,7 @@ EOF
[ -f hosts.yml ] || { cp hosts.yml.example hosts.yml; warn "hosts.yml aus Beispiel angelegt - bitte anpassen!"; } [ -f hosts.yml ] || { cp hosts.yml.example hosts.yml; warn "hosts.yml aus Beispiel angelegt - bitte anpassen!"; }
info "Baue Images" info "Baue Images"
"${DC[@]}" build compose build
cat <<EOF cat <<EOF
@@ -117,7 +230,7 @@ Fertig. Naechste Schritte:
2. Zielhosts vorbereiten: ./setup.sh host-script | ssh admin@HOST sudo sh 2. Zielhosts vorbereiten: ./setup.sh host-script | ssh admin@HOST sudo sh
3. Host-Keys holen: ./setup.sh keyscan (Fingerprints pruefen!) 3. Host-Keys holen: ./setup.sh keyscan (Fingerprints pruefen!)
4. Zugriff testen: ./setup.sh test 4. Zugriff testen: ./setup.sh test
5. Starten: ${DC[*]} up -d 5. Starten: ./setup.sh up
6. Dashboard: https://<dieser-server>:$(env_get DASHBOARD_PORT) (admin / siehe ./setup.sh passwords) 6. Dashboard: https://<dieser-server>:$(env_get DASHBOARD_PORT) (admin / siehe ./setup.sh passwords)
EOF EOF
} }
@@ -165,15 +278,30 @@ EOF
echo 'echo "Host vorbereitet: Benutzer $U ($(id $U))"' echo 'echo "Host vorbereitet: Benutzer $U ($(id $U))"'
} }
case "${1:-init}" in cmd_up() {
detect_runtime
tune_kernel
compose up -d
enable_autostart
open_firewall
info "Gestartet ($ENGINE). Dashboard in 1-3 Minuten: https://$(uname -n):$(env_get DASHBOARD_PORT)"
}
CMD="${1:-init}"
case "$CMD" in
init) cmd_init ;; init) cmd_init ;;
up) cmd_up ;;
down) detect_runtime; compose down ;;
ps) detect_runtime; compose ps ;;
logs) shift; detect_runtime; compose logs -f --tail=100 "$@" ;;
info) cmd_info ;;
host-script) shift; cmd_host_script "$@" ;; host-script) shift; cmd_host_script "$@" ;;
keyscan) "${DC[@]}" run --rm --no-deps sshpull.collector keyscan ;; keyscan) detect_runtime; compose run --rm --no-deps sshpull.collector keyscan ;;
test) "${DC[@]}" run --rm --no-deps sshpull.collector test ;; test) detect_runtime; compose run --rm --no-deps sshpull.collector test ;;
apply) "${DC[@]}" up -d --force-recreate wazuh.manager sshpull.collector ;; apply) detect_runtime; compose up -d --force-recreate wazuh.manager sshpull.collector ;;
passwords) passwords)
echo "Dashboard: admin / $(env_get INDEXER_PASSWORD)" echo "Dashboard: admin / $(env_get INDEXER_PASSWORD)"
echo "Wazuh-API: wazuh-wui / $(env_get API_PASSWORD)" echo "Wazuh-API: wazuh-wui / $(env_get API_PASSWORD)"
;; ;;
*) sed -n '2,13p' "$0"; exit 2 ;; *) sed -n '2,23p' "$0"; exit 2 ;;
esac esac