Sudoers Best Practices: Delegating Root Safely - 夜莺博客

Sudoers Best Practices: Delegating Root Safely

sudo is the standard way to give operators the access they need without handing out the root password, but most sudoers files in the wild are either all-or-nothing or one careless line away from a privilege escalation. The file is parsed top-down with the last match winning, it is edited through visudo for a reason, and the difference between ALL=(ALL) ALL and a scoped command list is the difference between an audit finding and a clean review. Here is a practical policy for a server fleet.

Why visudo and why /etc/sudoers.d

Edit the sudoers file only with visudo: it locks the file, checks syntax on exit, and refuses to install a broken policy — a broken sudoers file can lock every administrative account out of a host at once. For anything other than a one-line fix, put the change in a drop-in file instead of editing the main file:

sudo visudo -f /etc/sudoers.d/90-ops-team
sudo visudo -cf /etc/sudoers.d/90-ops-team     # syntax check only

The main file ends with #includedir /etc/sudoers.d, and the include line deliberately starts with # — that is not a comment, it is the literal directive. Removing it silently disables every drop-in file on the host. Drop-in filenames must not contain a dot or a tilde, because the parser ignores those files.

Rule structure

# who  where=(as whom:as group)  what
%ops    ALL=(root)   /usr/bin/systemctl restart nginx
alice   ALL=(ALL)    ALL
bob     web01=(root) NOPASSWD: /usr/sbin/nginx -t
  • who — a user or a %group. Prefer groups: membership changes then do not require editing policy.
  • where — the hostname the rule applies to, which matters when the same file is distributed to a whole fleet.
  • as whom — run as root by default; specify a service account where possible instead.
  • what — the command list. This is where least privilege actually lives.

Scoping commands properly

Cmnd_Alias NET_TOOL = /usr/bin/tcpdump, /usr/sbin/ethtool, /usr/bin/ss
Cmnd_Alias SERVICES = /usr/bin/systemctl status *, /usr/bin/systemctl restart nginx

%netops  ALL=(root) NET_TOOL, SERVICES

Two warnings that come up in every review. Wildcards are dangerous: /usr/bin/systemctl restart * effectively grants root over every service on the host, and any rule ending in a wildcard that a user can also write to is an escalation path. Second, absolute paths are mandatory — reboot is not a valid command specification because PATH is not consulted in sudoers, and the same applies to arguments: without a fixed path, a user can put their own binary earlier in PATH.

NOPASSWD: convenience with a cost

# automation account, tightly scoped
svc-deploy ALL=(root) NOPASSWD: /usr/local/bin/deploy.sh, /usr/bin/systemctl restart myapp

# never this
ops ALL=(ALL) NOPASSWD: ALL

NOPASSWD: ALL means anyone who compromises that account has root with no second factor. It is acceptable for a narrowly scoped automation account, which is exactly why the automation account should be the only place it appears. For humans, keep the password prompt — it is the last control that survives a stolen SSH key.

Logging and verification

Defaults logfile=/var/log/sudo.log
Defaults log_input, log_output
Defaults iolog_dir=/var/log/sudo-io
sudo -l                    # what am I allowed to do here?
sudo -l -U alice           # what is alice allowed to do?
sudo -k                    # clear cached credentials
sudo -u postgres psql

sudo -l -U <user> is the command to run after every policy change: it resolves group membership, sudoers.d files and host matching and prints the effective rules. If that output is not what you intended, nothing else in the file matters.

Hardening checklist

  • Grant access to groups, never to individual users, so joiner-mover-leaver is a group operation.
  • Fix the command paths and avoid trailing wildcards; use aliases so the intent is auditable.
  • Keep NOPASSWD for service accounts only.
  • Log input and output for privileged commands on production hosts.
  • Distribute sudoers.d files from configuration management and run visudo -cf in CI before they land.
  • Validate with sudo -l -U on a canary host, then roll out.

See also: OpenSSH server hardening, centralised authentication with FreeIPA, and SELinux denial troubleshooting.

原文链接:https://www.digitalocean.com/community/tutorials/how-to-edit-the-sudoers-file