# driveripper-ops sudo rules for the homelab dashboards UPS work. # # Install (from the repo checkout, as a user with sudo): # # sudo visudo -cf deploy/nut-sudoers # syntax check FIRST # sudo install -m 0440 -o root -g root deploy/nut-sudoers /etc/sudoers.d/dashboards-nut # sudo visudo -cf /etc/sudoers.d/dashboards-nut # and check the installed copy # # Scope: absolute paths only (`secure_path` is in effect), wildcards only where the command # is read-only or idempotent, and nothing here grants a shell, `sh -c`, an editor, or a # client that can send instant commands. # # WHY THESE ARE NEEDED # Reads already work with zero privileges — upsd on driveripper serves `LIST UPS` / # `LIST VAR` unauthenticated (on port 3051, not 3493). What is missing is a upsd.users # entry with `instcmds`, which is the only thing standing between the dashboard and its # battery-test buttons. `tee /etc/ups/*` is already granted, but writing upsd.users blind # would drop the accounts upsmon authenticates as — upsmon must run as a user with # `shutdown`, so an overwritten file means no orderly power-down. So: read first. # ---- already present on driveripper (used during setup) ------------------------------ # # (root) NOPASSWD: /usr/bin/tee /etc/ups/* # write a config file # (root) NOPASSWD: /usr/bin/cp /etc/ups/* /home/ops/* # copy one out (root-owned) # (root) NOPASSWD: /usr/bin/systemctl start|restart|reload|enable * # (root) NOPASSWD: /usr/bin/udevadm * # USB device discovery # (root) NOPASSWD: /usr/bin/firewall-cmd * # only if upsd must serve the LAN # (root) NOPASSWD: /usr/bin/dnf install * # nut, nut-client # ---- read: what is actually configured, before anything is rewritten ----------------- # Cmnd_Alias NUT_READ = \ /usr/bin/cat /etc/ups/*, \ /usr/bin/journalctl -u nut*, \ /usr/bin/systemctl status nut*, \ /usr/bin/upsdrvctl status, \ /usr/bin/upsc *, \ /usr/sbin/ss -ltnp, \ /usr/bin/lsusb, \ /usr/sbin/getenforce, \ /usr/bin/ausearch -m avc *, /usr/sbin/sealert -l * # ---- write: add/replace a scoped user, then reload ----------------------------------- # Cmnd_Alias NUT_WRITE = \ /usr/bin/tee /etc/ups/upsd.users, \ /usr/bin/tee /etc/ups/upsd.conf, \ /usr/bin/systemctl restart nut-server, \ /usr/bin/systemctl reload nut-server # ---- deliberately NOT granted -------------------------------------------------------- # # /usr/bin/upscmd, /usr/bin/upsrw — the dashboard's gated POST /api/ups/command is the # ONLY command path in this project, by design # systemctl stop * — stopping nut-server blinds the UPS view # tee /etc/ups/ups.conf, upsmon.conf — driver instances and shutdown policy are the # operator's, not the dashboard's # sh, bash, vim, tee to anything else — no escape hatches