Generalmente habilitamos el uso de sudo para que un usuario pueda ejecutar, con permisos de superusuario, cualquier comando o ejecutable. Esto puede ser una configuración válida para un sistema de escritorio, donde tenemos unos pocos usuarios (o a veces sólo uno) y necesitamos que algunos de ellos puedan autenticarse como root para ejecutar tareas de mantenimiento del sistema o instalar aplicaciones.

Pero cuando se trata de servidores, se debe habilitar sudo para que cada usuario únicamente pueda ejecutar, como superusuario, los comandos mínimos necesarios para llevar a cabo su tarea. Por ejemplo, si se requiere que un usuario tenga la capacidad de montar y desmontar sistemas de archivos, sólo se debe permitir ejecutar como superusuario los comandos mount y umount.

En este artículo voy a explicar cómo configurar sudoers para permitir que un usuario pueda ejecutar como root, utilizando sudo, sólo un comando específico.

Para muchos sysadmins sudo es visto como el malo de la película: ese comando con el que cualquier usuario puede ejecutar cualquier comando como superusuario utilizando su contraseña, o incluso permitir que cualquiera sea root ejecutando sudo su. Aunque este comportamiento es producto de la configuración utilizada por defecto en muchos sistemas de escritorio. Por ejemplo, en el artículo Cómo permitir sudo demostré como permitir que el usuario "pepe" pueda ejecutar cualquier comando como superusuario (e incluso abrir una sesión como superusuario ejecutando sudo su) agregando la siguiente línea (con la herramienta visudo) en el archivo /etc/sudoers:

pepe ALL=(ALL) ALL

Esta es una configuración muy básica y pobre desde el punto de vista de seguridad. Sin embargo es posible configurar sudo para que por ejemplo un usuario pueda ejecutar, autenticándose como superusuario, sólo un conjunto de comandos específicos, o incluso un único comando.

La herramienta sudo permite que un usuario pueda ejecutar un comando como superusuario, o como otro usuario, tal como se especifica en la política de seguridad. La política de seguridad se encarga de determinar qué privilegios tiene un usuario para ejecutar sudo (si es que tiene alguno). Comúnmente se requiere que el usuario se autentique a sí mismo, ingresando su contraseña u otro mecanismo de autenticación. Si se requiere autenticación, hay un tiempo límite específico de la política para ingresar la contraseña (por defecto 5 minutos). Además, las políticas de seguridad pueden soportar el almacenamiento temporal (caching) de credenciales para permitir que el usuario pueda ejecutar sudo nuevamente dentro de un período de tiempo sin necesidad de ingresar nuevamente su contraseña (por defecto también es 5 minutos).

El módulo sudoers implementa la política de seguridad por defecto de sudo. Se encarga de determinar los privilegios que tiene cada usuario para correr sudo. La política se configura en el archivo /etc/sudoers y todos los directorios incluidos mediante sentencias #includedir, y opcionalmente soporta LDAP.

El archivo sudoers está compuesto por dos tipos de entradas: aliases (variables) y especificaciones de usuario (que definen quién puede ejecutar qué). Existen cuatro tipos de aliases: User_Alias, Runas_Alias, Host_Alias y Cmnd_Alias. Cada definición de alias es de la forma:

TIPO_DE_ALIAS NOMBRE_DEL_ALIAS = valor1, valor2, ...

Donde los nombres de aliases deben comenzar con una letra mayúscula.

Para los aliases de usuario (User_Alias) se debe especificar una lista de usuarios. Esta lista soporta el uso de nombres de usuario, ids de usuario (prefijados con un caracter '#'), nombres de grupo e ids de grupo (prefijados con '%' y '%#' respectivamente), grupos de red (prefijados con '+'), nombres de grupos y nombres de ids no-Unix (prefijados con '%:' y '%:#' respectivamente) y otros aliases. Es posible utilizar comillas dobles para evitar caracteres especiales y espacios.

Los aliases para "ejecutar como" (Runas_Alias) se especifica igual que los aliases de usuario.

Para especificar los aliases de host (Host_Alias) se pueden utilizar nombres de host, direcciones IP, direcciones de red, grupos de red (prefijados con '+') y otros aliases de host.

Tal vez los más interesantes de todos los aliases son los aliases de comando (Cmnd_Alias). Es posible especificar uno o más nombres de comandos, directorios y otros aliases de comando.

Un nombre de comando es un nombre de archivo calificado (con la ruta absoluta al binario/ejecutable) que puede incluir comodines (wildcards). Un nombre de archivo simple permite a un usuario ejecutar el comando con cualquier argumento que desee. Sin embargo, es posible especificar los argumentos de línea de comandos que se permiten (incluyendo comodines). De esta forma se logra una muy buena granularidad, para permitir que el usuario ejecute únicamente lo que necesita (principio de mínimo privilegio). De forma alternativa, es posible especificar "" para indicar que el comando sólo puede ser ejecutado sin argumentos.

Un directorio es una ruta calificada finalizada con '/'. Cuando se especifica un directorio, el usuario será capaz de ejecutar cualquier archivo dentro del mismo (pero no dentro de los subdirectorios).

Si un comando tiene argumentos asociados, entonces deben coincidir exactamente con aquellos enviados por el usuario en la línea de comandos.

Las especificaciones de usuario determinan qué comandos un usuario puede ejecutar (y como qué usuario) en los hosts especificados. Por defecto los comandos se ejecutan como root, pero este comportamiento se puede cambiar en cada comando. La estructura básica de cada regla de especificación de usuario es:

QUIÉN DONDE = (COMO QUIÉN) QUÉ

Cada parte de la regla se puede definir en línea, por ejemplo:

pepe localhost = (operator) /usr/bin/mount

Este comando permite que el usuario "pepe" ejecute el comando mount como el usuario "operator" en el sistema local (localhost, 127.0.0.1, etc.)

Pero, como veremos en el ejemplo, es posible utilizar aliases en cada parte de la regla.

Manos a la obra

A modo de ejemplo, supongamos que es necesario que un usuario (no root) sea capaz de actualizar un sistema Debian sin especificar su contraseña. Pero no se desea que el usuario pueda instalar o eliminar paquetes. Sólo debe poder actualizar los paquetes actualmente instalados. Es decir, cómo ejecutar apt-get update && apt-get upgrade && apt-get clean sin ser root.

Como se hacen cambios en el sistema, el gestor de paquetes de APT requiere correr como root. Por ello será necesario que el usuario, "pepe" a partir de ahora, pueda ejecutar con sudo el comando apt-get. Además se requiere que "pepe" no necesite especificar su contraseña, y que sólo pueda ejecutar los comandos de APT "update", "upgrade" y "clean". No se desea que "pepe" pueda ejecutar por ejemplo apt-get install ni apt-get purge.

Entonces es necesario editar la política de seguridad por defecto "sudoers" para que el usuario "pepe" pueda ejecutar como superusuario (root), sin necesidad de ingresar su contraseña, los comandos sudo apt-get update, sudo apt-get upgrade y sudo apt-get clean.

Como mencioné anteriormente, además del archivo /etc/sudoers, por defecto se incluyen todos los archivos del directorio /etc/sudoers.d/. sudo lee reglas de los archivos en este directorio, excepto los nombres de archivo que comienzan con '.' o finalizan con '~', para evitar problemas con archivos ocultos/temporales.

Cambiar al directorio de configuración de reglas de sudoers:

root@debian7:~# cd /etc/sudoers.d/

Dentro de este directorio vamos a crear un nuevo archivo de configuración de reglas de sudoers llamado "pepe":

root@debian7:/etc/sudoers.d# nano pepe

El archivo /etc/sudoers.d/pepe debe tener el siguiente contenido:

################################################
# Política de seguridad para el usuario "pepe" #
# Sólo se permite ejecutar los comandos:       #
#  apt-get update                              #
#  apt-get upgrade                             #
#  apt-get clean                               #
################################################

#### CONFIGURACION GLOBAL

# Alias para definir el nombre de host del servidor
Host_Alias SERVIDOR = localhost, debian7.linuxito.com, debian7

# Configuración por defecto para contraseñas
Defaults passwd_tries = 3, passwd_timeout = 5

# Máscara de directorios y archivos por default
Defaults@SERVIDOR umask = 0022

#### USUARIOS

# Alias para definir al usuario "pepe"
User_Alias USR_PEPE = pepe

#### COMANDOS

# Alias para definir los comandos para actualizar el sistema
Cmnd_Alias CMD_APT_UPDATE = /usr/bin/apt-get update
Cmnd_Alias CMD_APT_UPGRADE = /usr/bin/apt-get upgrade
Cmnd_Alias CMD_APT_CLEAN = /usr/bin/apt-get clean

#### REGLAS
USR_PEPE SERVIDOR = NOPASSWD:CMD_APT_UPDATE
USR_PEPE SERVIDOR = NOPASSWD:CMD_APT_UPGRADE
USR_PEPE SERVIDOR = NOPASSWD:CMD_APT_CLEAN

Sólo se permite que "pepe" pueda ejecutar, sin ingresar password, los comandos apt-get update, apt-get upgrade y apt-get clean. Notar la opción "NOPASSWD:" delante de éstos comandos. Cambiar la variable "SERVIDOR" para que refleje el nombre host del servidor.

Si se van a definir varias políticas para diferentes usuarios/grupos es recomendable separar la configuración global en un archivo aparte (llamado "servidor", por ejemplo) para no repetirla. Lo mismo se puede hacer con los comandos y usuarios, ya que no es necesario que una variable esté definida en el mismo archivo que es usada.

Luego de crear los archivos necesarios dentro del directorio /etc/sudoers.d/, se deben configurar los permisos a nivel filesystem de forma adecuada:

root@debian7:/etc/sudoers.d# chmod 440 *

A partir de este momento el usuario "pepe" podrá ejecutar sudo apt-get update sin ingresar su contraseña, pero no podrá ejecutar apt-get install.

Para mayor información recomiendo leer las páginas de manual de sudo y sudoers:

man sudo
man sudoers

¡Espero que les sea útil!


Tal vez pueda interesarte


Compartí este artículo