En 02-07 viste una s donde esperabas una x y te prometí que la entenderías a fondo en esta lección. Ha llegado el momento, y viene acompañada de la otra pieza que has usado durante cuatro módulos sin preguntarte nada: sudo. Escribes sudo decenas de veces al día, pero ¿quién ha decidido que puedas? ¿Dónde está escrito? ¿Qué pasaría si Marta te pidiera que luis pudiera reiniciar la aplicación —solo reiniciarla— sin darle la máquina entera? Esta lección responde a las tres preguntas y añade las herramientas que el modelo clásico ugo/rwx no cubre: capabilities, ACL y atributos inmutables. Al final, operador podrá desplegar Tramontana con una regla de sudoers escrita por ti, y Luis leerá los logs sin estar en adm.
Contenido
- Por qué no se trabaja como root
su,su -,sudo -iysudo -scomparadossudoa fondo: caché, entorno y el error de la redirecciónsudoers: sintaxis,visudoy reglas seguras- Trazabilidad: dónde queda la huella de
sudo - Recuperarse de un
sudoersroto - SUID: UID real frente a UID efectivo
- SGID en directorios: el bit del trabajo en equipo
- El sticky bit y
/tmp - Capabilities: el sustituto moderno de SUID
- ACL: permisos que
ugono sabe expresar - Atributos extendidos e inmutabilidad
- Caso Tramontana: la regla de
sudoersdel despliegue
- Por qué no se trabaja como root
Root no tiene permisos: root no tiene comprobación de permisos. El kernel, ante un proceso con UID efectivo 0, se salta la verificación entera. Eso significa tres cosas:
- Un error es irreversible.
rm -rf /opt/tramontana /con un espacio de más, ejecutado comooperador, falla con «Permiso denegado» a la segunda ruta. Ejecutado como root, borra el sistema. - No hay trazabilidad. Si cinco personas comparten la contraseña de root,
auth.logdirá «root hizo X» y nadie sabrá quién fue. Consudo, dirá «operador ejecutó X como root». - No hay mínimo privilegio. Quien necesita reiniciar un servicio no necesita poder leer
/etc/shadowni reformatear un disco.
Por eso Ubuntu viene de fábrica con root sin contraseña utilizable (! en shadow, como viste en 05-01) y todo el trabajo administrativo pasa por sudo.
su, su -, sudo -i y sudo -s comparados
su, su -, sudo -i y sudo -s comparados| Comando | Contraseña que pide | Entorno resultante | PATH |
Directorio |
|---|---|---|---|---|
su |
La de root | Hereda el tuyo casi entero | El tuyo | El actual |
su - |
La de root | Login completo de root, entorno limpio | El de root | /root |
sudo -s |
La tuya | Shell con tu entorno, HOME conservado |
secure_path |
El actual |
sudo -i |
La tuya | Login completo de root, como su - |
El de root | /root |
sudo comando |
La tuya | Solo ese comando, entorno saneado | secure_path |
El actual |
El guion de su - (y de -i) es lo que marca la diferencia: sin él te llevas tus variables, tus alias y tu PATH a una sesión con UID 0, y ese es justo el vector por el que un PATH manipulado con un ls falso acaba ejecutándose como root. Si necesitas una sesión de root, usa sudo -i. Y como norma general, ninguna de las dos: un sudo por acción deja mejor rastro que una sesión de root abierta media hora.
sudo a fondo: caché, entorno y el error de la redirección
sudo a fondo: caché, entorno y el error de la redirecciónLo que hace sudo al invocarlo: comprueba tu identidad contra /etc/sudoers, te pide tu contraseña (no la de root), registra la orden, construye un entorno nuevo y ejecuta el comando con la identidad de destino.
$ sudo -l # ¿qué me deja hacer sudo aquí?
Los usuarios coinciden con esta especificación por defecto:
env_reset, mail_badpass, secure_path=/usr/sbin\:/usr/bin\:/sbin\:/bin
El usuario operador puede ejecutar los siguientes comandos en srv-tramontana:
(ALL : ALL) ALLLa caché de credenciales guarda que ya te autenticaste durante 15 minutos por terminal (timestamp_timeout, en minutos; 0 la desactiva y -1 la hace eterna, lo que es mala idea). sudo -k la invalida ahora mismo, sudo -v la renueva sin ejecutar nada, útil al principio de un script largo.
Opciones que se usan a diario:
sudo -u svc-tramontana /opt/tramontana/app/bin/comprobar # como OTRO usuario, no root
sudo -E ./script.sh # conservar el entorno (si sudoers lo permite; úsalo con miedo)Por defecto env_reset borra tu entorno y secure_path impone un PATH fijo. Es una protección deliberada: sin ella, exportar LD_PRELOAD o alterar el PATH antes de un sudo sería un ascenso a root inmediato. Esa es también la razón de que sudo no encuentre a veces un binario tuyo de /home/operador/bin: no está en secure_path, y hay que dar la ruta absoluta.
Y el clásico que arrastramos desde el Módulo 3:
No falla echo: falla la redirección, que la hace tu shell —que sigue siendo operador— antes de que sudo llegue a ejecutarse. Las dos soluciones correctas:
echo "algo" | sudo tee /etc/tramontana/nota.conf >/dev/null # la habitual
sudo bash -c 'echo "algo" > /etc/tramontana/nota.conf' # cuando hay varias redirecciones
sudoers: sintaxis, visudo y reglas seguras
sudoers: sintaxis, visudo y reglas segurasEl fichero es /etc/sudoers, pero no se edita: se edita con visudo, y las reglas propias se ponen en ficheros aparte dentro de /etc/sudoers.d/, que sudoers incluye con @includedir. visudo bloquea el fichero contra ediciones simultáneas y, sobre todo, valida la sintaxis antes de guardar. Un sudoers con un error de sintaxis deja el sistema sin ningún sudo funcional, y eso es una emergencia.
sudo visudo # edita /etc/sudoers con validación
sudo visudo -f /etc/sudoers.d/tramontana # edita un fichero suelto, también validado
sudo visudo -c # -> /etc/sudoers: correctoLos ficheros de /etc/sudoers.d/ deben tener modo 0440, propiedad root:root, y no llevar punto ni acabar en ~ en el nombre, o sudo los ignora en silencio.
La sintaxis de una regla
operador ALL=(ALL:ALL) ALL %sudo ALL=(ALL:ALL) ALL luis srv-tramontana=(root) NOPASSWD: /usr/bin/systemctl status tramontana.service
%delante del nombre significa grupo: por eso pertenecer asudote da poderes, es esta línea.máquinapermite distribuir el mismosudoersa un parque entero; en un servidor suelto se poneALL.(root)es la identidad de destino;(ALL:ALL)permite además elegir grupo con-g.NOPASSWD:evita pedir la contraseña. Cómodo para lo que ejecuta un script; peligroso para todo lo demás.
Alias
User_Alias OPERACIONES = operador, becario
Host_Alias PRODUCCION = srv-tramontana
Cmnd_Alias SERVICIO = /usr/bin/systemctl start tramontana.service, \
/usr/bin/systemctl restart tramontana.service
Runas_Alias APP = svc-tramontana
OPERACIONES PRODUCCION = (root) SERVICIOPor qué las listas negras no funcionan
sudoers admite ! para denegar, y es una trampa:
# NUNCA hagas esto: falsa sensación de seguridad luis ALL=(ALL) ALL, !/bin/su, !/usr/bin/passwd root
Se salta de mil maneras. Si puedes ejecutar ALL, puedes ejecutar cp /bin/bash /tmp/sh && chmod u+s /tmp/sh, o simplemente:
sudo vim -c ':!/bin/bash' # shell desde el editor
sudo find /etc -maxdepth 0 -exec /bin/bash \; # shell desde find
sudo awk 'BEGIN{system("/bin/bash")}' # shell desde awkLa regla de oro: una regla de sudo es una lista blanca. Enumera lo que se permite; no intentes enumerar lo que se prohíbe. Y desconfía de cualquier comando que sepa ejecutar otros comandos o editar ficheros arbitrarios (vim, less, find, awk, tar --to-command, systemctl sin subcomando fijo, cualquier intérprete).
Reglas seguras:
| Práctica | Motivo |
|---|---|
| Ruta absoluta siempre | sudo mi_script buscaría en un PATH que el usuario controla |
| Argumentos fijos en la regla | systemctl restart tramontana.service, no systemctl a secas |
| Evitar comodines | /bin/chown operador /var/log/* permite /var/log/../../etc/shadow |
| Script propio con permisos root:root 0755 | Si el usuario puede editarlo, la regla le da root completo |
NOPASSWD solo donde es imprescindible |
Y nunca sobre un comando con argumentos libres |
- Trazabilidad: dónde queda la huella de
sudo
sudo$ sudo grep -F 'sudo:' /var/log/auth.log | tail -2
ago 18 09:41:07 srv-tramontana sudo: operador : TTY=pts/0 ; PWD=/home/operador ; USER=root ; COMMAND=/usr/bin/systemctl restart tramontana.service
ago 18 09:41:19 srv-tramontana sudo: luis : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/luis ; USER=root ; COMMAND=/usr/bin/apt install nginxLa misma información está en el journal (journalctl -t sudo, que veremos en 05-06). Los intentos fallidos se registran igual, y son la señal de alarma más barata que tiene un servidor.
Si necesitas más, sudoers puede grabar la sesión entera con Defaults!SERVICIO log_input, log_output y Defaults iolog_dir=/var/log/sudo-io; se reproduce con sudoreplay -l y sudoreplay ID. Ojo: graba lo que se teclea, incluidas contraseñas escritas por error, así que ese directorio es material sensible y su retención debe estar acordada.
- Recuperarse de un
sudoers roto
sudoers rotoSi guardaste un sudoers inválido sin visudo, cualquier sudo responde algo como >>> /etc/sudoers: syntax error near line 22 <<< y se niega a funcionar. Salidas, por orden de preferencia:
- Una sesión root aún abierta en otra terminal: arréglalo desde ahí. Por eso conviene tener una abierta mientras se tocan estos ficheros.
pkexec, que usa polkit y no depende desudoers:pkexec visudo(requiere que exista una regla polkit para tu usuario, habitual en instalaciones de escritorio).- Modo de recuperación: reiniciar, elegir Advanced options → recovery mode → root shell, remontar con
mount -o remount,rw /y ejecutarvisudo. El procedimiento completo es materia de 07-01.
La costumbre que evita todo esto: editar siempre con visudo, y antes de cerrar la sesión, comprobar en otra terminal que sudo -l sigue funcionando.
- SUID: UID real frente a UID efectivo
Todo proceso lleva dos identidades: el UID real (quién lo lanzó) y el UID efectivo (con quién se comprueban los permisos). Normalmente coinciden. El bit SUID rompe esa igualdad: al ejecutar un binario con SUID, el kernel pone como UID efectivo el del propietario del fichero, no el de quien lo ejecuta.
El ejemplo canónico es passwd, que tiene que escribir en /etc/shadow (640 root:shadow) siendo invocado por un usuario normal:
Esa s en el lugar de la x del propietario es SUID. Mientras corre, passwd es root, y su código está escrito para hacer exactamente una cosa y nada más.
Un SUID root propio es casi siempre un fallo de seguridad, porque cualquier descuido dentro del programa —una llamada a system(), un PATH heredado, un desbordamiento— se convierte en root para quien lo invoque. Un script de shell con SUID ni siquiera funciona: Linux ignora el bit en los intérpretes, precisamente porque es imposible de asegurar.
Auditoría obligatoria en cualquier servidor:
$ sudo find / -xdev -perm -4000 -type f -printf '%M %u %p\n' 2>/dev/null | head -4
-rwsr-xr-x root /usr/bin/su
-rwsr-xr-x root /usr/bin/sudo
-rwsr-xr-x root /usr/bin/passwd
-rwsr-xr-x root /usr/bin/mountGuarda esa lista como línea base. Cualquier binario que aparezca después y no venga de un paquete es una alarma. -perm -2000 hace lo mismo con SGID.
- SGID en directorios: el bit del trabajo en equipo
En un ejecutable, SGID es el equivalente de SUID para el grupo. Pero su uso importante es otro: en un directorio, SGID hace que todo lo que se cree dentro herede el grupo del directorio en lugar del grupo primario de quien lo crea. Es la pieza que hace viable el trabajo compartido.
Sin SGID, si operador (grupo primario operador) deja una copia en /srv/tramontana/backups, el fichero pertenece al grupo operador y luis no puede leerlo aunque ambos estén en tramontana. Con SGID:
$ sudo chmod 2770 /srv/tramontana/backups # 2 = SGID, 770 = rwxrwx---
$ ls -ld /srv/tramontana/backups
drwxrws--- 5 operador tramontana 4096 ago 18 04:20 /srv/tramontana/backups
$ touch /srv/tramontana/backups/prueba && ls -l /srv/tramontana/backups/prueba
-rw-r----- 1 operador tramontana 0 ago 18 09:55 /srv/tramontana/backups/pruebaGrupo tramontana sin haberlo pedido: eso es SGID. Aplícalo a todo el árbol compartido y no solo a la raíz:
El bit SGID no arregla los permisos: si tu umask es 027, el fichero sale rw-r----- y el grupo solo lee. Para que el grupo también escriba hace falta umask 007, o mejor, una ACL por defecto (apartado 11).
- El sticky bit y
/tmp
/tmp/tmp es escribible por todo el mundo. Sin protección adicional, cualquiera podría borrar el fichero temporal de otro, porque el permiso de borrado depende del directorio, no del fichero. El sticky bit corrige eso: en un directorio con sticky, solo pueden borrar o renombrar un fichero su propietario, el propietario del directorio y root.
La t final es el sticky bit (octal 1). Es la razón de que el mktemp de tus scripts del Módulo 4 sea seguro frente al vecino, aunque siga necesitando trap para limpiar.
Resumen de los tres bits:
| Bit | Octal | Símbolo | En un fichero ejecutable | En un directorio |
|---|---|---|---|---|
| SUID | 4 | u+s → rws------ |
Corre con el UID del propietario | Sin efecto en Linux |
| SGID | 2 | g+s → ---rws--- |
Corre con el GID del grupo | Los hijos heredan el grupo |
| Sticky | 1 | +t → ------rwt |
Sin efecto hoy | Solo el dueño borra |
chmod 4755 /usr/local/bin/herramienta # SUID + rwxr-xr-x
chmod 2775 /srv/compartido # SGID + rwxrwxr-x ; 1777 sería stickyUna S o una T mayúsculas en ls -l significan que el bit especial está puesto pero falta la x correspondiente: casi siempre es un error de escritura.
- Capabilities: el sustituto moderno de SUID
SUID es todo o nada: das root entero para conseguir una sola facultad. Las capabilities de Linux parten los privilegios de root en unas cuarenta piezas independientes, y se pueden conceder una a una.
El caso de manual: Tramontana quiere escuchar en el puerto 80, y los puertos por debajo de 1024 requieren privilegio. En lugar de correr la aplicación como root:
$ sudo setcap 'cap_net_bind_service=+ep' /opt/tramontana/releases/3.2.1/bin/tramontana
$ getcap /opt/tramontana/releases/3.2.1/bin/tramontana
/opt/tramontana/releases/3.2.1/bin/tramontana cap_net_bind_service=epe es effective y p es permitted. Ahora el binario abre el 80 siendo svc-tramontana y no puede hacer nada más de lo que root podría. Otras habituales: cap_net_raw (para un ping propio), cap_dac_read_search (leer cualquier fichero: casi tan peligroso como root, cuidado), cap_sys_time.
capsh --print | head -3 # qué capabilities tiene tu shell ahora mismo
sudo setcap -r /ruta/binario # retirarlas; getcap -r / audita todo el sistemaAdvertencias reales: las capabilities son un atributo extendido del fichero, así que se pierden al copiar, al reemplazar el binario en un despliegue y en un sistema de ficheros que no las soporte. Si desplegar.sh sustituye el release, hay que volver a aplicarlas — o, mejor, dejar que systemd lo haga con AmbientCapabilities en la unidad, que es lo que montaremos en 05-05.
- ACL: permisos que
ugo no sabe expresar
ugo no sabe expresarEl modelo clásico tiene tres sujetos: propietario, grupo, otros. Marta pide algo que no cabe ahí: «que Luis pueda leer /var/log/tramontana para diagnosticar, pero sin meterlo en adm, que da acceso a todos los logs del sistema». Con ugo solo podrías cambiar el grupo del directorio o abrirlo a «otros». Con ACL, das exactamente ese permiso a esa persona.
$ getfacl /var/log/tramontana
# file: var/log/tramontana
# owner: svc-tramontana
# group: adm
user::rwx
group::r-x
other::---Concedemos lectura y recorrido a luis, y que la herede lo que se cree después:
sudo setfacl -m u:luis:rx /var/log/tramontana # sobre el directorio
sudo setfacl -R -m u:luis:r /var/log/tramontana/*.log # sobre los ficheros actuales
sudo setfacl -d -m u:luis:r /var/log/tramontana # ACL POR DEFECTO: los futuros$ ls -ld /var/log/tramontana
drwxr-x---+ 2 svc-tramontana adm 4096 ago 18 10:02 /var/log/tramontana
$ getfacl /var/log/tramontana | grep -A1 '^user:luis'
user:luis:r-x
mask::r-xEse + al final de los permisos es la marca de que hay una ACL; sin él, ls -l te mentiría por omisión.
| Operación | Comando |
|---|---|
| Añadir/modificar | setfacl -m u:luis:r fichero (g:grupo:rw para grupos) |
| ACL por defecto en directorio | setfacl -d -m u:luis:r directorio |
| Quitar una entrada | setfacl -x u:luis fichero |
| Borrar todas las ACL | setfacl -b fichero |
La máscara (mask::) es el techo de permisos efectivos de todas las entradas salvo user:: y other::. Si la máscara es r--, una entrada user:luis:rw- queda efectivamente en r--, y getfacl lo indica con un comentario #effective:r--. Y aquí está la trampa: chmod g=... reescribe la máscara, de modo que un chmod -R 750 posterior puede anular en silencio todas tus ACL. Si usas ACL, revísalas después de cualquier chmod sobre esa ruta.
Requisito: el sistema de ficheros debe estar montado con soporte ACL, que en ext4 de Ubuntu 24.04 viene activado de serie. Y no olvides que cp no copia ACL salvo con -p o -a, ni tar salvo con --acls.
- Atributos extendidos e inmutabilidad
Por debajo de los permisos hay una capa más: los atributos del sistema de ficheros. El útil para un administrador es i, inmutable: el fichero no se puede modificar, borrar, renombrar ni enlazar, ni siquiera por root, hasta que se retire el atributo.
$ sudo chattr +i /etc/tramontana/app.conf && lsattr /etc/tramontana/app.conf
----i---------e------- /etc/tramontana/app.conf
$ sudo rm /etc/tramontana/app.conf
rm: no se puede borrar '/etc/tramontana/app.conf': Operación no permitida
$ sudo chattr -i /etc/tramontana/app.conf # para poder editarlo de nuevoEs una red de seguridad contra el error humano y contra scripts demasiado entusiastas, no contra un atacante con root (que puede quitarlo igual que tú). Otro atributo útil es a (append-only), pensado para ficheros de log: se puede añadir, no reescribir ni truncar. Y una advertencia práctica: un fichero inmutable rompe cualquier automatismo que lo toque, incluidos apt y tu propio desplegar.sh. Documéntalo en el HISTORIAL o lo pagarás a las 4:20 de la madrugada.
- Caso Tramontana: la regla de
sudoers del despliegue
sudoers del despliegueMarta aprueba los despliegues, pero quien los ejecuta es operador, que hoy tiene sudo completo por estar en el grupo sudo. El objetivo: que pueda hacer su trabajo —gestionar el servicio y desplegar— sin root total, y que luis pueda consultar el estado sin tocar nada.
# /etc/sudoers.d/tramontana (modo 0440, root:root, editado con visudo -f)
# Gestión del servicio y despliegue de Tramontana Reservas.
# Revisado por: Marta Vidal (operaciones) — 2026-08-18
Cmnd_Alias TRAMO_SERVICIO = /usr/bin/systemctl start tramontana.service, \
/usr/bin/systemctl stop tramontana.service, \
/usr/bin/systemctl restart tramontana.service, \
/usr/bin/systemctl reload tramontana.service
Cmnd_Alias TRAMO_LECTURA = /usr/bin/systemctl status tramontana.service, \
/usr/bin/systemctl is-active tramontana.service, \
/usr/bin/journalctl -u tramontana.service *
Cmnd_Alias TRAMO_DESPLIEGUE = /home/operador/bin/desplegar-seguro
operador srv-tramontana = (root) TRAMO_SERVICIO, TRAMO_LECTURA, TRAMO_DESPLIEGUE
luis srv-tramontana = (root) NOPASSWD: TRAMO_LECTURA$ sudo visudo -c -f /etc/sudoers.d/tramontana
/etc/sudoers.d/tramontana: correcto
$ sudo -l -U luis
(root) NOPASSWD: /usr/bin/systemctl status tramontana.service, ...Detalles que no son decorativos:
desplegar-seguroes un envoltorio propiedad deroot:rooty modo 0755 en/home/operador/bin/. Si perteneciera aoperadory fuera escribible por él, la regla equivaldría a dar root completo: podría reescribir el script con/bin/bashdentro. Este es el fallo más frecuente al conceder «solo un script».- Los subcomandos van fijos:
systemctla secas permitiríasystemctl edit, y de ahí a un editor como root hay un paso. luistiene solo lectura y conNOPASSWD, porque lo llama desde su panel de diagnóstico.operadorsigue en el gruposudomientras dure la transición; el objetivo a medio plazo es sacarlo y quedarse solo con estas reglas.
Aviso de cumplimiento. Una regla de
sudoes una concesión de privilegio con impacto directo en la seguridad del sistema y en el acceso a datos personales de huéspedes (los logs y las copias los contienen). Toda alta, cambio o retirada de reglas debe quedar documentada, con fecha y autorizante, y debe revisarla el responsable de seguridad o de cumplimiento (RGPD) antes de aplicarse en producción. Revisasudo -l -U usuariopara cada cuenta al menos una vez al trimestre y en cada baja de personal.
Y las piezas del apartado anterior aplicadas al proyecto:
sudo chmod 2770 /opt/tramontana/shared/uploads /srv/tramontana/backups # SGID: grupo heredado
sudo setfacl -m u:luis:rx -m d:u:luis:r /var/log/tramontana # Luis lee logs sin estar en adm
sudo chattr +i /etc/tramontana/app.conf # nadie lo toca por accidenteErrores Comunes y Consejos
- Editar
/etc/sudoerscon un editor normal. Un error de sintaxis y te quedas fuera:visudosiempre, y ten una segunda terminal abierta mientras editas. - Fichero mal nombrado o con permisos incorrectos.
sudoignora en silencio los ficheros de/etc/sudoers.d/que contengan un punto o no sean 0440. Comprueba consudo -l -U usuario. - Conceder un script que el usuario puede editar. Es root completo disfrazado. El objetivo de una regla debe ser
root:rooty no escribible por su beneficiario. - Usar comodines o comandos «que ejecutan cosas».
systemctl,vim,less,find,tar, cualquier intérprete: todos tienen una vía conocida a shell. Fija subcomando y argumentos, y no confíes en!para denegar: las listas negras se saltan siempre. - Aplicar SGID solo a la carpeta raíz de un árbol compartido: los subdirectorios existentes no lo heredan; usa
find -type d -exec chmod g+s {} +. - Perder las capabilities en un despliegue.
setcapvive en el fichero; si sustituyes el binario, desaparece. Declárala en la unidad de systemd. - Un
chmodque se lleva por delante las ACL al reescribir la máscara: tras cualquierchmodsobre una ruta con+, verifica congetfacl. - Consejo: guarda la línea base de
find / -perm -4000y degetcap -r /junto alHISTORIAL. Comparar esa lista es la auditoría más barata y más eficaz que puedes hacer.
Ejercicios
- Una regla mínima y correcta. El becario debe poder reiniciar únicamente
tramontana.servicey ver su estado, sin contraseña para el estado y con contraseña para el reinicio. Escribe el fichero, instálalo con los permisos correctos, valídalo y demuestra quesudo systemctl restart nginxle queda prohibido. - Auditoría de SUID. Encuentra los binarios con SUID del sistema, comprueba a qué paquete pertenece cada uno y explica por qué encontrar
/usr/local/bin/utilcon SUID root sería una alarma. - ACL de escritura para un tercero. Marta necesita dejar un fichero de tarifas en
/srv/tramontana/backups/envios/sin pertenecer al grupotramontana. Concédele escritura solo en ese subdirectorio, con herencia, y verifica la máscara efectiva.
Soluciones
1.
# /etc/sudoers.d/becario, creado con: sudo visudo -f /etc/sudoers.d/becario becario srv-tramontana = (root) NOPASSWD: /usr/bin/systemctl status tramontana.service becario srv-tramontana = (root) PASSWD: /usr/bin/systemctl restart tramontana.service
$ sudo chmod 0440 /etc/sudoers.d/becario && sudo visudo -c -f /etc/sudoers.d/becario
/etc/sudoers.d/becario: correcto
$ sudo -l -U becario
(root) NOPASSWD: /usr/bin/systemctl status tramontana.service
(root) /usr/bin/systemctl restart tramontana.serviceAl intentar lo prohibido, como becario:
Lo siento, el usuario becario no tiene permitido ejecutar '/usr/bin/systemctl restart nginx' como root en srv-tramontana.
Nótese que la lista es blanca: no hemos escrito ninguna prohibición, y todo lo no enumerado queda fuera por construcción.
2.
$ sudo find / -xdev -perm -4000 -type f 2>/dev/null | while read -r f; do
printf '%-28s %s\n' "$f" "$(dpkg -S "$f" 2>/dev/null | cut -d: -f1 || echo '*** SIN PAQUETE ***')"
done
/usr/bin/sudo sudo
/usr/bin/passwd passwd
/usr/local/bin/util *** SIN PAQUETE ***/usr/local/bin/util no pertenece a ningún paquete: nadie de la distribución responde por él, no se actualiza con apt y nadie ha auditado su código. Con SUID root, cualquier fallo suyo —o cualquier system() que herede el PATH de quien lo invoca— entrega root a cualquier usuario del sistema. Un binario así en un servidor de producción se investiga como un posible compromiso, no se «deja por si acaso».
3.
$ sudo setfacl -m u:marta:rwx -d -m u:marta:rw /srv/tramontana/backups/envios
$ getfacl /srv/tramontana/backups/envios
# file: srv/tramontana/backups/envios
# owner: operador
# group: tramontana
user::rwx
user:marta:rwx
group::rwx
mask::rwx
other::---
default:user:marta:rw-
default:mask::rw-u:marta:rwx sobre el directorio le permite entrar y crear; la entrada default: hace que los ficheros que deje dentro nazcan con rw- para ella. La máscara es rwx, así que los permisos efectivos son los concedidos: si valiera r-x, getfacl marcaría #effective:r-x y Marta no podría escribir pese a la entrada. Y recuerda: un chmod g=rx posterior sobre ese directorio reescribiría la máscara y anularía el permiso sin tocar la entrada de Marta.
Conclusión
Se acabó la magia de sudo y la de esa s que arrastrabas desde 02-07. Sabes que root no tiene permisos sino ausencia de comprobaciones, y por qué eso obliga a trabajar con mínimo privilegio y trazabilidad; distingues su de su - y sudo -s de sudo -i por el entorno que hereda cada uno; entiendes env_reset, secure_path y por qué la redirección de sudo echo falla; escribes reglas de sudoers con visudo, en /etc/sudoers.d/, con rutas absolutas, argumentos fijos y forma de lista blanca, sabiendo que las listas negras se saltan desde vim, find o awk; sabes dónde queda la traza y cómo salir de un sudoers roto.
Y dominas la capa de permisos que el modelo ugo no cubre: SUID y la diferencia entre UID real y efectivo, con find -perm -4000 como auditoría; SGID en directorios para que un equipo comparta ficheros de verdad, aplicado ya a /opt/tramontana/shared/uploads y a /srv/tramontana/backups; el sticky bit que hace seguro /tmp; las capabilities que sustituyen a un SUID entero por una sola facultad como cap_net_bind_service; las ACL con las que Luis lee /var/log/tramontana sin entrar en adm, con su máscara y su trampa del chmod; y chattr +i para blindar /etc/tramontana/app.conf. En /etc/sudoers.d/tramontana hay una regla real, validada y documentada, que permite operar el servicio sin repartir root.
El siguiente cabo suelto es el software. Has instalado cosas con apt durante cuatro módulos sin preguntarte de dónde venían, quién las firma ni qué pasa si el motor de base de datos salta de versión mayor una noche cualquiera mientras duermes. En Gestión de Paquetes verás las dos capas de Debian, dpkg y apt, la anatomía de un .deb, los repositorios en formato deb822 de Ubuntu 24.04 con sus claves en /etc/apt/keyrings/, cómo fijar versiones para que la base de datos de Tramontana no se mueva sola, y el debate incómodo de si un servidor debe reiniciarse solo tras una actualización de seguridad.
Curso de Linux: De Principiante a Administrador de Sistemas
Módulo 1: Introducción a Linux
- ¿Qué es Linux?
- Historia de Linux
- Distribuciones de Linux
- Instalando Linux
- Primer Contacto con el Sistema
- Estructura del Sistema de Archivos de Linux
Módulo 2: Comandos Básicos de Linux
- Introducción a la Línea de Comandos
- Obtener Ayuda y Documentación del Sistema
- Navegando el Sistema de Archivos
- Operaciones con Archivos y Directorios
- Visualización y Edición de Archivos
- Enlaces Duros y Simbólicos
- Permisos y Propiedad de Archivos
Módulo 3: Habilidades Avanzadas en la Línea de Comandos
- El Entorno del Shell: Variables, Alias e Historial
- Uso de Comodines y Expresiones Regulares
- Búsqueda de Archivos y Contenido: find, locate y grep
- Tuberías y Redirección
- Procesamiento de Texto: cut, sort, uniq, sed y awk
- Gestión de Procesos
- Programación de Tareas con Cron
- Comandos de Redes
Módulo 4: Scripting en Shell
- Introducción al Scripting en Shell
- Variables y Tipos de Datos
- Entrada, Salida y Argumentos de un Script
- Estructuras de Control
- Funciones y Librerías
- Depuración y Manejo de Errores
- Scripts de Producción: Buenas Prácticas
Módulo 5: Administración del Sistema
- Gestión de Usuarios y Grupos
- sudo y Permisos Especiales
- Gestión de Paquetes
- Gestión de Discos
- systemd y la Gestión de Servicios
- Registros del Sistema: journald y syslog
- Monitoreo del Sistema y Optimización del Rendimiento
- Respaldo y Restauración
Módulo 6: Redes y Seguridad
- Configuración de Redes
- SSH y Acceso Remoto
- Firewall y Seguridad Perimetral
- Sistemas de Detección de Intrusos
- Gestión de Secretos y Certificados TLS
- Asegurando Sistemas Linux
Módulo 7: Temas Avanzados
- El Proceso de Arranque y la Recuperación del Sistema
- Diagnóstico Avanzado: strace, perf y eBPF
- Optimización del Kernel de Linux
- Virtualización con Linux
- Contenedores de Linux y Docker
- Automatización con Ansible
- Alta Disponibilidad y Balanceo de Carga
