feat(waf): Phase 4 — Packaging, CRS, systemd, sudoers — v1.2.69
- Makefile: edgeguard-waf zu BINARIES hinzugefügt - deploy/systemd/edgeguard-waf.service: systemd-Unit (User=edgeguard, After=postgresql + edgeguard-api, Hardening, ReadWritePaths=/var/log/edgeguard) - build-package.sh: edgeguard-waf Binary + Service ins .deb - postinst: OWASP CRS v4.7.0 Download bei Erstinstall nach /usr/share/edgeguard/waf/crs/; graceful wenn kein Internet vorhanden - postinst: edgeguard-waf.service enable + start bei install/upgrade - postinst: sudoers für start/stop/enable/disable/restart edgeguard-waf.service - system.go: edgeguard-waf in servicesToCheck + toggleAllowlist Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2
Makefile
2
Makefile
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
GO ?= $(shell which go || echo /usr/local/go/bin/go)
|
GO ?= $(shell which go || echo /usr/local/go/bin/go)
|
||||||
MODULE := git.netcell-it.de/projekte/edgeguard-native
|
MODULE := git.netcell-it.de/projekte/edgeguard-native
|
||||||
BINARIES := edgeguard-api edgeguard-scheduler edgeguard-ctl
|
BINARIES := edgeguard-api edgeguard-scheduler edgeguard-ctl edgeguard-waf
|
||||||
VERSION := $(shell cat VERSION 2>/dev/null || echo 0.0.1-dev)
|
VERSION := $(shell cat VERSION 2>/dev/null || echo 0.0.1-dev)
|
||||||
LDFLAGS := -s -w -X main.version=$(VERSION)
|
LDFLAGS := -s -w -X main.version=$(VERSION)
|
||||||
GOFLAGS := -trimpath -mod=readonly
|
GOFLAGS := -trimpath -mod=readonly
|
||||||
|
|||||||
32
deploy/systemd/edgeguard-waf.service
Normal file
32
deploy/systemd/edgeguard-waf.service
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=EdgeGuard WAF SPOE Agent (Coraza/OWASP CRS)
|
||||||
|
Documentation=https://git.netcell-it.de/projekte/edgeguard-native
|
||||||
|
After=network-online.target postgresql.service edgeguard-api.service
|
||||||
|
Wants=network-online.target
|
||||||
|
Requires=postgresql.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=edgeguard
|
||||||
|
Group=edgeguard
|
||||||
|
ExecStart=/usr/bin/edgeguard-waf
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
# Hardening — WAF agent only needs DB access and one TCP listen socket.
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
PrivateTmp=true
|
||||||
|
PrivateDevices=true
|
||||||
|
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||||
|
SystemCallFilter=@system-service
|
||||||
|
# CRS rules are read from /usr/share/edgeguard/waf/crs/ (read-only, OK).
|
||||||
|
# Alerts/logs are written to /var/log/edgeguard/.
|
||||||
|
ReadWritePaths=/var/log/edgeguard
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -197,6 +197,7 @@ var servicesToCheck = []struct{ Label, Unit string }{
|
|||||||
{"postgresql", "postgresql"},
|
{"postgresql", "postgresql"},
|
||||||
{"crowdsec", "crowdsec"},
|
{"crowdsec", "crowdsec"},
|
||||||
{"crowdsec-firewall-bouncer", "crowdsec-firewall-bouncer"},
|
{"crowdsec-firewall-bouncer", "crowdsec-firewall-bouncer"},
|
||||||
|
{"edgeguard-waf", "edgeguard-waf"},
|
||||||
}
|
}
|
||||||
|
|
||||||
type serviceStatus struct {
|
type serviceStatus struct {
|
||||||
@@ -639,6 +640,7 @@ func (h *SystemHandler) ServiceRestart(c *gin.Context) {
|
|||||||
var toggleAllowlist = map[string]bool{
|
var toggleAllowlist = map[string]bool{
|
||||||
"crowdsec": true,
|
"crowdsec": true,
|
||||||
"crowdsec-firewall-bouncer": true,
|
"crowdsec-firewall-bouncer": true,
|
||||||
|
"edgeguard-waf": true,
|
||||||
"squid": true,
|
"squid": true,
|
||||||
"unbound": true,
|
"unbound": true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,12 @@ edgeguard ALL=(root) NOPASSWD: /usr/bin/cscli collections list -o json
|
|||||||
edgeguard ALL=(root) NOPASSWD: /usr/bin/cscli collections install *
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/cscli collections install *
|
||||||
edgeguard ALL=(root) NOPASSWD: /usr/bin/cscli collections remove *
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/cscli collections remove *
|
||||||
edgeguard ALL=(root) NOPASSWD: /usr/bin/cscli version
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/cscli version
|
||||||
|
# WAF agent service control
|
||||||
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl start edgeguard-waf.service
|
||||||
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl stop edgeguard-waf.service
|
||||||
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl enable edgeguard-waf.service
|
||||||
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl disable edgeguard-waf.service
|
||||||
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl restart edgeguard-waf.service
|
||||||
# CrowdSec service toggle (start/stop/enable/disable)
|
# CrowdSec service toggle (start/stop/enable/disable)
|
||||||
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl start crowdsec.service
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl start crowdsec.service
|
||||||
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl stop crowdsec.service
|
edgeguard ALL=(root) NOPASSWD: /usr/bin/systemctl stop crowdsec.service
|
||||||
@@ -790,10 +796,38 @@ EOSQL
|
|||||||
/etc/systemd/system/haproxy.service.d/edgeguard.conf
|
/etc/systemd/system/haproxy.service.d/edgeguard.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── OWASP Core Rule Set (CRS) für edgeguard-waf ─────────────────────
|
||||||
|
# Nur beim Erstinstall — kein Überschreiben bei Upgrades damit
|
||||||
|
# admins angepasste crs-setup.conf behalten können.
|
||||||
|
WAF_CRS_DIR="/usr/share/edgeguard/waf/crs"
|
||||||
|
if [ "$1" = "configure" ] && [ -z "$2" ] && [ ! -d "$WAF_CRS_DIR/rules" ]; then
|
||||||
|
CRS_VERSION="4.7.0"
|
||||||
|
echo "postinst: installing OWASP CRS v${CRS_VERSION}..."
|
||||||
|
install -d -m 0755 "$WAF_CRS_DIR/rules"
|
||||||
|
CRS_TMP="$(mktemp -d)"
|
||||||
|
if curl -sL --max-time 60 \
|
||||||
|
"https://github.com/coreruleset/coreruleset/archive/refs/tags/v${CRS_VERSION}.tar.gz" \
|
||||||
|
-o "${CRS_TMP}/crs.tar.gz" 2>/dev/null; then
|
||||||
|
tar xzf "${CRS_TMP}/crs.tar.gz" -C "${CRS_TMP}" 2>/dev/null || true
|
||||||
|
CRS_SRC="${CRS_TMP}/coreruleset-${CRS_VERSION}"
|
||||||
|
if [ -f "${CRS_SRC}/crs-setup.conf.example" ]; then
|
||||||
|
install -m 0644 "${CRS_SRC}/crs-setup.conf.example" "${WAF_CRS_DIR}/crs-setup.conf"
|
||||||
|
install -m 0644 "${CRS_SRC}/rules/"*.conf "${WAF_CRS_DIR}/rules/" 2>/dev/null || true
|
||||||
|
chown -R "$EG_USER":"$EG_USER" "$WAF_CRS_DIR"
|
||||||
|
echo "postinst: OWASP CRS v${CRS_VERSION} installed to ${WAF_CRS_DIR}"
|
||||||
|
else
|
||||||
|
echo "postinst: CRS download succeeded but layout unexpected — skipping" >&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "postinst: CRS download failed (no internet?) — WAF usable without CRS" >&2
|
||||||
|
fi
|
||||||
|
rm -rf "${CRS_TMP}"
|
||||||
|
fi
|
||||||
|
|
||||||
# ── systemd: pick up new units + restart haproxy with our cfg
|
# ── systemd: pick up new units + restart haproxy with our cfg
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl restart haproxy.service || true
|
systemctl restart haproxy.service || true
|
||||||
systemctl enable edgeguard-api.service edgeguard-scheduler.service || true
|
systemctl enable edgeguard-api.service edgeguard-scheduler.service edgeguard-waf.service || true
|
||||||
# restart (NICHT enable --now): das neue Unit-File könnte ein
|
# restart (NICHT enable --now): das neue Unit-File könnte ein
|
||||||
# geänderter ReadWritePaths-Block sein (Befund 1.0.87:
|
# geänderter ReadWritePaths-Block sein (Befund 1.0.87:
|
||||||
# /var/lib/apt fehlte → apt-get update aus dem Update-Banner-
|
# /var/lib/apt fehlte → apt-get update aus dem Update-Banner-
|
||||||
@@ -802,7 +836,7 @@ EOSQL
|
|||||||
# der laufende Daemon behält das alte Sandbox-Snapshot bis zum
|
# der laufende Daemon behält das alte Sandbox-Snapshot bis zum
|
||||||
# restart. Bei Erst-Install ist nichts running, dann ist das
|
# restart. Bei Erst-Install ist nichts running, dann ist das
|
||||||
# ein normaler Start.
|
# ein normaler Start.
|
||||||
systemctl restart edgeguard-api.service edgeguard-scheduler.service || true
|
systemctl restart edgeguard-api.service edgeguard-scheduler.service edgeguard-waf.service || true
|
||||||
|
|
||||||
# WireGuard-Sicherung: enabled-aber-inaktive wg-quick@-Interfaces
|
# WireGuard-Sicherung: enabled-aber-inaktive wg-quick@-Interfaces
|
||||||
# nach dem API-Restart starten. Der API-Renderer kann wg-quick@
|
# nach dem API-Restart starten. Der API-Renderer kann wg-quick@
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ build_api() {
|
|||||||
[ -f "$pkg_src/DEBIAN/conffiles" ] && cp "$pkg_src/DEBIAN/conffiles" "$build_dir/DEBIAN/"
|
[ -f "$pkg_src/DEBIAN/conffiles" ] && cp "$pkg_src/DEBIAN/conffiles" "$build_dir/DEBIAN/"
|
||||||
|
|
||||||
# binaries
|
# binaries
|
||||||
for bin in edgeguard-api edgeguard-scheduler edgeguard-ctl; do
|
for bin in edgeguard-api edgeguard-scheduler edgeguard-ctl edgeguard-waf; do
|
||||||
install -m 0755 "$REPO_ROOT/build/$ARCH/$bin" "$build_dir/usr/bin/$bin"
|
install -m 0755 "$REPO_ROOT/build/$ARCH/$bin" "$build_dir/usr/bin/$bin"
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -70,6 +70,8 @@ build_api() {
|
|||||||
"$build_dir/etc/systemd/system/"
|
"$build_dir/etc/systemd/system/"
|
||||||
install -m 0644 "$REPO_ROOT/deploy/systemd/edgeguard-scheduler.service" \
|
install -m 0644 "$REPO_ROOT/deploy/systemd/edgeguard-scheduler.service" \
|
||||||
"$build_dir/etc/systemd/system/"
|
"$build_dir/etc/systemd/system/"
|
||||||
|
install -m 0644 "$REPO_ROOT/deploy/systemd/edgeguard-waf.service" \
|
||||||
|
"$build_dir/etc/systemd/system/"
|
||||||
|
|
||||||
# systemd drop-in for HAProxy — postinst copies it into
|
# systemd drop-in for HAProxy — postinst copies it into
|
||||||
# /etc/systemd/system/haproxy.service.d/. Shipped under
|
# /etc/systemd/system/haproxy.service.d/. Shipped under
|
||||||
|
|||||||
Reference in New Issue
Block a user