Правильный способ разрешить пользователю вводить пароль для скрипта bash, используя только графический интерфейс (со скрытым терминалом)

8

Я сделал скрипт bash, который использует kdialog исключительно для взаимодействия с пользователем. Он запускается из файла ".desktop", поэтому пользователь никогда не видит терминал. Он выглядит на 100% как приложение с графическим интерфейсом (хотя это всего лишь скрипт bash). Он работает только в KDE (Kubuntu 12.04).

Моя единственная проблема - безопасно и удобно обрабатывать ввод пароля . Я не могу найти удовлетворительное решение.

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

Основная проблема заключается в том, что использование kdesudoдля запуска моего сценария, который является стандартным способом графического интерфейса пользователя, означает, что весь сценарий выполняется пользователем root. Таким образом, владельцы файлов назначаются пользователю root, на которые я не могу положиться ~/в путях, и многие другие вещи не идеальны. Выполнение всего скрипта от имени пользователя root - это просто очень неудовлетворительное решение, и я считаю, что это плохая практика.

Я ценю любые идеи, позволяющие пользователю вводить пароль sudo только один раз через графический интерфейс, при этом не запуская весь сценарий от имени пользователя root. Спасибо.

MountainX
источник

Ответы:

14

Опция -Asudo позволяет вам указать вспомогательную программу (в переменной SUDO_ASKPASS), которая будет запрашивать пароль.

Создайте скрипт для запроса пароля (myaskpass.sh):

#!/bin/bash
zenity --password --title=Authentication

Затем вставьте эту строку в начале вашего скрипта:

export SUDO_ASKPASS="/path/to/myaskpass.sh"

и заменить все случаи sudo <command>с:

sudo -A <command>

Вы можете использовать любую программу для запроса пароля, какую захотите zenity. Мне пришлось заключить его в скрипт, потому что SUDO_ASKPASS должен указывать на файл, поэтому он не будет работать с --passwordопцией, требуемой для zenity.

Вышеприведенный код работает как талисман, если он запускается из командной строки или если вы выберете « Запуск в терминале» после двойного щелчка по файлу скрипта в файловом менеджере, но если вы выберете « Выполнить» или попытаетесь запустить его из файла .desktop, каждый sudoбудет запрашивать для пароля еще раз.


Если вам вообще не нужно окно терминала, вы можете сохранить пароль в переменной и передать его по адресу sudo -S. Может быть, есть некоторые проблемы с безопасностью, но я думаю, что это довольно безопасно (читайте комментарии к этому ответу ).

Вставьте эту строку в начале вашего скрипта:

PASSWD="$(zenity --password --title=Authentication)\n"

и заменить все случаи sudo <command>с:

echo -e $PASSWD | sudo -S <command>
Эрик Карвалью
источник
Спасибо. Это очень интересно. Однако при использовании этого обычного тайм-аута sudo (например, 15 минут) теряется. Мой скрипт, содержащий более 50 команд sudo, теперь запрашивает пароль пользователя более 50 раз! Я немного погуглил и не нашел решения. Вы знаете один?
MountainX
Спасибо за обновления. Предлагаемая вами альтернатива - это то, что я исключил из соображений безопасности, но, прочитав комментарии по предоставленной вами ссылке, я думаю, что она достаточно безопасна. И это простой способ решить проблему. Спасибо.
MountainX
Тестирование в моей системе должно быть sudo -s(в нижнем регистре s), а не sudo -S(в верхнем регистре s).
WinEunuuchs2Unix
0

Это основано на превосходном ответе Эрика Карвалью. Я публикую это, чтобы уточнить проблему, с которой я столкнулся. В частности, при использовании этого обычного тайм-аута sudo (например, 15 минут) теряется. Мой скрипт, содержащий более 50 команд sudo, теперь запрашивает пароль пользователя более 50 раз!

Вот полный рабочий пример всех частей решения. Он состоит из сценария bash, сценария "myaskpass", как предложил Эрик, и файла ".desktop". Все это должно быть на 100% графическим интерфейсом (никакого взаимодействия с терминалом вообще), поэтому файл .desktop необходим (afaik).

$ cat myaskpass.sh 
#!/bin/bash
kdialog --password "Please enter your password: "
exit 0


$ cat askpasstest1.desktop 
#!/usr/bin/env xdg-open
[Desktop Entry]
Comment=SUDO_ASKPASS tester1
Exec=bash /home/user/test/askpasstest1.sh
GenericName=SUDO_ASKPASS tester1
Name=SUDO_ASKPASS tester1
NoDisplay=false
Path[$e]=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
Categories=Application;Utility;
X-KDE-SubstituteUID=false
X-KDE-Username=

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

#!/bin/bash

sudo -k
SUDO_ASKPASS="/home/user/test/myaskpass.sh" sudo -A touch filemadeas_askpass1
touch filemadeas_regularuser1
SUDO_ASKPASS="/home/user/test/myaskpass.sh" sudo -A touch filemadeas_askpass2
touch filemadeas_regularuser2
ls -la filemadeas* > /home/user/test/fma.log
kdialog --title "Files Created" --textbox /home/user/test/fma.log 640 480
sudo rm filemadeas_*
rm fma.log

exit 0
MountainX
источник
Запустив этот скрипт из командной строки, пароль запрашивается только один раз. При запуске из графического интерфейса (щелкнув .desktop или .sh в файловом менеджере) каждый sudo -Aповторно запрашивает пароль. Я постараюсь выяснить это.
Эрик Карвалью
Я только что обновил свой ответ.
Эрик Карвалью
Эрик ... ты нашел решение проблемы?
Энтони
0

Следующий скрипт работает через командную строку, файл рабочего стола или двойной щелчок, запрашивает пароль только один раз, а шаблон команды sudo -Sp '' <your command here> <<<${sudo_password}может использоваться несколько раз в любом месте файла:

    # get sudo password
    sudo_password=$( gksudo --print-pass --message="Provide permission to make system changes: Type your password or press Cancel." -- : 2>/dev/null )
    # check for null entry or cancellation
    if [[ ${?} != 0 || -z ${sudo_password} ]]
    then
        exit 4
    fi
    if ! sudo -kSp '' [ 1 ] <<<${sudo_password} 2>/dev/null
    then
        exit 4
    fi
    # command
    sudo -Sp '' gedit "/etc/hosts" <<<${sudo_password}
Сади
источник