Richiedi il privilegio di root all'interno di uno script


23

Ho uno script che può essere eseguito come sudo script.shopkexec script.sh

Sarebbe molto più bello dal punto di vista dell'utente se lo script chiedesse la password all'utente quando la eseguiva solo per nome script.sh.

Come posso "incorporare" la richiesta pkexeco sudoeseguire l'intero script con il privilegio di root?

Nota che eseguire tutto con sudo sh -cpotrebbe non essere la soluzione migliore in quanto ho funzioni nello script.

Risposte:


55

Questo funzionerà:

echo "$(whoami)"

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

esempio:

./test.sh 
blade
[sudo] password for blade: 
root

3
La cosa positiva di questo è la ricorsione con exec- chiama se stesso ma allo stesso tempo sostituisce il processo, quindi non generiamo più istanze della sceneggiatura
Sergiy Kolodyazhnyy

1
Ricorsione in soccorso !!! Ricordami di aggiungere una taglia a questa in pochi giorni!
Fabby

6
Qualcosa da tenere presente quando si fa questo è l'escalation dei privilegi; in pratica, più comandi esegui come root, più opportunità ci sono per un hacker malintenzionato di sfruttare qualcosa per ottenere l'accesso a un account root. Non sto dicendo che è sempre sbagliato far girare l'intero script come root, ma vale la pena pensarci un po 'prima di decidere di farlo. Penso che sarebbe bello (anche se non necessario) se la risposta toccasse questo.
David Z,

Se hai un valore di timeout decente impostato in / etc / sudoers, puoi opzionalmente mettere sudo davanti a ciascun comando nello script che necessita davvero dell'accesso root e lo chiederà solo una volta. Una cosa che sbaglio spesso è che chiamare un tale script da una GUI non funzionerà perché sudo ottiene / dev / null per l'immissione della password e fallisce. Questo è ciò che gksudo e kdesudo sono stati progettati per gestire perché useranno la GUI per chiedere la password.
Joe

1
@ Coder256: non credo che la tua modifica fosse corretta. "$@"si espanderà a più parole, una per ogni parametro.
jwodder,

12

Se desideri un bel dialogo, prova qualcosa del genere. L'ho strappato da qualcos'altro che ho scritto, quindi ha cose extra che potresti non aver bisogno o che desideri, ma mostra l'idea generale:

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

finestra di dialogo sudo

Questo utilizza whiptail, che puoi installare se non lo hai già:

sudo apt-get install whiptail

1
Perché stai salvando la password in una variabile?
heemayl

10
Non chiamare exec echo [PASSWORD]! Genererà un processo con la password sulla riga di comando che qualsiasi utente può vedere. Utilizzare il comando integrato echo(forzare la versione integrata con builtin echo) o il bashism <<<(in questo modo :) sudo ... <<< "$pass"; Sh e altre shell hanno Here Documents per questi casi. Inoltre, citare la password nel caso contenga caratteri speciali.
David Foerster,

In alternativa, inserisci il whiptailcomando in uno script separato e usa qualcosa di simile SUDO_ASKPASS=/path/to/askpass-with-whiptail.sh sudo -A -p "My password prompt" -- "$0" "$@"per sudogestire la richiesta di password personalizzata.
David Foerster,

@DavidFoerster Potrebbe funzionare, ma poi hai bisogno di due script oppure scrivi lo script askpass in un file temporaneo e poi lo passi a sudo.
Michael Hampton

Ok comunque altri hanno già notato che non è desiderabile passare la password a una variabile. Il modo in cui l'app si avvicina a questo è di passare l'output della finestra di dialogo al nome pipe come ho mostrato qui askubuntu.com/a/704643/295286
Sergiy Kolodyazhnyy

11

La risposta di blade19899 è davvero la strada da percorrere, tuttavia si potrebbe anche chiamare sudo bashlo shebang:

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

L'ovvio avvertimento è che funzionerà solo fino a quando viene chiamato lo script ./scripte fallirà non appena lo script viene chiamato bash script.


5
Questo è uno dei motivi per cui non si dovrebbe mai digitare bash scriptsulla riga di comando per invocare uno script. Se lo script specifica qualcosa di diverso da quello bashnella #!riga, la sua invocazione bash scriptfallirà. Se provassi a invocare uno script Python usando bash script.pyanche questo fallirebbe.
Kasperd,

1
Puoi eseguirlo con perl script, però. Perl, nel tentativo di essere davvero molto gentile, controlla la linea shebang, e se non sta invocando perl, esegue il programma corretto.
martedì

Questo è male perché sta eseguendo tutti i comandi nello script con sudo. È meglio isolare i pochi comandi che hanno davvero bisogno di sudo e aggiungerli dove necessario. Non includere la valutazione delle funzioni in queste chiamate sudo; dovrebbero essere il più chiari e minimi possibile.
Douglas tenuto il

@DouglasHeld Anche se posso essere d'accordo, questo è ciò che la domanda sta ponendo: "Come posso" incorporare "la richiesta a pkexec o sudo per eseguire l'intero script con il privilegio di root?". Abbastanza sicuro ci sarebbero casi d'uso in cui sarebbe utile essere in grado di farlo.
kos

6

Prefazione i comandi all'interno dello script con cui è necessario l'accesso root sudo: se l'utente non ha già ottenuto le autorizzazioni, lo script richiede una password a quel punto.

esempio

#!/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

Questo script può essere eseguito come sudo <scriptname>o come <scriptname>. In entrambi i casi chiederà la password, una sola volta.


2
Il problema qui è che potrebbero esserci più comandi che richiedono l'accesso come root, il che significa richiedere sudo25 diversi comandi ridondanti: è più facile chiamare sudo una volta. Qui, tuttavia, il motivo per cui il tuo script chiama sudo solo una volta è perché sudo ha un tempo di attesa di 15 minuti - i comandi che richiedono più tempo di quello dovranno essere riproposti. La tua strada funziona bene. . . non nel modo in cui ne ho bisogno per funzionare.
Sergiy Kolodyazhnyy,

@Serg Per una sceneggiatura piccola, il modo in cui ho avuto è stato semplice e veloce - non sono davvero un programmatore elegante!
Charles Green

Sei il miglior programmatore che pubblica su questa pagina. Stai usando sudo esattamente come dovrebbe essere usato - solo dove necessario e con risultati molto chiari previsti.
Douglas tenuto il

4

Sembra che nessun altro abbia affrontato l'ovvia preoccupazione qui. Inserendo sudonel tuo script che poi distribuisci promuovi cattive abitudini degli utenti . (Suppongo che tu lo stia distribuendo perché dici "dal punto di vista dell'utente").

La verità è che esiste una linea guida nell'uso di applicazioni e script che è simile al principio di sicurezza nel settore bancario di: Non dare mai le tue informazioni personali a qualcuno che ti chiama e dice che stanno chiamando "dalla tua banca" , e che esiste per ragioni simili.

La regola per le applicazioni è:

Non digitare mai la password quando richiesto a meno che non si sia certi di cosa si sta facendo. Questo vale tre volte per chiunque abbia sudoaccesso.

Se stai digitando la password perché hai eseguito sudosulla riga di comando, ottimo. Se lo stai digitando perché hai eseguito un comando SSH, va bene. Se lo stai digitando quando accedi al tuo computer, ovviamente, fantastico.

Se esegui semplicemente uno script o un file eseguibile esterno e inserisci la tua password quando ti viene richiesta, non hai idea di cosa ci faccia lo script. Potrebbe essere archiviarlo in un file temporaneo in testo normale, per quanto ne sai, e potrebbe anche non riuscire a ripulire dopo se stesso.

Ovviamente ci sono preoccupazioni separate e aggiuntive sull'esecuzione di un insieme sconosciuto di comandi come root, ma quello di cui sto parlando qui è mantenere la sicurezza sulla password stessa . Anche supponendo che l'applicazione / lo script non sia dannoso, si desidera comunque che la password venga gestita in modo sicuro per impedire ad altre applicazioni di acquisirla e utilizzarla in modo dannoso.

Quindi, la mia personale risposta a questo è, la cosa migliore da inserire nel tuo script se ha bisogno dei privilegi di root è:

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

# do privileged stuff, etc.

Anche se sono completamente d'accordo con te, un utente che esegue qualcosa senza sapere cosa fa sudo script_namee altrettanto vulnerabile, è lo stesso. Forse questa idea promuove cattive abitudini - non dirò nulla al riguardo. Ma la chiave è sapere cosa fa un programma e questa è la responsabilità dell'utente. Questa è l'idea alla base del software open source. Per quanto riguarda la mia sceneggiatura, bene. . . uno script è un semplice testo - gli utenti possono leggerlo se vogliono sapere cosa fa
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy è simile, ma se digiti la password direttamente nello script è effettivamente peggio. Uno script eseguito con sudo non conosce ancora la tua password.
Wildcard

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.