Cómo ingresar la contraseña solo una vez en un script bash que necesita sudo

21

Datos

  • Quiero que los usuarios operadores en esta máquina monten sus propios recursos compartidos cifs
  • El sudoersarchivo ya contiene el /bin/mount -t cifs //*/* /media/* -o username=*comando para todos los operadores.
  • Quiero que los usuarios monten un recurso cifscompartido a través de un script que escriba la contraseña solo una vez, no dos veces.
  • La contraseña de sudo y la contraseña cifs son idénticas.

Lo que ya tengo

Este script funciona:

#!/bin/bash
sudo 'mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER'

... ¡ pero requiere que los usuarios escriban la misma contraseña dos veces!

  • Una vez para sudo
  • Una vez para el monte mismo

Esto también funcionaría:

#!/bin/bash
echo -n Password: 
read -s szPassword
echo $szPassword | sudo -S sh -c 'echo $szPassword | mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER'

... pero esto requeriría que permita que todos los usuarios del operador puedansudo sh (problema de seguridad importante)

Pregunta

¿Cómo montar un recurso compartido cifs en bash ¹ sin poner shel sudoersarchivo ni crear un archivo permanente / temporal?

Nota 1: sin python, perl, C, Go, ... por favor?
Nota 2: Sé que puedo eliminar la contraseña a través del sudoersarchivo, pero estoy tratando de reforzar la seguridad, no aflojarla, sin renunciar a la comodidad ...

Fabby
fuente
2
¿Qué tal printf "%s\n" "$szPassword" "$szPassword" | sudo -S mount -t cifs / ...?
muru
Intentando eso ahora! @Muru
Fabby

Respuestas:

24

En su lugar, debe hacer que el usuario haga la llamada de usar sudo como sudo script. solo verifique si el script se está ejecutando como root, si no, pídalo

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root, use sudo "$0" instead" 1>&2
   exit 1
fi

No intentes capturar la contraseña de tus usuarios.

Braiam
fuente
1
Quizás me falta algo, pero ¿puede explicar cómo esto reduce el número de solicitudes de contraseña de dos a uno? De lo contrario, no veo cómo esto responde la pregunta.
Oliphaunt - reinstalar a Mónica el
@Oliphaunt No veo dos solicitudes de contraseña, ¿puedes explicar eso? Además, esta respuesta no es lo que OP quiere, sino lo que necesita. Es una solución limpia y adecuada cuando necesita ejecutar comandos como root, y cómo lo hacen otras utilidades (verifique si es root, de lo contrario rescatará)
Braiam
1
El problema del OP (según tengo entendido) es que se le solicita al usuario su contraseña sudoy luego (al autenticarse con éxito) nuevamente mount. En su caso de uso, estas contraseñas son idénticas, por lo que puedo ver por qué el OP desea que el usuario solo tenga que ingresar esta contraseña una vez. No creo que su solución ayude con esto. Estoy de acuerdo en que uno no debe capturar contraseñas.
Oliphaunt - reinstalar a Mónica el
Gracias, pero podría haber simplificado un poco la pregunta: ya es un script, ya contiene esa prueba (excepto la 1>&2), está en el inicio automático y solía ser solo un recurso compartido cifs, pero ahora son tres, así que realmente una contraseña es necesario (Ya contiene esa prueba en caso de que alguien más, que no sea miembro del grupo de operadores, intente ejecutarla)
Fabby
@Fabby Sigo pensando que estás abordando el problema incorrectamente. Para estos casos, hay ayuda para "recordar" la contraseña de un recurso compartido CIFS / SMB de forma segura (edición, ~/.smbcredentialspor ejemplo), e incluso sin la necesidad de sudo (si utiliza gvfs, umount o polkit).
Braiam
7

¡Soy tonto!

El siguiente script:

#!/bin/bash
read -p "Password: " -s szPassword
printf "%s\n" "$szPassword" | sudo --stdin mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER,password="$szPassword"

simplemente funciona y:

  1. No crea ningún archivo que contenga contraseñas
  2. Permite al usuario escribir solo una contraseña para múltiples recursos compartidos (incluidos los de Windows)
  3. No necesita privilegios adicionales para ser otorgados. :-)
Fabby
fuente
1
1 pregunta: ¿eso hace eco del comando en la lista de procesos?
Rinzwind
3
@Rinzwind como incorporado, no debería en bash o zsh. Sin embargo, el comando de montaje podría.
muru
<<<también podría usarse en lugar de printf , pero un mejor enfoque sería abandonarlo por readcompleto y usarlo sudo --stdinsolo. Algo así como $ printf "Type out your password\n" && sudo --stdin apt-get update Usuario aún puede escribir la contraseña de sudo. y eso no lo pondrá en la lista de procesos. Pero, por supuesto, hay una cantidad infinita de otros posibles problemas de seguridad, como keyloggers, vulnerabilidades potenciales en sudo, y bla, y bla, y bla en el infinito
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy: ¡Siéntase libre de editar , hombre!
Fabby
3

No requiere sudocontraseña para ejecutar este comando; la contraseña solicita mountrestos.

En sudoers, incluye algo como

ALL        ALL = NOPASSWD: /bin/mount -t cifs //*/* /media/* -o username=*

Después de incluir esto, sudoya no pedirá una contraseña para este comando específico; el usuario aún necesita proporcionar una contraseña para el mountcomando.

Nota : Tomé el comando textualmente de lo que incluiste en la pregunta; No verifiqué si sus comodines permitirían a los usuarios hacer algo desagradable. Lea la página de sudoersmanual para ver ejemplos de maldad. En particular, tenga en cuenta que esta línea sudoerspermite al usuario agregar cualquier número de -ointerruptores u otros argumentos mount. Es posible que desee repensar su enfoque, por ejemplo, agregando un script como @Braiam propone y permita ejecutarlo sudosin autenticación adicional. Luego, el script garantiza que los usuarios solo puedan ejecutar la forma específica de la mountque desea que ejecuten.

Además, en lugar de permitir esto para todos los usuarios, también puede limitar esto a los miembros de un determinado grupo, por ejemplo, puede crear un grupo cifsmounty luego tener

%cifsmount ALL = NOPASSWD: /bin/mount -t cifs //*/* /media/* -o username=*
Oliphaunt - reinstalar a Monica
fuente
@Fabby Lo siento, pero ¿qué tiene de peligroso esto? También puedo estar detectando una pizca de sarcasmo, no estoy seguro.
Oliphaunt - reinstalar a Mónica el
bueno, incluso si sudo no requiere una contraseña, mount aún podría requerir una contraseña. El archivo / etc / sudoers podría usarse para hacer que sudo no requiera una contraseña. Eso no afectaría si Mount solicita una contraseña. Si una persona no pudo montar, entonces sudo terminaría ejecutando un comando que falla, lo que probablemente no sea un problema.
TOOGAM
@TOOGAM Esa fue mi intención. Una contraseña en lugar de dos.
Oliphaunt - reinstalar a Mónica el
Mi intención es mantener un grupo de "operadores" en el archivo sudoers, de modo que si un operador intenta montar sus propias cosas, todavía tiene que escribir una contraseña, pero para montar los montajes de operador "estándar", solo tiene que escribir la contraseña una vez en lugar de 5 veces ... Pero su solución podría funcionar para otros, así que votó positivamente ... (y se eliminaron los comentarios originales)
Fabby
1

Una solución general a estos problemas es colocar el siguiente preámbulo en la parte superior de su sudo que requiere scripts:

#!/bin/bash
case $EUID in
   0) : cool we are already root - fall through ;;
   *) # not root, become root for the rest of this session
      # (and ask for the sudo password only once)
      sudo $0 "$@" ;;
esac
# now the present process is effective-UID  (root)
# so there's no need to put sudo in front of commands

any more commands here will run as superuser ...

Obviamente, esto tiene un inconveniente en que si algunos comandos en el script no requieren sudoejecutarse, aquí hay una elevación innecesaria de privilegios.

De todos modos, pensé que compartiría este pequeño consejo. Lo mejor de todo es que si ya eres eficaz-uid root (por ejemplo, si ya lo llamaste bajo sudo), hace lo correcto con gracia. También es menos amigable dar un error y obligarlo a volver a escribir / volver a ejecutar (con sudo).

También es posible que desee consultar la timestamp_timeoutvariable en la man 5 sudoersque se le sudorecuerda recordar las credenciales del usuario durante un número limitado de minutos (y puede ser fraccional).

arielf
fuente
Simplifiqué demasiado el script para obtener una respuesta fácil: el script ya contiene: #test if root: if not: bail out if [[ $EUID -ne 0 ]]; then echo "This script must be run as root, use sudo "$0" instead" 1>&2 exit 1 fi El punto es que también contiene múltiples monturas, todas con la misma contraseña (nuevamente: eliminado), pero gracias de todos modos ...
Fabby
1
El punto es que la solución anterior requeriría solo un tipeo de la contraseña (para sudo). No debería requerir ningún otro. Además, es general (y más elegante que dar un error y tener que volver a escribir el comando con sudo) para todos los problemas similares, incluso cuando requieren múltiples (más de dos) comandos privilegiados.
arielf
¡ Debería pero no lo hace ! ;-) Eso es porque cada montaje compartido cifs requiere una contraseña también. (ya que puede ser diferente de la contraseña de Ubuntu, pero en este caso no es porque los operadores mantienen sincronizadas sus contraseñas de Windows y Ubuntu)
Fabby