Mengapa saya perlu tty untuk menjalankan sudo jika saya bisa sudo tanpa kata sandi?

226

Saya telah mengkonfigurasi sudountuk menjalankan tanpa kata sandi, tetapi ketika saya mencoba ssh 'sudo Foo', saya masih mendapatkan pesan kesalahan sudo: sorry, you must have a tty to run sudo.

Mengapa ini terjadi dan bagaimana saya bisa mengatasinya?

merlin2011
sumber

Jawaban:

290

Itu mungkin karena /etc/sudoersfile Anda (atau file apa pun yang termasuk) memiliki:

Defaults requiretty

... yang membuatnya sudomembutuhkan TTY. Sistem Red Hat (RHEL, Fedora ...) telah diketahui membutuhkan TTY dalam sudoersfile default . Itu tidak memberikan manfaat keamanan nyata dan dapat dihapus dengan aman.

Red Hat telah mengakui masalahnya dan itu akan dihapus di rilis mendatang.

Jika mengubah konfigurasi server bukanlah suatu opsi, sebagai solusi untuk kesalahan konfigurasi tersebut, Anda dapat menggunakan opsi -tatau -ttopsi sshyang memunculkan terminal semu di sisi jarak jauh, tetapi berhati-hatilah bahwa ia memiliki sejumlah sisi. efek.

-ttdimaksudkan untuk penggunaan interaktif. Ini menempatkan terminal lokal dalam rawmode sehingga Anda berinteraksi dengan terminal jarak jauh. Itu berarti bahwa jika sshI / O bukan dari / ke terminal, itu akan memiliki efek samping. Misalnya, semua masukan akan bergema kembali, karakter terminal khusus ( ^?, ^C, ^U) akan menyebabkan pengolahan khusus; pada output, LFs akan dikonversi ke CRLFs ... (lihat jawaban untuk Mengapa file biner ini diubah? untuk lebih jelasnya.

Untuk meminimalkan dampak, Anda dapat memintanya sebagai:

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

The < <(cat)akan menghindari pengaturan dari terminal lokal (jika ada) di rawmodus. Dan kami menggunakan stty raw -echountuk menetapkan disiplin garis terminal jarak jauh sebagai lewat (efektif sehingga berperilaku seperti pipa yang akan digunakan sebagai pengganti terminal semu tanpa -tt, meskipun itu hanya berlaku setelah perintah itu dijalankan, jadi Anda perlu untuk menunda pengiriman sesuatu untuk input sampai itu terjadi).

Perhatikan bahwa karena output dari perintah jarak jauh akan menuju terminal, itu masih akan mempengaruhi buffering-nya (yang akan berbasis garis untuk banyak aplikasi) dan efisiensi bandwidth sejak TCP_NODELAYdinyalakan. Juga dengan -tt, sshatur IPQoS lowdelaysebagai lawan throughput. Anda dapat mengatasi keduanya dengan:

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

Juga, perhatikan bahwa itu berarti perintah jarak jauh tidak dapat mendeteksi end-of-file pada stdin dan stdout dan stderr dari perintah jarak jauh digabung menjadi satu aliran.

Jadi, tidak begitu bagus untuk bekerja.

Jika Anda sudah suatu punya cara untuk menelurkan sebuah pseudo-terminal di remote host (seperti dengan expect, zsh, socat, perl's IO::Pty...), maka itu akan lebih baik untuk menggunakannya untuk membuat pseudo-terminal untuk melampirkan sudoke (tapi bukan untuk I / O), dan digunakan sshtanpa -t.

Misalnya dengan 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'

Atau dengan script(di sini dengan asumsi implementasi dari 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'

(dengan asumsi (untuk keduanya) bahwa shell login dari pengguna jarak jauh adalah seperti Bourne).

Stéphane Chazelas
sumber
30

Secara default, SUDO dikonfigurasi untuk memerlukan TTY. Artinya, SUDO diharapkan dijalankan dari shell login. Anda dapat mengalahkan persyaratan ini dengan menambahkan -tpergantian ke permintaan SSH Anda:

ssh -t someserver sudo somecommand

The -talokasi kekuatan pseudo-tty.

Jika Anda ingin melakukan ini secara global, modifikasi /etc/sudoersuntuk menentukan !requiretty. Ini dapat dilakukan aa per pengguna, per grup atau semua level yang mencakup.

JRFerguson
sumber
5
Tidak, itu bukan default. Hanya distribusi redhat dari sudo yang ada requirettydi sudoers default-nya. Ini akan diperbaiki dalam rilis yang lebih baru
Stéphane Chazelas
1
@StephaneChazelas +1 untuk memberi tahu saya bahwa ini sebagian besar berasal dari Red Hat dan saudara kandungnya dan ++ lainnya jika saya bisa untuk laporan bug saat ini!
JRFerguson
18

Gunakan -tbendera sshuntuk memaksa alokasi tty.

$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
Kyle Jones
sumber
Tambahkan sedetik -tuntuk memaksa alokasi ketikaPseudo-terminal will not be allocated because stdin is not a terminal.
Samveen
11

Saya mengalami masalah ini menggunakan Docker dan Centos 7. Saya akhirnya melakukan hal berikut:

yum install -y sudo

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

Saya menemukan retasan ini di https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile

Martin Tapp
sumber
1
Jawaban ini sangat masuk akal bagi saya, menggunakan Docker dan CentOS 7 juga. Mudah dimengerti dan juga salin / tempel ramah!
DaShaun
1

Alternatif yang menarik adalah menjalankan FreeIPA atau IdM untuk mengelola pengguna Anda dan aturan sudoer secara terpusat. Anda kemudian dapat membuat aturan sudo dan menetapkan opsi

! Persyaratan kecil

dalam aturan. Perintah kemudian akan berjalan seperti yang diharapkan. Anda juga akan mendapat manfaat mengelola semua server dan pengguna dari satu set konfigurasi.

strtluge
sumber
0

Saya memiliki masalah yang sama. Dalam kasus saya, solusinya adalah dua baris

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

Penjelasan:

  • Tempatkan perintah yang ingin Anda jalankan (termasuk perintah sudo) ke dalam skrip misalnya "ssh_test.sh".

  • Baca seluruh skrip ke dalam variabel yang disebut "skrip".

  • Laksanakan ssh hanya dengan satu -t dan berikan variabel alih-alih perintah.

Sebelum ini, saya mengalami masalah menggunakan kombinasi membaca dari stdin dan menggunakan heredocs

Gerry Hickman
sumber
-1

Saya menemukan pertanyaan ini ketika Googling dan saya menemukan kesalahan ini karena alasan yang sangat berbeda.

Perbaikan saya adalah berhenti memanggil skrip shell hilir sudodari skrip shell induk saya, ketika skrip shell induk sudah dipanggil dengan sudo.

entpnerd
sumber