Продолжая неустанно трудиться на благо безопасности и удобства администрирования, мы дошли до мысли о том, что sudo — вещь удобная, но небезопасная. Или наоборот, безопасная, но неудобная. Смотря, что написано в sudoers.

Если там что-то, вроде

%wheel ALL=(ALL) NOPASSWD: ALL

то это небезопасно. Любой, кто завладел нужным аккаунтом, получает рута.
А если там

%wheel ALL=(ALL) ALL

то это неудобно. Приходится вбивать пароль каждый раз. И если писать скриптики для групповой порчи серверов

for s in server1 server2 server3; do ssh user@$s "sudo echo 'Превед!' > /etc/motd"; done

то вбивать каждый раз пароль для sudo радости не приносит.

Кроме того, пароли имеют свойство утекать, и, если кто-то завладеет аккаунтом, то ничего ему не мешает сделать alias sudo=…, где будет вороваться пароль. Да и вообще, пароли — не наш выбор. На дворе уже космические корабли бороздят просторы вселенной.

А наш выбор — ssh-ключи. Вообще-то, сильная аутентификация еще лучше, но не в этот раз.

Пускай sudo проверяет аутентичность пользователя по наличию ssh private key, public часть которого лежит в условленном месте.

Недолгий поиск нашел вот этот замечательный проект, который представляет собой pam модуль, проверяющий наличие private ключа в ssh-агенте и его соответствие public ключу в указанном файле. А sudo уже давно умеет использовать pam.

После сборки и установки pam_ssh_agent_auth.so в папку с pam-модулями (/lib/security/ обычно), надо добавить в /etc/pam.d/sudo следующее

auth sufficient pam_ssh_agent_auth.so file=/etc/security/authorized_keys

Потом убедиться, что в /etc/sudoers (используйте visudo, да) в env_keep добавлен SSH_AUTH_SOCK, добавить туда же

%wheel ALL=(ALL) ALL

или аналогичное. Ну и положить свой публичный ключ в /etc/security/authorized_keys (chmod 600 его).

После этого, если зафорварден ssh-agent, sudo не должно спрашивать пароль. И никаких NOPASSWD.

Beware, это будет работать только с sudo >= 1.6.9. В 1.6.8 и ниже pam-модулю не передаются никакие переменные окружения, в том числе и SSH_AUTH_SOCK. Несмотря на любое написанное в sudoers, старый sudo сначала обнуляет практически все переменные окружения, потом запускает pam-модуль, а потом восстанавливает нужное окружение. sudo 1.6.9 убивает только те переменные, которые надо убивать.