web-dev-qa-db-fra.com

Pourquoi ai-je besoin d'un tty pour exécuter Sudo si je peux Sudo sans mot de passe?

J'ai configuré Sudo pour fonctionner sans mot de passe, mais lorsque j'essaie de 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 contourner ce problème?

229
merlin2011

C'est probablement parce que votre fichier /etc/sudoers (Ou tout fichier qu'il contient) a:

Defaults requiretty

... ce qui fait que Sudo nécessite un ATS. Les systèmes Red Hat (RHEL, Fedora ...) sont connus pour exiger un TTY dans le fichier sudoers par défaut. Cela n'apporte aucun réel avantage en termes de sécurité et peut être retiré en toute sécurité.

Red Hat a reconnu le problème et il sera supprimé dans les futures versions.

Si la modification de la configuration du serveur n'est pas une option, comme solution de contournement pour cette mauvaise configuration, vous pouvez utiliser les options -t Ou -tt Pour ssh qui apparaît un pseudo-terminal sur le côté distant, mais attention, il a un certain nombre d'effets secondaires.

-tt Est destiné à une utilisation interactive. Il place le terminal local en mode raw pour que vous interagissiez avec le terminal distant. Cela signifie que si ssh les E/S ne proviennent pas de/vers un terminal, cela aura des effets secondaires. Par exemple, toutes les entrées seront renvoyées en écho, des caractères terminaux spéciaux (^?, ^C, ^U) Entraîneront un traitement spécial; en sortie, LFs sera converti en CRLFs ... (voir cette 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)

La fonction < <(cat) évitera le paramétrage du terminal local (le cas échéant) en mode raw. Et nous utilisons stty raw -echo Pour définir la discipline de ligne du terminal distant comme passage (en fait, il se comporte comme le tuyau 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 devez donc retarder l'envoi de quelque chose pour entrée jusqu'à ce que cela se produise).

Notez que puisque la sortie de la commande distante ira à un terminal, cela affectera toujours sa mise en mémoire tampon (qui sera basée sur la ligne pour de nombreuses applications) et l'efficacité de la bande passante puisque TCP_NODELAY Est activé. Également avec -tt, ssh définit l'IPQoS sur lowdelay par 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 stdout et stderr de la commande distante sont fusionnés en un seul flux.

Donc, pas un si bon travail après tout.

Si vous avez un moyen de générer un pseudo-terminal sur l'hôte distant (comme avec expect, zsh, socat, Perl's IO::Pty ...), alors il serait préférable de l'utiliser pour créer le pseudo-terminal pour attacher Sudo à (mais pas pour les E/S), et utiliser ssh sans -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).

294

Par défaut, Sudo est configuré pour exiger un ATS. Autrement dit, Sudo devrait être exécuté à partir d'un shell de connexion. Vous pouvez contourner cette exigence en ajoutant le -t basculez vers votre invocation SSH:

ssh -t someserver Sudo somecommand

Le -t force l'allocation d'un pseudo-tty.

Si vous souhaitez effectuer cette opération globalement, modifiez /etc/sudoers spécifier !requiretty. Cela peut être fait par utilisateur, par groupe ou au niveau global.

30
JRFerguson

Utilisez le -t drapeau à ssh pour forcer l'allocation tty.

$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
18
Kyle Jones

J'ai rencontré ce problème en utilisant Docker et Centos 7. J'ai fini par faire ce qui 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

11
Martin Tapp

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

! require

dans la règle. La commande s'exécutera alors comme prévu. Vous aurez également les avantages de gérer tous les serveurs et utilisateurs à partir d'un seul ensemble de configurations.

1
strtluge

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

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

Explication:

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

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

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

Avant cela, j'ai rencontré des problèmes en utilisant des combinaisons de lecture depuis stdin et en utilisant heredocs

0
Gerry Hickman