Forma correcta de permitir que el usuario ingrese la contraseña para un script bash usando solo la GUI (con el terminal oculto)

8

He creado un script bash que usa kdialog exclusivamente para interactuar con el usuario. Se inicia desde un archivo ".desktop" para que el usuario nunca vea el terminal. Se ve 100% como una aplicación GUI (aunque es solo un script bash). Se ejecuta solo en KDE (Kubuntu 12.04).

Mi único problema es manejar la entrada de contraseña de forma segura y conveniente. No puedo encontrar una solución satisfactoria.

El script fue diseñado para ejecutarse como un usuario normal y para solicitar la contraseña cuando se necesita un comando sudo por primera vez. De esta manera, la mayoría de los comandos, aquellos que no requieren derechos de sudo, se ejecutan como el usuario normal. Lo que sucede (cuando el script se ejecuta desde el terminal) es que se le solicita al usuario su contraseña una vez y el tiempo de espera de sudo predeterminado permite que finalice el script, incluidos los comandos de sudo adicionales, sin solicitar al usuario nuevamente. Así es como quiero que funcione cuando se ejecuta detrás de la GUI también.

El problema principal es que el uso kdesudopara iniciar mi script, que es la forma estándar de la GUI, significa que el usuario root ejecuta todo el script. Entonces, la propiedad de los archivos se asigna al usuario raíz, no puedo confiar ~/en las rutas, y muchas otras cosas son menos que ideales. Ejecutar todo el script como usuario root es solo una solución muy insatisfactoria y creo que es una mala práctica.

Agradezco cualquier idea para permitir que un usuario ingrese la contraseña de sudo solo una vez a través de GUI sin ejecutar todo el script como root. Gracias.

MountainX
fuente

Respuestas:

14

La -Aopción sudo le permite especificar un programa auxiliar (en la variable SUDO_ASKPASS) que le pedirá la contraseña.

Cree un script para solicitar la contraseña (myaskpass.sh):

#!/bin/bash
zenity --password --title=Authentication

Luego inserte esta línea al comienzo de su script:

export SUDO_ASKPASS="/path/to/myaskpass.sh"

y reemplace todas las ocurrencias de sudo <command>con:

sudo -A <command>

Puede usar cualquier programa de solicitud de contraseña que desee en lugar de zenity. Tuve que encapsularlo dentro de un script porque SUDO_ASKPASS debe apuntar a un archivo, por lo que no funcionará con la --passwordopción requerida por zenity.

Lo anterior funciona de maravilla si se ejecuta desde la línea de comandos o si elige Ejecutar en la terminal después de hacer doble clic en el archivo de secuencia de comandos en el administrador de archivos, pero si elige Ejecutar o intenta iniciarlo desde un archivo .desktop, todos sudole pedirán el para contraseña nuevamente.


Si no desea una ventana de terminal, puede almacenar la contraseña en una variable y canalizarla sudo -S. Tal vez haya algunas preocupaciones de seguridad, pero creo que es bastante seguro (lea los comentarios en esta respuesta ).

Inserte esta línea al comienzo de su script:

PASSWD="$(zenity --password --title=Authentication)\n"

y reemplace todas las ocurrencias de sudo <command>con:

echo -e $PASSWD | sudo -S <command>
Eric Carvalho
fuente
Gracias. Eso es muy interesante. Sin embargo, cuando se usa esto, el tiempo de espera de sudo habitual (por ejemplo, 15 minutos) se pierde. ¡Mi script, que tiene más de 50 comandos sudo, ahora solicita la contraseña del usuario más de 50 veces! Busqué en Google un poco y no vi una solución. ¿Conoces uno?
MountainX
Gracias por la actualización. La alternativa que sugiere es algo que había descartado debido a problemas de seguridad, pero al leer los comentarios en el enlace que proporcionó, creo que probablemente sea lo suficientemente seguro. Y es una manera fácil de resolver el problema. Gracias.
MountainX
Las pruebas en mi sistema tienen que ser sudo -s(minúsculas s) y no sudo -S(mayúsculas s).
WinEunuuchs2Unix
0

Esto se basa en la excelente respuesta de Eric Carvalho. Lo estoy publicando para explicar el problema que encontré. Específicamente, cuando se usa esto, se pierde el tiempo de espera de sudo habitual (por ejemplo, 15 minutos). ¡Mi script, que tiene más de 50 comandos sudo, ahora solicita la contraseña del usuario más de 50 veces!

Aquí hay un ejemplo de trabajo completo de todas las partes de la solución. Consiste en un script bash, un script "myaskpass" como sugirió Eric y un archivo ".desktop". Todo debería ser 100% GUI (sin interacción del terminal), por lo que el archivo .desktop es esencial (afaik).

$ cat myaskpass.sh 
#!/bin/bash
kdialog --password "Please enter your password: "
exit 0


$ cat askpasstest1.desktop 
#!/usr/bin/env xdg-open
[Desktop Entry]
Comment=SUDO_ASKPASS tester1
Exec=bash /home/user/test/askpasstest1.sh
GenericName=SUDO_ASKPASS tester1
Name=SUDO_ASKPASS tester1
NoDisplay=false
Path[$e]=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
Categories=Application;Utility;
X-KDE-SubstituteUID=false
X-KDE-Username=

Y un script de prueba en sí mismo. Este le pedirá su contraseña dos veces cuando use esta solución. (Normalmente, solo se pediría una vez debido al tiempo de espera predeterminado de sudo).

#!/bin/bash

sudo -k
SUDO_ASKPASS="/home/user/test/myaskpass.sh" sudo -A touch filemadeas_askpass1
touch filemadeas_regularuser1
SUDO_ASKPASS="/home/user/test/myaskpass.sh" sudo -A touch filemadeas_askpass2
touch filemadeas_regularuser2
ls -la filemadeas* > /home/user/test/fma.log
kdialog --title "Files Created" --textbox /home/user/test/fma.log 640 480
sudo rm filemadeas_*
rm fma.log

exit 0
MountainX
fuente
Al ejecutar este script desde la línea de comandos, la contraseña se solicita solo una vez. Ejecutar desde la GUI (haciendo clic en .desktop o .sh en el administrador de archivos) sudo -Avuelve a asignar la contraseña. Trataré de resolver esto.
Eric Carvalho
Acabo de actualizar mi respuesta.
Eric Carvalho
Eric ... ¿encontraste una solución al problema?
Anthony
0

El siguiente script funciona a través de la línea de comando, archivo de escritorio o doble clic, solicita la contraseña solo una vez, y el patrón de comando sudo -Sp '' <your command here> <<<${sudo_password}se puede usar varias veces en cualquier parte del archivo:

    # get sudo password
    sudo_password=$( gksudo --print-pass --message="Provide permission to make system changes: Type your password or press Cancel." -- : 2>/dev/null )
    # check for null entry or cancellation
    if [[ ${?} != 0 || -z ${sudo_password} ]]
    then
        exit 4
    fi
    if ! sudo -kSp '' [ 1 ] <<<${sudo_password} 2>/dev/null
    then
        exit 4
    fi
    # command
    sudo -Sp '' gedit "/etc/hosts" <<<${sudo_password}
Sadi
fuente