Żądanie uprawnień roota ze skryptu

23

Mam skrypt, który może działać jako sudo script.shlubpkexec script.sh

Byłoby o wiele ładniej z punktu widzenia użytkownika, gdyby skrypt pytał użytkownika o hasło podczas uruchamiania go po nazwie script.sh.

Jak mogę „osadzić” żądanie do pkexeclub sudouruchomić cały skrypt z uprawnieniami roota?

Zauważ, że uruchamianie wszystkiego za pomocą sudo sh -cmoże nie być najlepszym rozwiązaniem, ponieważ mam funkcje w skrypcie.

Sergiy Kolodyazhnyy
źródło

Odpowiedzi:

55

To zadziała:

echo "$(whoami)"

[ "$UID" -eq 0 ] || exec sudo "$0" "$@"

przykład:

./test.sh 
blade
[sudo] password for blade: 
root
blade19899
źródło
3
exec
Zaletą
1
Rekurencja na ratunek !!! Przypomnij mi, żebym dodał nagrodę za kilka dni!
Fabby
6
Należy przy tym pamiętać o eskalacji uprawnień; Zasadniczo, im więcej poleceń uruchamiasz jako root, tym więcej złośliwych hakerów ma okazję wykorzystać w celu uzyskania dostępu do konta root. Nie twierdzę, że zawsze źle jest uruchomić cały skrypt jako root, ale warto się nad tym zastanowić, zanim zdecydujesz się to zrobić. Myślę, że byłoby miło (choć niekoniecznie), gdyby odpowiedź na to dotykała.
David Z
Jeśli masz przyzwoitą wartość limitu czasu ustawioną w / etc / sudoers, możesz opcjonalnie umieścić sudo przed każdą komendą w skrypcie, który naprawdę potrzebuje dostępu do roota i zapyta tylko raz. Jedną z rzeczy, które często mylę, jest to, że wywoływanie takiego skryptu z GUI nie działa, ponieważ sudo otrzymuje / dev / null dla wprowadzenia hasła i nie działa. Do tego właśnie zostały zaprojektowane gksudo i kdesudo, ponieważ będą używać GUI, aby poprosić o hasło.
Joe
1
@ Coder256: Nie sądzę, aby twoja edycja była poprawna. "$@"rozwinie się do wielu słów, po jednym dla każdego parametru.
jwodder
12

Jeśli chcesz ładny dialog, spróbuj czegoś takiego. Wyrwałem to prosto z czegoś innego, co napisałem, więc zawiera dodatkowe rzeczy, których możesz nie potrzebować lub chcieć, ale pokazuje to ogólny pomysł:

brand="My Software"

# Check that the script is running as root. If not, then prompt for the sudo
# password and re-execute this script with sudo.
if [ "$(id -nu)" != "root" ]; then
    sudo -k
    pass=$(whiptail --backtitle "$brand Installer" --title "Authentication required" --passwordbox "Installing $brand requires administrative privilege. Please authenticate to begin the installation.\n\n[sudo] Password for user $USER:" 12 50 3>&2 2>&1 1>&3-)
    exec sudo -S -p '' "$0" "$@" <<< "$pass"
    exit 1
fi

okno dialogowe sudo

Używa to whiptail, który możesz zainstalować, jeśli jeszcze go nie masz:

sudo apt-get install whiptail
Michael Hampton
źródło
1
Dlaczego zapisujesz hasło w zmiennej?
heemayl
10
Nie dzwoń exec echo [PASSWORD]! Spowoduje to odrodzenie procesu z hasłem w wierszu poleceń, które każdy użytkownik może zobaczyć. Albo użyj wbudowanego polecenia echo( builtin echowymuś wbudowaną wersję za pomocą ) lub bashism <<<(tak :) sudo ... <<< "$pass"; Sh i inne powłoki mają tutaj Dokumenty dla tych przypadków. Podaj także hasło, jeśli zawiera znaki specjalne.
David Foerster,
Alternatywnie, umieścić whiptailpolecenia do osobnego skryptu i używać coś SUDO_ASKPASS=/path/to/askpass-with-whiptail.sh sudo -A -p "My password prompt" -- "$0" "$@"mieć sudoumowę z hasłem niestandardowego szybkiego.
David Foerster,
@DavidFoerster To może działać, ale wtedy albo potrzebujesz dwóch skryptów, albo piszesz skrypt askpass do pliku tymczasowego, a następnie przekazujesz go do sudo.
Michael Hampton,
Ok, ale inni już zauważyli, że niepożądane jest przekazywanie hasła do zmiennej. Sposób, w jaki podchodzę do tego id, polega na przekazaniu wyjścia okna dialogowego do nazwanego potoku, jak pokazałem tutaj askubuntu.com/a/704643/295286
Sergiy Kolodyazhnyy
11

Odpowiedź od blade19899 jest rzeczywiście słuszna, jednak można również wywołać sudo bashshebang:

#!/usr/bin/sudo bash
# ...

Oczywistym zastrzeżeniem jest to, że będzie działać tylko tak długo, jak długo skrypt jest wywoływany za pomocą ./scripti zawiedzie, gdy tylko skrypt zostanie wywołany za pomocą bash script.

kos
źródło
5
Jest to jeden z powodów, dla których nigdy nie należy pisać bash scriptw wierszu polecenia, aby wywołać skrypt. Jeśli skrypt określi coś innego niż bashw #!wierszu, wywołanie go za pomocą bash scriptzakończy się niepowodzeniem. Gdybym próbował wywołać użycie skryptu Python bash script.py, również by się nie udało.
kasperd
1
Możesz go jednak uruchomić perl script. Perl, chcąc być naprawdę naprawdę miłym, sprawdza linię shebang, a jeśli nie wywołuje perla, uruchamia odpowiedni program.
tbodt
Jest to złe, ponieważ uruchamia każdą komendę w skrypcie z sudo. Lepiej jest wyodrębnić kilka poleceń, które naprawdę potrzebują sudo i dodać je w razie potrzeby. Nie dołączaj oceny funkcji do tych wywołań sudo; powinny być tak jasne i minimalne, jak to możliwe.
Douglas odbył się
@DouglasHeld Chociaż mogę się z tym zgodzić, oto pytanie: „Jak mogę„ osadzić ”żądanie do pkexec lub sudo, aby uruchomić cały skrypt z uprawnieniami roota?”. Całkiem pewne, że w niektórych przypadkach przydatna byłaby taka możliwość.
Kos
6

Wstępuję do poleceń w skrypcie, które wymagają dostępu sudodo konta root - jeśli użytkownik nie uzyskał jeszcze uprawnień, skrypt wyświetla monit o podanie hasła.

przykład

#!/bin/sh 
mem=$(free  | awk '/Mem:/ {print $4}')
swap=$(free | awk '/Swap:/ {print $3}')

if [ $mem -lt $swap ]; then
    echo "ERROR: not enough RAM to write swap back, nothing done" >&2
    exit 1
fi

sudo swapoff -a && 
sudo swapon -a

Ten skrypt może być uruchamiany jako sudo <scriptname>lub jako <scriptname>. W obu przypadkach poprosi o hasło tylko raz.

Charles Green
źródło
2
Problem polega na tym, że może istnieć wiele poleceń, które wymagają dostępu do konta root, co oznacza wywołanie sudo25 różnych poleceń nadmiarowych - łatwiej jest wywołać sudo raz. Tutaj jednak powodem, dla którego skrypt wywołuje sudo tylko raz, jest to, że sudo ma czas na 15 minut - polecenia, które trwają dłużej, będą musiały zostać powtórzone. Twoja droga działa po prostu. . . nie tak, jak potrzebuję.
Sergiy Kolodyazhnyy
@Serg W przypadku małego skryptu mój sposób był szybki i łatwy - naprawdę nie jestem eleganckim programistą!
Charles Green
Jesteś najlepszym programistą zamieszczającym posty na tej stronie. Używasz sudo dokładnie tak, jak powinno się go używać - tylko w razie potrzeby i z bardzo wyraźnymi oczekiwanymi wynikami.
Douglas odbył się
4

Wydaje się, że nikt inny nie zajął się tutaj oczywistym problemem. Umieszczenie sudow skrypcie, który następnie rozpowszechniasz, promuje złe nawyki użytkowników . (Zakładam, że je rozpowszechniasz, ponieważ wspominasz „z punktu widzenia użytkownika”).

Prawda jest taka, że ​​istnieją wytyczne dotyczące korzystania z aplikacji i skryptów, które są podobne do zasady bezpieczeństwa w bankowości: Nigdy nie podawaj swoich danych osobowych komuś, kto dzwoni do ciebie i mówi, że dzwoni „z twojego banku” i który istnieje z podobnych powodów.

Reguła dla aplikacji jest następująca:

Nigdy nie wpisuj hasła po wyświetleniu monitu, chyba że masz pewność, co się z nim dzieje. Dotyczy to potrójnie każdego, kto ma sudodostęp.

Jeśli wpisujesz hasło, ponieważ działałeś sudow wierszu poleceń, świetnie. Jeśli wpisujesz to, ponieważ uruchomiłeś polecenie SSH, w porządku. Oczywiście, jeśli wpisujesz go podczas logowania do komputera.

Jeśli po prostu uruchomisz obcy skrypt lub plik wykonywalny i nieuprzejmie wpiszesz hasło, gdy zostaniesz o to poproszony, nie masz pojęcia, co skrypt z nim robi. Może to być przechowywanie go w pliku tymczasowym w postaci zwykłego tekstu, o ile wiesz, a nawet może nie zostać wyczyszczone po sobie.

Oczywiście istnieją osobne i dodatkowe obawy związane z uruchamianiem nieznanego zestawu komend jako root, ale tutaj mówię o utrzymaniu bezpieczeństwa samego hasła . Nawet zakładając, że aplikacja / skrypt nie jest złośliwy, nadal chcesz, aby hasło było obsługiwane bezpiecznie, aby uniemożliwić innym aplikacjom przechwycenie go i złośliwe użycie.

Tak więc, moja osobista odpowiedź na to jest najlepsza rzecz, którą mogę umieścić w swoim skrypcie, jeśli potrzebuje uprawnień roota:

#!/bin/bash
[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1;}

# do privileged stuff, etc.
Dzika karta
źródło
Chociaż całkowicie się z tobą zgadzam, użytkownik, który uruchamia coś, nie wiedząc, co robi, sudo script_namejest równie podatny na zagrożenia, jest tak samo. Może ten pomysł promuje złe nawyki - nic o tym nie powiem. Ale kluczem jest wiedza o tym, co robi program, i to jest odpowiedzialność użytkownika. To cała idea oprogramowania open source. Jeśli chodzi o mój własny skrypt, to dobrze. . . skrypt jest zwykłym tekstem - użytkownicy mogą go przeczytać, jeśli chcą wiedzieć, co robi
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy jest podobny, ale jeśli wpiszesz swoje hasło bezpośrednio w skrypcie, to w rzeczywistości będzie gorzej. Skrypt uruchamiany za pomocą sudo nadal nie zna twojego hasła.
Wildcard
1

Zrobiłem to w ten sposób:

echo -n "Enter password for sudo rights: "
read -s pass

echo $pass | sudo -S [your command here]
88 ważył
źródło
4
Przynajmniej podaj swoje zmienne.
muru
Podanie zmiennych może nawet nie pomóc, jeśli hasło zaczyna się od myślnika.
Wildcard