The brief asked for an AGENTS.md capturing the overall plan and it never landed, while two files already pointed readers at it. It now holds the invariants (read-only by construction, never invent a number, unconfigured is not broken, no CDN, no guessed metric names), the locked decisions with their reasons, the verified fleet facts, the commands, and the four known gaps. Also corrected the docs that had drifted: - upsd config lives in /etc/ups on driveripper, not /etc/nut, and the real blocker is that upsd binds nothing on 3493 — with the sudo rules still needed written down in deploy/nut-sudoers. - .env.example told operators to set `LISTEN 0.0.0.0` and `actions = -`; both are worse than needed. Loopback + ssh forward, and per-command instcmds instead of granting load.off. - nut.py claimed the command path is gated three times and that the confirmation asks for the UPS name; it is gated four times and asks for DANGER. - .gitignore described a tracked .agents/ roadmap that does not exist. LLM-Generated: true
56 lines
3.1 KiB
Plaintext
56 lines
3.1 KiB
Plaintext
# driveripper-ops sudo rules for the UPS dashboard work
|
|
#
|
|
# Install as /etc/sudoers.d/dashboards-nut (visudo -cf it first):
|
|
#
|
|
# sudo visudo -cf - <<'EOF' ... EOF # syntax check
|
|
# install -m 0440 deploy/nut-sudoers /tmp/dashboards-nut
|
|
# sudo mv /tmp/dashboards-nut /etc/sudoers.d/dashboards-nut
|
|
#
|
|
# Keep it scoped: paths are absolute (sudoers uses `secure_path`), arguments are wildcards
|
|
# only where the command is read-only or idempotent, and nothing here allows a shell,
|
|
# `EDITOR=`, `dnf install` of arbitrary code, or `upsd -c` with an attacker-chosen file.
|
|
|
|
# ---- already present on driveripper (this is what the dashboard setup used) ---------- #
|
|
# (root) NOPASSWD: /usr/bin/tee /etc/ups/* # write upsd.conf / upsd.users
|
|
# (root) NOPASSWD: /usr/bin/cp /etc/ups/* /home/ops/* # back up a config before editing
|
|
# (root) NOPASSWD: /usr/bin/systemctl start|restart|reload|enable *
|
|
# (root) NOPASSWD: /usr/bin/udevadm * # USB device discovery/replug
|
|
# (root) NOPASSWD: /usr/bin/firewall-cmd * # only if upsd must serve the LAN
|
|
# (root) NOPASSWD: /usr/bin/dnf install * # nut, nut-client, nut-dev
|
|
|
|
# ---- still needed: diagnose why upsd runs but binds nothing -------------------------- #
|
|
# Reading is the blocker. `upsd` is active, both drivers are up, and 3493 has no listener,
|
|
# but /etc/ups/* is 0640 root:nut and the journal needs group membership:
|
|
# $ sudo cat /etc/ups/upsd.conf -> Permission denied
|
|
# $ journalctl -u nut-server -n 50 -> No entries (not in systemd-journal/wheel)
|
|
# $ upsc -l -> Error: Connection failure: Connection refused
|
|
|
|
Cmnd_Alias NUT_DIAGNOSE = \
|
|
/usr/bin/cat /etc/ups/*, \
|
|
/usr/bin/systemctl status *, \
|
|
/usr/bin/journalctl -u nut-server *, /usr/bin/journalctl -u nut-driver@*, \
|
|
/usr/bin/journalctl -u nut*, \
|
|
/usr/sbin/ss -ltnp, \
|
|
/usr/sbin/getenforce, \
|
|
/usr/bin/ausearch *, /usr/sbin/sealert -l *, \
|
|
/usr/sbin/semanage port -l, \
|
|
/usr/bin/upsdrvctl status, /usr/bin/upsdrvctl status *, \
|
|
/usr/bin/upsc *, \
|
|
/usr/bin/lsusb
|
|
|
|
# ---- still needed: apply the fix and verify ------------------------------------------ #
|
|
# `tee /etc/ups/*` already writes configs; these cover the reload path, SELinux booleans,
|
|
# and a bounded cleanup of the .bak files `tee`-based edits leave behind.
|
|
Cmnd_Alias NUT_APPLY = \
|
|
/usr/bin/tee /etc/ups/upsd.conf, /usr/bin/tee /etc/ups/upsd.users, \
|
|
/usr/bin/tee /etc/ups/ups.conf, /usr/bin/tee /etc/ups/nut.conf, \
|
|
/usr/bin/rm -f /etc/ups/*.bak-*, \
|
|
/usr/bin/upsdrvctl restart, /usr/bin/upsdrvctl restart *, \
|
|
/usr/sbin/setsebool -P allow_upsd_tcp_server 1, \
|
|
/usr/sbin/setsebool -P nis_enabled 0
|
|
|
|
# NOTE: deliberately NOT allowed, so an agent cannot power-cycle anything by accident:
|
|
# /usr/bin/upscmd (any form) — the dashboard's own gated POST is the only command path
|
|
# systemctl stop * — stopping nut-server would blind the UPS view
|
|
# editors, shells, `sh -c` — no escape hatches
|