Сценарий оболочки — Sudo-разрешения, потерянные со временем

#bash #shell #ubuntu #sudo

#bash #оболочка #ubuntu #sudo

Вопрос:

Я создал простой скрипт bash, который должен сохранять права суперпользователя на протяжении всего скрипта. К сожалению, но понятно, что скрипт теряет свои sudo повышенные разрешения, когда sleep происходит. Не подходит для меня:

 sudo echo "I am sudo!" # Asks for passwords
sleep(60)
sudo echo "I am sudo!" # Need to enter password again.
  

Я думал о замене sleep циклом while, который поддерживает работу sudo, но я почти уверен, что есть лучшие варианты, позволяющие сохранить sudo разрешения на протяжении всего сценария?

Спасибо

Комментарии:

1. почему вы не разрешаете пользователю запускать его sudo ?

Ответ №1:

Гибкость sudo сильно недооценивается. Это приводит к очень плохим практикам (таким как sudo su - метод операции canon-ball).

Гораздо лучший метод — специально разрешить команды, которые вы собираетесь разрешить, без использования пароля:

 phill = NOPASSWD: /bin/ls, /usr/bin/lprm
  

При желании вы можете сделать это для определенных пользователей с определенных хостов, работающих от имени определенных пользователей-администраторов. Вы даже можете запретить пользователям передавать экранирование оболочки в качестве параметров. Вы можете заставить sudo запретить запущенной программе динамически выполнять дальнейшие приложения и т.д. и т.п. Вы захотите прочитать справочную страницу для sudoers (и обязательно ознакомьтесь с процедурами редактирования этого специального файла!).

Вот небольшой пример того, (отсюда):

 User_Alias     OPERATORS = joe, mike, jude
Runas_Alias    OP = root, operator
Host_Alias     OFNET = 10.1.2.0/255.255.255.0
Cmnd_Alias     PRINTING = /usr/sbin/lpc, /usr/bin/lprm

OPERATORS ALL=ALL
#The users in the OPERATORS group can run any command from any terminal.

linus ALL=(OP) ALL
# The user linus can run any command from any terminal as any user in the OP group (root or operator).

user2 OFNET=(ALL) ALL
# user user2 may run any command from any machine in the OFNET network, as any user.

user3 ALL= PRINTING
# user user3 may run lpc and lprm from any machine.

go2linux ALL=(ALL) ALL
# user go2linux may run any command from any machine acting as any user. (like Ubuntu)

 If you want not to be asked for a password use this form
go2linux ALL=(ALL) ALL NO PASSWD: ALL
  

Ответ №2:

Работая строго в скрипте (и не редактируя файл sudoers или вызывая скрипт через sudo ./script.sh ), вот какой, на мой взгляд, самый чистый метод.

 startsudo() {
    sudo -v
    ( while true; do sudo -v; sleep 50; done; ) amp;
    SUDO_PID="$!"
    trap stopsudo SIGINT SIGTERM
}
stopsudo() {
    kill "$SUDO_PID"
    trap - SIGINT SIGTERM
    sudo -k
}
  

По сути, это определяет пару функций для включения и отключения режима sudo. Вызов startsudo перед запуском вашего кода, использующего sudo, проверяет подлинность с помощью sudo, запускает фоновый цикл обновления sudo, сохраняет PID цикла и устанавливает блокировку сигнала для остановки режима sudo при нажатии Ctrl C. Вызов stopsudo завершает цикл, очищает перехватчик сигналов и делает недействительной предыдущую аутентификацию с помощью sudo.

После копирования этих функций в свой скрипт, используйте их следующим образом.

 startsudo
echo "Sudo mode is active."
# whatever you want to do with sudo
stopsudo
  

Я хотел бы поблагодарить @karl за простоту встраивания цикла обновления sudo и @sehe за указание на то, что для завершения цикла следует использовать перехват сигнала, если он не завершается обычным образом. Обе эти идеи улучшили мой скрипт резервного копирования btrfs, который использует цикл обновления sudo, чтобы избежать повторного запроса пользователя после того, как резервное копирование вложенного тома занимает больше времени, чем время ожидания sudo.

Ответ №3:

Вы можете настроить это время ожидания, добавив в /etc /sudoers

 Defaults timestamp_timeout=#Number of minutes
  

Но его намного проще запустить

 sudo ./worker.sh
  

Ответ №4:

Вот обходной путь:

 sudo echo "I am sudo!" # Asks for passwords
( while true; do sudo -v; sleep 40; done ) amp;   # update the user's timestamp
sudoPID=$!
# ...
sleep(60)
sudo echo "I am sudo!" # Need to enter password again.
kill -TERM $sudoPID
sudo -k  # invalidate the user's timestamp at end of script (does not require a password)
  

Комментарии:

1. Если вы собираетесь взломать его таким образом, ПО крайней мере, убедитесь, что kill и sudo -k зарегистрированы в вашем скрипте как ловушки сигналов. Это требует больших дыр в безопасности. (прервать скрипт с помощью Ctrl-C, sudo автоматически поддерживается на неопределенный срок)

Ответ №5:

Это мой способ:

 #!/bin/sh
echo "Working..."
# add you pass
echo "yourpass" >> file.pass ;sleep 5 
# Check if root
if [ `cat file.pass | sudo -S su root -c whoami` != "root" ]; then
echo "Not running as root. Exiting..."
sleep 2
echo "Cleaning..."
sleep 1
srm file.pass
echo "Cleaned"
exit 0
else
echo "Running as root. Good"
sleep 2
# and run any sudo with
cat file.pass | sudo -S su root -c ls #<any command>
fi

sleep 5
echo `cat file.pass | sudo -S su root -c whoami` "say bay bay"
# if pass no longer need
srm file.pass
echo "End session :)"
exit 0
  

Комментарии:

1. Это выглядит как правильный ответ, но сохранение пароля пользователя в файл кажется довольно небезопасным. Кроме того, что делает srm команда? В моем дистрибутиве Linux этого нет.

Ответ №6:

Получите привилегии root раз и навсегда:

 sudo su -
# What I need to do with root