Как ввести пароль только один раз в bash-скрипте, требующем sudo

21

Данные

  • Я хочу, чтобы пользователи-операторы на этой машине монтировали свои собственные ресурсы cifs.
  • sudoersФайл уже содержит /bin/mount -t cifs //*/* /media/* -o username=*команду для всех операторов
  • Я хочу, чтобы пользователи монтировали cifsобщий ресурс через скрипт, набирая пароль только один раз, а не дважды.
  • Пароль sudo и пароль cifs идентичны.

Что у меня уже есть

Этот скрипт работает:

#!/bin/bash
sudo 'mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER'

... но это требует, чтобы пользователи вводили один и тот же пароль дважды!

  • Один раз для sudo
  • Один раз для самой горы

Это также будет работать:

#!/bin/bash
echo -n Password: 
read -s szPassword
echo $szPassword | sudo -S sh -c 'echo $szPassword | mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER'

... но для этого нужно, чтобы все операторы могли это делатьsudo sh (серьезная проблема безопасности)

Вопрос

Как смонтировать долю CIFS в Баш ¹ без ввода shв sudoersфайл и не создавая постоянный / временный файл ???

Примечание 1: нет Python, Perl, C, Go, ... пожалуйста?
Примечание 2: я знаю, что могу просто удалить пароль через sudoersфайл, но я пытаюсь повысить безопасность, а не ослабить его, не отказываясь от удобства ...

Fabby
источник
2
Как насчет printf "%s\n" "$szPassword" "$szPassword" | sudo -S mount -t cifs / ...?
Муру
Попробуй это сейчас! @Muru
Fabby

Ответы:

24

Вместо этого вы должны заставить пользователя использовать sudo as sudo script. просто проверьте, запускается ли скрипт от имени пользователя root, если не спросите его

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root, use sudo "$0" instead" 1>&2
   exit 1
fi

Не пытайтесь захватить пароль ваших пользователей.

Braiam
источник
1
Возможно, я что-то упускаю, но не могли бы вы объяснить, как это уменьшает количество запросов пароля с двух до одного? В противном случае я не вижу, как это отвечает на вопрос.
Олифаунт - восстановить Монику
@Oliphaunt Я не вижу две подсказки пароля, вы можете это объяснить? Кроме того, этот ответ не то, что хочет ОП, а то, что ему нужно. Это чистое и правильное решение, когда вам нужно запускать команды от имени пользователя root и как это делают другие утилиты (проверьте, не выполнил ли root, иначе
выручите
1
Проблема OP (насколько я понимаю) состоит в том, что у пользователя запрашивается пароль, sudoа затем (после успешной аутентификации) снова mount. В их случае использования эти пароли идентичны, поэтому я понимаю, почему ОП хочет, чтобы пользователь вводил этот пароль только один раз. Я не верю, что ваше решение поможет с этим. Я согласен с тем, что не следует захватывать пароли.
Олифаунт - восстановить Монику
Спасибо, но я, возможно, немного упростил вопрос: это уже скрипт, уже содержит этот тест (кроме 1>&2), находится в автозапуске, и раньше это был только один ресурс cifs, но теперь это три, так что действительно один пароль нужно. (Он уже содержит этот тест на случай, если кто-то другой, не
являющийся
@ Fabby Я все еще думаю, что вы подходите к проблеме неправильно. Для этих случаев есть помощник, который «запоминает» пароль общего ресурса CIFS / SMB безопасно ( ~/.smbcredentialsнапример, редактирование ) и даже без необходимости использования sudo (если вы используете gvfs, umount или polkit).
Брайам
7

Я тупой!

Следующий скрипт:

#!/bin/bash
read -p "Password: " -s szPassword
printf "%s\n" "$szPassword" | sudo --stdin mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER,password="$szPassword"

просто работает и:

  1. Не создает никаких файлов, содержащих пароли
  2. Позволяет пользователю вводить только один пароль для нескольких общих ресурсов (включая Windows)
  3. Не нуждается в дополнительных привилегиях. :-)
Fabby
источник
1
1 вопрос: выводит ли команда команду в список процессов?
Rinzwind
3
@Rinzwind как встроенный, он не должен быть в bash или zsh. Команда mount могла бы, хотя.
Муру
<<<можно также использовать вместо printf , но лучшим подходом было бы readвообще отказаться от использования и просто использовать sudo --stdinвсе само. Нечто подобное $ printf "Type out your password\n" && sudo --stdin apt-get update Пользователь все еще может ввести пароль sudo. и это не поместит его в список процессов. Но, конечно, существует бесконечное количество возможных других проблем безопасности, таких как клавиатурные шпионы, потенциальные уязвимости sudo, и бла, и бла, и бла в бесконечность
Сергей Колодяжный
@SergiyKolodyazhnyy: Не стесняйтесь редактировать , чувак!
Fabby
3

Не требовать sudoпароля для выполнения этой команды; запрос пароля mountостается.

В sudoers, включить что-то вроде

ALL        ALL = NOPASSWD: /bin/mount -t cifs //*/* /media/* -o username=*

После включения этого sudoбольше не будет запрашивать пароль для этой конкретной команды; пользователь все еще должен предоставить пароль для mountкоманды.

Примечание : я взял команду дословно из того, что вы включили в вопрос; Я не проверял, позволят ли его подстановочные знаки пользователям делать что-то неприятное. Прочитайте sudoersman-страницу для примеров злобности. В частности, обратите внимание, что эта строка sudoersпозволяет пользователю добавлять любое количество -oпереключателей или других аргументов mount. Возможно, вы захотите переосмыслить свой подход, например, добавив скрипт, такой как предлагает @Braiam, и разрешите его выполнение sudoбез дополнительной аутентификации. Затем сценарий гарантирует, что пользователи могут запускать только ту форму, mountкоторую вы хотите, чтобы они запускали.

Кроме того, вместо того, чтобы разрешить это для всех пользователей, вы также можете ограничить это членами определенной группы, например, вы можете создать группу cifsmountи затем иметь

%cifsmount ALL = NOPASSWD: /bin/mount -t cifs //*/* /media/* -o username=*
Олифаунт - восстановить Монику
источник
@ Fabby Извините, но что в этом такого опасного? Также я могу обнаружить намек на сарказм, не уверен.
Олифаунт - восстановить Монику
хорошо, даже если sudo не требует пароля, mount может по-прежнему требовать пароль. Файл / etc / sudoers может быть использован только для того, чтобы sudo не требовал пароль. Это не повлияет на то, запрашивает ли mount пароль. Если человеку не удалось подключиться, то sudo просто завершил бы выполнение команды, которая не удалась, что, вероятно, не является проблемой.
TOOGAM
@TOOGAM Это было мое намерение. Один пароль вместо двух.
Олифаунт - восстановить Монику
Мое намерение состоит в том, чтобы сохранить одну группу «operator» в файле sudoers, поэтому, если оператор пытается смонтировать свои собственные данные, ему все равно придется вводить пароль, но для монтирования «стандартных» операторов монтирования ему нужно только ввести пароль один раз вместо 5 раз ... Но ваше решение может работать для других, так что проголосовало ... (и оригинальные комментарии удалены)
Fabby
1

Общее решение этих проблем - поместить следующую преамбулу в начало вашего sudo, требующего сценариев:

#!/bin/bash
case $EUID in
   0) : cool we are already root - fall through ;;
   *) # not root, become root for the rest of this session
      # (and ask for the sudo password only once)
      sudo $0 "$@" ;;
esac
# now the present process is effective-UID  (root)
# so there's no need to put sudo in front of commands

any more commands here will run as superuser ...

Очевидно, что это имеет недостаток в том, что если некоторые команды в скрипте не требуют sudoзапуска, здесь есть ненужное повышение привилегий.

Во всяком случае, думал, что поделюсь этим маленьким советом. Самое приятное в этом то, что если вы уже являетесь пользователем root с эффективной эффективностью (например, если вы уже называли его с помощью sudo), он корректно поступает правильно. Также выдает ошибку и заставляет вас повторно вводить / перезапускать (с помощью sudo) менее дружественно.

Вы можете также захотеть проверить timestamp_timeoutпеременную, в man 5 sudoersкоторой указывается sudoзапоминать учетные данные пользователя в течение ограниченного количества минут (и может быть дробным).

arielf
источник
Я упростил сценарий, чтобы получить простой ответ: сценарий уже содержит: #test if root: if not: bail out if [[ $EUID -ne 0 ]]; then echo "This script must be run as root, use sudo "$0" instead" 1>&2 exit 1 fi Дело в том, что он также содержит несколько монтирований, все с одним и тем же паролем (снова: удален), но все равно спасибо ...
Fabby
1
Дело в том, что для решения, приведенного выше, потребуется только один ввод пароля (для sudo). Это не должно требовать другого. Кроме того, он является общим (и более элегантным, чем выдача сообщения об ошибке и необходимость повторного ввода команды с помощью sudo) для всех подобных проблем, даже если для них требуется несколько (более двух) привилегированных команд.
Ариэльф
Это должно, но это не так ! ;-) Это потому, что для каждого монтирования общего ресурса cifs также требуется пароль. (поскольку он может отличаться от пароля Ubuntu, но в данном случае это не так, поскольку операторы синхронизируют свои пароли Windows и Ubuntu)
Fabby