fix: critical bugs + security hardening

Phase 1 (critical bugs):
- Fix firewall import string-to-list bug (system_import.py)
- Add rich rules removal in firewall config apply (handlers/firewall.py)

Phase 2 (security hardening):
- Restrict sudo wildcards to specific paths (sudoers.d/vacuum-walld)
- Fix TOCTOU: use /run/vacuum-wall/ for temp files (nginx, dnsmasq, network handlers)
- Remove unnecessary sudo from wg genkey/pubkey (handlers/wireguard.py)

Phase 3 (validation):
- Validate poll intervals > 0 (daemon/server.py)
- Restrict sysctl to whitelisted parameters (handlers/network.py)

Phase 4 (defensive programming):
- Enforce shell=False in run() and run_proc() (lib/common.py)
- Track issuance tasks for graceful shutdown (handlers/acme.py)
- Add nginx template marker consistency tests (tests/test_system_import.py)
This commit is contained in:
2026-07-10 17:05:37 +00:00
parent 803258cf18
commit 05524f3756
27 changed files with 1805 additions and 521 deletions
+5 -6
View File
@@ -9,9 +9,8 @@ Defaults:{{ USER_DAEMON_NAME }} secure_path="/usr/local/sbin:/usr/local/bin:/usr
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/sbin/nginx -t
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/sbin/nginx -s reload
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/systemctl is-active nginx
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp * /etc/nginx/*
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp * /etc/nginx/conf.d/*
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp * /etc/nginx/snippets/*
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp -- /run/vacuum-wall/include.tmp /etc/nginx/conf.d/vacuum-wall.conf
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp -- /run/vacuum-wall/ssl-snippet.tmp /etc/nginx/snippets/vacuum-wall-ssl.conf
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/rm /etc/nginx/conf.d/vacuum-wall.conf
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/rm /etc/nginx/snippets/vacuum-wall-ssl.conf
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/chown root\:root /etc/nginx/conf.d/vacuum-wall.conf
@@ -22,12 +21,12 @@ Defaults:{{ USER_DAEMON_NAME }} secure_path="/usr/local/sbin:/usr/local/bin:/usr
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/systemctl is-active dnsmasq
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cat /var/lib/misc/dnsmasq.leases
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/mkdir -p /etc/dnsmasq.d
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp * /etc/dnsmasq.d/*
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp -- /run/vacuum-wall/dnsmasq.tmp /etc/dnsmasq.d/vacuum-wall.conf
# WireGuard management
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/wg-quick *
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/wg *
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp * /etc/wireguard/*
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp -- /run/vacuum-wall/wg0.conf.tmp /etc/wireguard/wg0.conf
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/chown root\:root /etc/wireguard/wg0.conf
# Network interface queries
@@ -39,7 +38,7 @@ Defaults:{{ USER_DAEMON_NAME }} secure_path="/usr/local/sbin:/usr/local/bin:/usr
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /bin/networkctl status *
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /bin/networkctl reload
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /bin/networkctl reconfigure *
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp * /etc/systemd/network/*
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/cp -- /run/vacuum-wall/99-*.network /etc/systemd/network/
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/rm /etc/systemd/network/*.network
{{ USER_DAEMON_NAME }} ALL=(root) NOPASSWD: /usr/bin/mkdir -p /etc/systemd/network
+5 -1
View File
@@ -18,9 +18,13 @@ Environment=PYTHONUNBUFFERED=1
Environment=ACME_HOME={{ PROJECT_DIR }}/data/acme
Environment=HOME={{ PROJECT_DIR }}
# Runtime directory for temp files used during config apply
RuntimeDirectory=vacuum-wall
RuntimeDirectoryMode=0750
# Security hardening
ProtectSystem=strict
ReadWritePaths={{ PROJECT_DIR }} /tmp /etc/systemd/network /etc/nginx /etc/dnsmasq.d /etc/wireguard /run/sudo /run/firewalld /run/nginx /run/nginx.pid /var/log/nginx
ReadWritePaths={{ PROJECT_DIR }} /tmp /etc/systemd/network /etc/nginx /etc/dnsmasq.d /etc/wireguard /run/vacuum-wall /run/sudo /run/firewalld /run/nginx /run/nginx.pid /var/log/nginx
PrivateTmp=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes