Pourquoi ai-je besoin d'un terminal pour exécuter sudo si je peux utiliser sudo sans mot de passe?


226

J'ai configuré sudopour fonctionner sans mot de passe, mais quand j'essaie ssh 'sudo Foo', je reçois toujours le message d'erreur sudo: sorry, you must have a tty to run sudo.

Pourquoi cela se produit-il et comment puis-je le contourner?

Réponses:


290

C'est probablement parce que votre /etc/sudoersfichier (ou tout fichier inclus) contient:

Defaults requiretty

... ce qui sudonécessite un ATS. Les systèmes Red Hat (RHEL, Fedora, etc.) nécessitent un TTY dans le sudoersfichier par défaut . Cela ne procure aucun avantage réel en matière de sécurité et peut être supprimé en toute sécurité.

Red Hat a reconnu le problème et celui-ci sera supprimé dans les prochaines versions.

Si la modification de la configuration du serveur n’est pas une option, vous pouvez utiliser les options -tou -ttpour sshlesquelles un pseudo-terminal est créé du côté distant, mais prenez garde qu’il comporte un certain nombre de côtés. effets.

-ttest destiné à une utilisation interactive. Il met le terminal local en rawmode afin que vous puissiez interagir avec le terminal distant. Cela signifie que si les sshE / S ne proviennent pas d'un terminal, cela aura des effets secondaires. Par exemple, toutes les entrées seront renvoyées en écho, les caractères spéciaux (terminaux ^?, ^C, ^U) provoquera un traitement spécial; en sortie, LFs sera converti en CRLFs ... (voir la réponse à Pourquoi ce fichier binaire est-il modifié? pour plus de détails.

Pour minimiser l'impact, vous pouvez l'invoquer comme suit:

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

Le < <(cat)évitera le réglage du terminal local ( le cas échéant) en rawmode. Et nous utilisons stty raw -echopour définir la discipline de ligne du terminal distant comme passerelle (de manière à ce qu'il se comporte comme le canal qui serait utilisé à la place d'un pseudo-terminal sans -tt, bien que cela ne s'applique qu'après l'exécution de cette commande, vous avez donc besoin de retarder l'envoi de quelque chose à l'entrée jusqu'à ce que cela se produise).

Notez que, puisque la sortie de la commande à distance ira à un terminal, cela affectera toujours sa mise en mémoire tampon (qui sera basée sur les lignes pour de nombreuses applications) et l'efficacité de la bande passante car elle TCP_NODELAYest activée. Également avec -tt, sshdéfinit IPQoS lowdelaypar opposition à throughput. Vous pouvez contourner les deux avec:

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

Notez également que cela signifie que la commande distante ne peut pas détecter la fin de fichier sur son stdin et que les sorties stdout et stderr de la commande distante sont fusionnées dans un flux unique.

Donc, pas si bon que ça marche après tout.

Si vous avez un obtenu un moyen de frayer un pseudo-terminal sur l'hôte distant (comme avec expect, zsh, socat, perl« s IO::Pty...), il serait alors préférable d'utiliser pour créer le pseudo-terminal pour vous connecter sudo(mais pas pour I / O), et utiliser sshsans -t.

Par exemple, avec 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'

Ou avec script(en supposant ici l'implémentation de 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'

(en supposant (pour les deux) que le shell de connexion de l'utilisateur distant ressemble à Bourne).


30

Par défaut, SUDO est configuré pour exiger un TTY. C'est-à-dire que SUDO devrait être exécuté à partir d'un shell de connexion. Vous pouvez supprimer cette exigence en ajoutant le -tcommutateur à votre invocation SSH:

ssh -t someserver sudo somecommand

L' -taffectation des forces d'un pseudo-tty.

Si vous voulez effectuer ceci globalement, modifiez /etc/sudoerspour spécifier !requiretty. Cela peut être fait par utilisateur, par groupe ou par niveau.


5
Non, ce n'est pas le défaut. Ce n'est que la distribution redhat de sudo qui avait requirettydans sa version par défaut des sudoers. Il sera corrigé dans les nouvelles versions
Stéphane Chazelas

1
@StephaneChazelas +1 pour m'avoir éclairé sur le fait qu'il est en grande partie originaire de Red Hat et de ses frères et sœurs et un autre ++ si je pouvais pour le rapport de bogue actuel!
JRFerguson

18

Utilisez le -tdrapeau sshpour forcer l'attribution de tty.

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

Ajouter une seconde -tpour forcer l'attribution quandPseudo-terminal will not be allocated because stdin is not a terminal.
Samveen

11

J'ai rencontré ce problème avec Docker et Centos 7. J'ai finalement procédé comme suit:

yum install -y sudo

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

J'ai trouvé ce hack sur https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile


1
Cette réponse me paraissait la plus logique, en utilisant également Docker et CentOS 7. C'était facile à comprendre ainsi que copier / coller convivial!
DaShaun

1

Une alternative intéressante consiste à exécuter FreeIPA ou IdM pour gérer vos utilisateurs et vos règles sudoer de manière centralisée. Vous pouvez ensuite créer des règles sudo et attribuer l'option

! requiretty

dans la règle. La commande s'exécutera comme prévu. Vous bénéficierez également de la gestion de tous les serveurs et utilisateurs à partir d’un seul ensemble de configurations.


0

J'ai eu le même problème. Dans mon cas, la solution était deux lignes

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

Explication:

  • Placez les commandes que vous voulez exécuter (y compris les commandes sudo) dans un script, par exemple "ssh_test.sh".

  • Lisez le script en entier dans une variable appelée "myscript".

  • Appelez ssh avec un seul -t et fournissez la variable au lieu d'une commande.

Avant cela, je rencontrais des problèmes en utilisant des combinaisons de lecture de stdin et en utilisant heredocs


-1

J'ai trouvé cette question en cherchant sur Google et j'ai rencontré cette erreur pour une raison complètement différente.

Mon correctif était d'arrêter d'appeler des scripts de shell en aval à sudopartir de mon script de shell parent, alors que le script de shell parent était déjà appelé avec sudo.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.