Mejores Prácticas para Conceder y Revocar Privilegios de Usuario en MySQL

Usa MySQL GRANT, REVOKE, SHOW GRANTS y DROP USER de forma segura con ejemplos de mínimo privilegio para cuentas de aplicación y administración.

Mejores Prácticas para Conceder y Revocar Privilegios de Usuario en MySQL

Los privilegios de MySQL determinan lo que tus aplicaciones, herramientas y administradores pueden hacer después de conectarse. Una sola cuenta con acceso amplio puede convertir un pequeño error o una contraseña filtrada en una exposición completa de la base de datos.

Usa GRANT, REVOKE y SHOW GRANTS con el principio de mínimo privilegio: cada cuenta debe tener solo los permisos que necesita, desde solo los hosts que utiliza.

Comprendiendo los Privilegios de MySQL

Antes de profundizar en GRANT y REVOKE, es crucial entender los diferentes alcances y tipos de privilegios disponibles en MySQL. Los privilegios definen qué acciones puede realizar un usuario y sobre qué objetos de la base de datos.

Los privilegios de MySQL se pueden categorizar por su alcance:

  • Privilegios Globales (*.*): Se aplican a todas las bases de datos y tablas en el servidor MySQL. Ejemplos incluyen SUPER, PROCESS, RELOAD, CREATE USER.
  • Privilegios de Base de Datos (nombre_base_datos.*): Se aplican a todas las tablas y objetos dentro de una base de datos específica. Ejemplos incluyen SELECT, INSERT, UPDATE, DELETE, CREATE, DROP.
  • Privilegios de Tabla (nombre_base_datos.nombre_tabla): Se aplican a todas las columnas dentro de una tabla específica. Ejemplos incluyen SELECT, INSERT, UPDATE, DELETE, ALTER.
  • Privilegios de Columna (nombre_base_datos.nombre_tabla.nombre_columna): Se aplican a columnas específicas dentro de una tabla. Esto es menos común pero útil para un control altamente granular.
  • Privilegios de Rutina (nombre_base_datos.nombre_rutina): Se aplican a procedimientos almacenados y funciones, controlando EXECUTE y ALTER ROUTINE.
  • Privilegios de Proxy: Permiten que un usuario actúe como otro, útil para aplicaciones que gestionan identidades de usuario.

Algunos privilegios específicos comunes incluyen:

  • SELECT: Leer datos de tablas.
  • INSERT: Agregar nuevas filas a tablas.
  • UPDATE: Modificar filas existentes en tablas.
  • DELETE: Eliminar filas de tablas.
  • CREATE: Crear bases de datos, tablas o índices.
  • DROP: Eliminar bases de datos, tablas o índices.
  • ALTER: Modificar estructuras de tablas.
  • INDEX: Crear o eliminar índices.
  • REFERENCES: Establecer restricciones de clave foránea.
  • CREATE VIEW, SHOW VIEW: Gestionar vistas.
  • CREATE ROUTINE, ALTER ROUTINE, EXECUTE: Gestionar y ejecutar procedimientos almacenados y funciones.
  • FILE: Leer o escribir archivos en el host del servidor (altamente poderoso, usar con extrema precaución).
  • GRANT OPTION: Permite a un usuario conceder sus propios privilegios a otros usuarios. Este es un privilegio muy poderoso y debe otorgarse con moderación.

El Comando GRANT: Concediendo Privilegios de Forma Segura

El comando GRANT se utiliza para asignar privilegios a un usuario de MySQL. Al conceder privilegios, es crucial considerar el principio de mínimo privilegio: solo conceder lo absolutamente necesario.

Sintaxis Básica

La sintaxis general para el comando GRANT es:

GRANT privilegios ON objeto TO 'usuario'@'host' [WITH GRANT OPTION];
  • privilegios: Una lista separada por comas de privilegios (por ejemplo, SELECT, INSERT).
  • objeto: Especifica el alcance (por ejemplo, *.* para global, nombre_base_datos.*, nombre_base_datos.nombre_tabla).
  • 'usuario'@'host': La cuenta de usuario, incluyendo el nombre de usuario y el host desde el cual pueden conectarse. El host puede ser una dirección IP, un nombre de host o un comodín (% para cualquier host, localhost para conexiones locales).
  • WITH GRANT OPTION: (Opcional) Permite al usuario conceder los privilegios especificados a otros usuarios.

Crea o cambia contraseñas con CREATE USER y ALTER USER. Las versiones antiguas de MySQL permitían GRANT ... IDENTIFIED BY, pero la sintaxis moderna de MySQL mantiene la creación de cuentas separada.

Ejemplos Prácticos

Repasemos algunos escenarios comunes.

  1. Creando un Nuevo Usuario y Concediendo Acceso Global de Solo Lectura (Altamente Desaconsejado)

    CREATE USER 'lector_global'@'localhost' IDENTIFIED BY 'StrongPass123!';
    GRANT SELECT ON *.* TO 'lector_global'@'localhost';
    

    Advertencia: Conceder SELECT en *.* da acceso a todas las bases de datos y tablas. Esto es generalmente demasiado amplio para usuarios de aplicaciones y debe evitarse a menos que sea absolutamente necesario para tareas administrativas específicas.

  2. Concediendo Acceso Completo a una Base de Datos Específica para un Usuario de Aplicación

    Un escenario común para un usuario de aplicación que necesita gestionar datos dentro de su propia base de datos.

    CREATE USER 'usuario_app'@'localhost' IDENTIFIED BY 'AppPassSecure!';
    GRANT SELECT, INSERT, UPDATE, DELETE ON `mi_app_db`.* TO 'usuario_app'@'localhost';
    

    Aquí, usuario_app puede realizar operaciones CRUD básicas solo dentro de la base de datos mi_app_db, pero no puede crear nuevas tablas ni modificar el esquema.

  3. Concediendo Acceso de Solo Lectura a una Tabla Específica

    Para una herramienta de informes que solo necesita leer de una tabla particular.

    CREATE USER 'herramienta_informes'@'%' IDENTIFIED BY 'ReportSecret!';
    GRANT SELECT ON `ventas_db`.`pedidos` TO 'herramienta_informes'@'%';
    

    El host '%' permite que herramienta_informes se conecte desde cualquier host, pero solo con acceso SELECT en la tabla pedidos en ventas_db.

  4. Concediendo GRANT OPTION (Usar con Extrema Precaución)

    Si un administrador necesita delegar la gestión de privilegios para una base de datos específica.

    CREATE USER 'admin_db'@'localhost' IDENTIFIED BY 'AdminPass#456';
    GRANT ALL PRIVILEGES ON `inventario_db`.* TO 'admin_db'@'localhost' WITH GRANT OPTION;
    

    admin_db ahora puede conceder cualquier privilegio en inventario_db a otros usuarios. Este es un privilegio poderoso que elude el control centralizado y debe usarse solo cuando sea inevitable.

Consejos para Conceder Privilegios

  • Principio de Mínimo Privilegio: Siempre concede el conjunto mínimo de privilegios requerido para que un usuario o aplicación funcione. Evita ALL PRIVILEGES a menos que sea para una cuenta de administrador de base de datos dedicada.
  • Hosts Específicos: Restringe las conexiones de usuario a direcciones IP o nombres de host específicos ('usuario'@'192.168.1.10' o 'usuario'@'servidorapp.ejemplo.com') en lugar de '%' cuando sea posible.
  • Usuarios Separados: Crea cuentas de usuario separadas para diferentes aplicaciones o servicios, incluso si acceden a la misma base de datos. Esto aísla posibles brechas de seguridad.
  • Sin root para Aplicaciones: Nunca uses la cuenta de usuario root para tus aplicaciones. Crea usuarios dedicados con mínimos privilegios.

El Comando REVOKE: Revocando Privilegios de Forma Efectiva

El comando REVOKE se utiliza para eliminar privilegios de un usuario de MySQL. Es tan importante como GRANT para mantener un entorno de base de datos seguro, especialmente cuando los roles cambian o las aplicaciones se retiran.

Sintaxis Básica

La sintaxis general para el comando REVOKE es:

REVOKE privilegios ON objeto FROM 'usuario'@'host';
  • privilegios: Una lista separada por comas de privilegios a revocar.
  • objeto: El alcance del cual revocar (debe coincidir con el alcance donde se concedieron los privilegios).
  • 'usuario'@'host': La cuenta de usuario de la cual revocar privilegios.

Ejemplos Prácticos

  1. Revocando el Privilegio DELETE de un Usuario de Aplicación

    Si una aplicación ya no necesita eliminar datos, o si deseas reducir sus permisos.

    REVOKE DELETE ON `mi_app_db`.* FROM 'usuario_app'@'localhost';
    

    Ahora, usuario_app aún puede SELECT, INSERT y UPDATE, pero no puede DELETE dentro de mi_app_db.

  2. Revocando GRANT OPTION de un Administrador Delegado

    Si admin_db ya no necesita gestionar los permisos de otros usuarios para inventario_db.

    REVOKE GRANT OPTION ON `inventario_db`.* FROM 'admin_db'@'localhost';
    

    Nota: Para revocar GRANT OPTION, debes especificar explícitamente GRANT OPTION en la declaración REVOKE.

  3. Revocando Todos los Privilegios en una Base de Datos Específica

    Para eliminar todos los privilegios que un usuario tiene sobre una base de datos particular.

    REVOKE ALL PRIVILEGES ON `db_antigua`.* FROM 'app_antigua'@'%';
    

    Advertencia: REVOKE ALL PRIVILEGES en *.* revocará todos los privilegios globales, lo que puede incluir SUPER, CREATE USER, etc. Ten cuidado al usar este alcance globalmente.

  4. Eliminando una Cuenta de Usuario

    Cuando un usuario o aplicación ya no es necesario, es mejor eliminar el usuario por completo.

    DROP USER 'herramienta_informes'@'%';
    

    Este comando elimina al usuario y todos sus privilegios asociados.

Consejos para Revocar Privilegios

  • Coincidir Alcance: Al revocar, asegúrate de que el alcance del objeto (*.*, nombre_base_datos.*, etc.) coincida precisamente con cómo se concedió originalmente el privilegio. Si concediste SELECT en nombre_base_datos.*, debes revocarlo de nombre_base_datos.*, no de nombre_base_datos.nombre_tabla.
  • Verificar: Siempre usa SHOW GRANTS FOR 'usuario'@'host'; después de conceder o revocar privilegios para confirmar los cambios.
  • Omitir flushes innecesarios: FLUSH PRIVILEGES no es necesario después de GRANT, REVOKE, CREATE USER o DROP USER; MySQL aplica esas declaraciones inmediatamente.
  • Considerar efectos en cascada: Si un usuario con GRANT OPTION ha concedido privilegios a otros, revocar su GRANT OPTION no revoca automáticamente los privilegios que concedió. Necesitarías revocar esos por separado.

Mejores Prácticas para la Gestión de Privilegios de Usuario en MySQL

Implementar una estrategia robusta de gestión de privilegios es crucial para la seguridad de la base de datos.

1. Principio de Mínimo Privilegio (PoLP)

Esta es la regla de oro. Concede solo los privilegios mínimos absolutos requeridos para que un usuario o aplicación realice su función prevista. Por ejemplo:

  • Una herramienta de informes necesita SELECT.
  • Una aplicación web típicamente necesita SELECT, INSERT, UPDATE, DELETE.
  • Un proceso ETL podría necesitar INSERT, UPDATE, DELETE, CREATE TABLE, DROP TABLE (pero solo en esquemas de staging específicos).

2. Cuentas de Usuario Dedicadas

  • Evitar Cuentas Compartidas: Cada aplicación, servicio o usuario administrativo debe tener su propia cuenta de usuario única de MySQL. Esto ayuda en la auditoría y el seguimiento de la actividad.
  • Sin root para Aplicaciones: Nunca configures tus aplicaciones para conectarse como el usuario root. El usuario root tiene acceso sin restricciones y solo debe ser utilizado para tareas administrativas críticas por administradores humanos.

3. Contraseñas Fuertes y Rotación de Contraseñas

  • Exige contraseñas fuertes y únicas para todas las cuentas de usuario de MySQL. Utiliza los plugins de validación de contraseñas de MySQL si están disponibles.
  • Implementa una política regular de rotación de contraseñas, especialmente para cuentas con altos privilegios.

4. Restricciones de Host

  • Limita las conexiones de usuario a direcciones IP o nombres de host específicos siempre que sea posible. Reemplaza '%' con localhost, la IP de un servidor de aplicaciones o una subred de red ('usuario'@'192.168.1.%'). Esto previene intentos de acceso no autorizados desde ubicaciones desconocidas.

5. Auditorías y Revisiones Regulares

  • Revisa periódicamente todas las cuentas de usuario y sus privilegios asociados. Elimina cualquier cuenta obsoleta o privilegios innecesarios.
  • Usa SHOW GRANTS FOR 'usuario'@'host'; para inspeccionar permisos.
  • Considera herramientas automatizadas para auditar entornos grandes.

6. Documentar Permisos

  • Mantén una documentación clara de tus usuarios de base de datos, sus roles y los privilegios concedidos a cada uno. Esto ayuda a mantener la consistencia y facilita las auditorías de seguridad.

7. Separar Entornos de Desarrollo, Staging y Producción

  • Nunca uses credenciales de producción en entornos de desarrollo o staging. Cada entorno debe tener su propio conjunto de usuarios y privilegios distintos.

8. Evitar GRANT OPTION a Menos que Sea Absolutamente Necesario

  • Conceder WITH GRANT OPTION delega la gestión de privilegios a ese usuario, lo que puede eludir las políticas de seguridad centralizadas. Reserva esto solo para usuarios administrativos de alta confianza y en el alcance más restrictivo posible.

Visualizando Privilegios Actuales

Para verificar los privilegios asignados a un usuario, usa el comando SHOW GRANTS:

SHOW GRANTS FOR 'nombre_usuario'@'host';

Ejemplo:

SHOW GRANTS FOR 'usuario_app'@'localhost';

La salida podría verse así:

+-------------------------------------------------------------+
| Grants for usuario_app@localhost                            |
+-------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'usuario_app'@'localhost'             |
| GRANT SELECT, INSERT, UPDATE ON `mi_app_db`.* TO 'usuario_app'@'localhost' |
+-------------------------------------------------------------+

La línea GRANT USAGE ON *.* indica que el usuario no tiene privilegios globales, solo la capacidad de conectarse.

Conclusión

Mantén la gestión de privilegios de MySQL limitada y revisable. Crea cuentas dedicadas, restringe hosts, concede solo las acciones necesarias en el alcance útil más pequeño y verifica cada cambio con SHOW GRANTS. Cuando una aplicación o persona ya no necesite acceso, revoca el privilegio o elimina la cuenta en lugar de dejar credenciales obsoletas.