El uso exclusivo de la cuenta root para operar en un entorno de bases de datos representa un riesgo de seguridad crítico. Para mitigar este problema, es fundamental implementar una administración adecuada de usuarios en MySQL, asignando cuentas específicas con privilegios limitados a las bases de datos y tablas que realmente necesitan manipular.
- Información de las Cuentas de Usuario
En MySQL, los datos de los usuarios se almacenan en la tabla user dentro de la base de datos del sistema mysql.
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| inventory_db |
| mysql |
| performance_schema |
| sys |
+--------------------+
mysql> USE mysql;
Database changed
mysql> SELECT Host, User, authentication_string FROM user;
+-----------+------------------+------------------------------------------------------------------------+
| Host | User | authentication_string |
+-----------+------------------+------------------------------------------------------------------------+
| localhost | debian-sys-maint | $A$005$Ir17{.dswvJU-PDolvS3oBXr2zxf7Z2T4Mi6U6UX/gzYiVWEd.jfzs8T/1 |
| localhost | mysql.infoschema | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| localhost | mysql.session | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| localhost | mysql.sys | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| localhost | root | |
+-----------+------------------+
Descripción de los campos:
Host: Define desde qué máquina o dirección IP se permite la conexión. Un valor delocalhostrestringe el acceso únicamente al servidor local.User: El nombre de la cuenta.authentication_string: Almacena el hash de la contraseña generado mediante el plugin de autenticación correspondiente.
1.1 Creación de Usuarios
Para registrar una nueva cuenta en el sistema, se utiliza la siguiente sintaxis:
CREATE USER 'nombre_usuario'@'host_o_ip' IDENTIFIED BY 'contraseña_segura';
Ejemplo práctico:
-- Crear un usuario con acceso exclusivo desde el servidor local
mysql> CREATE USER 'dev_operator'@'localhost' IDENTIFIED BY 'SecurePass#2023!';
Query OK, 0 rows affected (0.05 sec)
-- Verificar la creación
mysql> SELECT User, Host, authentication_string FROM user;
+------------------+-----------+------------------------------------------------------------------------+
| User | Host | authentication_string |
+------------------+-----------+------------------------------------------------------------------------+
| debian-sys-maint | localhost | $A$005$Ir17{.dswvJU-PDolvS3oBXr2zxf7Z2T4Mi6U6UX/gzYiVWEd.jfzs8T/1 |
| dev_operator | localhost | $A$005$X9#mP2kL9... (hash generado automáticamente) |
| root | localhost | |
+------------------+-----------+
-- Si los cambios no se reflejan inmediatamente, forzar la recarga de privilegios:
mysql> FLUSH PRIVILEGES;
También es posible configurar el Host como % para permitir conexiones desde cualquier dirección IP, aunque esto no se recomienda en entornos de producción por motivos de seguridad:
-- Crear un usuario con acceso remoto (uso bajo propia responsabilidad)
mysql> CREATE USER 'remote_analyst'@'%' IDENTIFIED BY 'RemotePass#99!';
Query OK, 0 rows affected (0.02 sec)
1.2 Eliminación de Usuarios
Para revocar el acceso y eliminar una cuenta permanentemente:
DROP USER 'nombre_usuario'@'host_o_ip';
-- Nota: Si se omite el host, MySQL asumirá '%' por defecto en algunas versiones antiguas, pero es buena práctica especificarlo.
Ejemplo práctico:
-- Eliminar el usuario de acceso remoto
mysql> DROP USER 'remote_analyst'@'%';
Query OK, 0 rows affected (0.03 sec)
-- Confirmar la eliminación
mysql> SELECT User, Host FROM user WHERE User = 'remote_analyst';
Empty set (0.00 sec)
1.3 Actualización de Contraseñas
Las credenciales pueden ser modificadas por el propio usuario o por un administrador.
-- Opción 1: El usuario actual cambia su propia contraseña
SET PASSWORD = 'nueva_contraseña';
-- Opción 2: Un administrador (como root) cambia la contraseña de otro usuario
-- Para MySQL 8.0 y versiones posteriores, se recomienda usar ALTER USER:
ALTER USER 'nombre_usuario'@'host_o_ip' IDENTIFIED BY 'nueva_contraseña';
-- En versiones anteriores (5.7 o inferior) se usaba:
-- SET PASSWORD FOR 'nombre_usuario'@'host_o_ip' = PASSWORD('nueva_contraseña');
Ejemplo práctico:
-- El administrador root actualiza la clave del operador local
mysql> ALTER USER 'dev_operator'@'localhost' IDENTIFIED BY 'NewSecurePass#2024!';
Query OK, 0 rows affected (0.01 sec)
mysql> FLUSH PRIVILEGES;
- Control de Privilegios y Permisos
Una cuenta recién creeada carece de permisos para interactuar con los objetos de la base de datos. Es necesario asignar los privilegios específicos según el principio de menor privilegio.
2.1 Asingación de Privilegios
La instrucción GRANT se utiliza para otorgar permisos.
GRANT lista_de_privilegios ON base_de_datos.objeto TO 'nombre_usuario'@'host_o_ip';
Detalles de la sintaxis:
lista_de_privilegios: Puede ser un solo permiso o varios separados por comas (ej.SELECT, INSERT, UPDATE). UsarALL PRIVILEGESotorga todos los permisos sobre el objeto especificado.base_de_datos.objeto:*.*: Aplica a todas las bases de datos y todos sus objetos.nombre_bd.*: Aplica a todas las tablas y objetos dentro de una base de datos específica.nombre_bd.nombre_tabla: Aplica únicamente a una tabla concreta.
Ejemplo práctico:
-- Otorgar permisos de solo lectura sobre todas las tablas de inventory_db
mysql> GRANT SELECT ON inventory_db.* TO 'dev_operator'@'localhost';
Query OK, 0 rows affected (0.01 sec)
-- Otorgar permisos de lectura y escritura sobre una tabla específica
mysql> GRANT SELECT, INSERT, UPDATE ON inventory_db.products TO 'dev_operator'@'localhost';
Query OK, 0 rows affected (0.02 sec)
2.2 Inspeción de Privilegios Asignados
Para auditar los permisos actuales de una cuenta, se utiliza SHOW GRANTS.
SHOW GRANTS FOR 'nombre_usuario'@'host_o_ip';
Ejemplo práctico:
-- Revisar los permisos del usuario root
mysql> SHOW GRANTS FOR 'root'@'localhost'\G
*************************** 1. row ***************************
Grants for root@localhost: GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO `root`@`localhost` WITH GRANT OPTION
-- Revisar los permisos del operador de desarrollo
mysql> SHOW GRANTS FOR 'dev_operator'@'localhost'\G
*************************** 1. row ***************************
Grants for dev_operator@localhost: GRANT USAGE ON *.* TO `dev_operator`@`localhost`
*************************** 2. row ***************************
Grants for dev_operator@localhost: GRANT SELECT, INSERT, UPDATE ON `inventory_db`.`products` TO `dev_operator`@`localhost`
*************************** 3. row ***************************
Grants for dev_operator@localhost: GRANT SELECT ON `inventory_db`.* TO `dev_operator`@`localhost`
2.3 Revocación de Privilegios
Si es necesario retirar permisos previamente otorgados, se emplea la sentencia REVOKE.
REVOKE lista_de_privilegios ON base_de_datos.objeto FROM 'nombre_usuario'@'host_o_ip';
Ejemplo práctico:
-- Retirar el permiso de inserción sobre la tabla de productos
mysql> REVOKE INSERT ON inventory_db.products FROM 'dev_operator'@'localhost';
Query OK, 0 rows affected (0.01 sec)
-- Revocar todos los permisos sobre la base de datos completa
mysql> REVOKE ALL PRIVILEGES ON inventory_db.* FROM 'dev_operator'@'localhost';
Query OK, 0 rows affected (0.02 sec)