Perché ho bisogno di un tty per eseguire sudo se posso sudo senza una password?


226

Ho configurato sudoper funzionare senza una password, ma quando provo a ssh 'sudo Foo'ottenere ancora il messaggio di errore sudo: sorry, you must have a tty to run sudo.

Perché questo accade e come posso aggirarlo?

Risposte:


290

Questo probabilmente perché il tuo /etc/sudoersfile (o qualsiasi altro file incluso) ha:

Defaults requiretty

... il che rende sudonecessario un TTY. È noto che i sistemi Red Hat (RHEL, Fedora ...) richiedono un TTY nel sudoersfile predefinito . Ciò non offre alcun reale vantaggio in termini di sicurezza e può essere rimosso in modo sicuro.

Red Hat ha riconosciuto il problema e verrà rimosso nelle versioni future.

Se la modifica della configurazione del server non è un'opzione, come soluzione per quella errata configurazione, è possibile utilizzare le opzioni -to -tta sshcui viene generato uno pseudo-terminale sul lato remoto, ma attenzione che ha un certo numero di lati effetti.

-ttè pensato per l'uso interattivo. Mette il terminale locale in rawmodalità in modo da interagire con il terminale remoto. Ciò significa che se l' sshI / O non proviene da / verso un terminale, ciò avrà effetti collaterali. Ad esempio, tutti gli input verrà eco indietro, caratteri speciali terminali ( ^?, ^C, ^U) causerà elaborazione speciale; sull'output, LFs verrà convertito in CRLFs ... (vedere questa risposta a Perché questo file binario viene modificato? per maggiori dettagli.

Per ridurre al minimo l'impatto, è possibile invocarlo come:

ssh -tt host 'stty raw -echo; sudo ...' < <(cat)

Il < <(cat)eviterà l'impostazione del terminale locale (se presente) in rawmodalità. E stiamo usando stty raw -echoper impostare la disciplina di linea del terminale remoto come pass through (in modo efficace, quindi si comporta come la pipe che verrebbe utilizzata al posto di uno pseudo-terminale senza -tt, anche se questo si applica solo dopo l'esecuzione di quel comando, quindi è necessario ritardare l'invio di qualcosa per l'input fino a quando ciò accade).

Si noti che poiché l'output del comando remoto verrà indirizzato a un terminale, ciò influenzerà comunque il suo buffering (che sarà basato su linea per molte applicazioni) e l'efficienza della larghezza di banda poiché TCP_NODELAYè attiva. Inoltre -tt, sshimposta IPQoS su lowdelayopposto a throughput. Puoi aggirare entrambi con:

ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)

Inoltre, si noti che significa che il comando remoto non è in grado di rilevare la fine del file sul suo stdin e che lo stdout e lo stderr del comando remoto vengono uniti in un singolo flusso.

Quindi, dopotutto, non è un buon lavoro.

Se hai un ottenuto un modo per generare una pseudo-terminale sul host remoto (come con expect, zsh, socat, perls' IO::Pty...), allora sarebbe meglio usare che per creare la pseudo-terminale da allegare sudoa (ma non per I / O) e utilizzare sshsenza -t.

Ad esempio, con expect:

ssh host 'expect -c "spawn -noecho sh -c {
     exec sudo cmd >&4 2>&5 <&6 4>&- 5>&- 6<&-}
 exit [lindex [wait] 3]" 4>&1 5>&2 6<&0'

O con script(qui assumendo l'implementazione da util-linux):

ssh host 'SHELL=/bin/sh script -qec "
              sudo cmd <&3 >&4 2>&5 3<&- 4>&- 5>&-
            " /dev/null 3<&0 4>&1 5>&2'

(supponendo (per entrambi) che la shell di accesso dell'utente remoto sia simile a Bourne).


30

Per impostazione predefinita, SUDO è configurato per richiedere un TTY. Cioè, SUDO dovrebbe essere eseguito da una shell di login. È possibile annullare questo requisito aggiungendo il -tpassaggio alla chiamata SSH:

ssh -t someserver sudo somecommand

L' -tassegnazione forze di una pseudo-tty.

Se si desidera eseguire questa operazione a livello globale, modificare /etc/sudoersper specificare !requiretty. Questo può essere fatto aa per utente, per gruppo o livello onnicomprensivo.


5
No, non è l'impostazione predefinita. È solo la distribuzione redhat di sudo che aveva requirettynei suoi sudoer predefiniti. Sarà risolto nelle versioni più recenti
Stéphane Chazelas,

1
@StephaneChazelas +1 per avermi chiarito che è in gran parte indigeno di Red Hat e dei suoi fratelli e un altro ++ se potessi per l'attuale segnalazione di bug!
JRFerguson,

18

Usa la -tbandiera sshper forzare l'allocazione di tty.

$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$

Aggiungi un secondo -tper forzare l'allocazione quandoPseudo-terminal will not be allocated because stdin is not a terminal.
Samveen

11

Ho riscontrato questo problema utilizzando Docker e Centos 7. Ho finito per fare quanto segue:

yum install -y sudo

sed -i -e 's/Defaults requiretty.*/ #Defaults requiretty/g' /etc/sudoers

Ho trovato questo trucco su https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile


1
Questa risposta ha avuto più senso per me, usando anche Docker e CentOS 7. È stato facile da capire e da copiare / incollare!
DaShaun,

1

Un'alternativa interessante è eseguire FreeIPA o IdM per gestire centralmente i tuoi utenti e le regole sudoer. È quindi possibile creare regole sudo e assegnare l'opzione

! requiretty

nella regola. Il comando verrà quindi eseguito come previsto. Avrai anche i vantaggi di gestire tutti i server e gli utenti da un unico set di configurazioni.


0

Ho avuto lo stesso problema. Nel mio caso, la soluzione era di due righe

myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"

Spiegazione:

  • Inserire i comandi che si desidera eseguire (inclusi i comandi sudo) in uno script, ad esempio "ssh_test.sh".

  • Leggi l'intero script in una variabile chiamata "myscript".

  • Richiamare ssh con solo uno -t e fornire la variabile invece di un comando.

Prima di questo, mi sono imbattuto in problemi usando combinazioni di lettura da stdin e usando heredocs


-1

Ho trovato questa domanda mentre cercavamo su Google e ho riscontrato questo errore per una ragione completamente diversa.

La mia correzione era quella di smettere di chiamare script shell downstream come sudodal mio script shell genitore, quando lo script shell genitore era già stato chiamato con sudo.

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.