mysql.h


GRANT, REVOKE

GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON {tbl_name | * | *.* | db_name.*}
    TO user [IDENTIFIED BY [PASSWORD] 'password']
        [, user [IDENTIFIED BY [PASSWORD] 'password']] ...
    [REQUIRE
        NONE |
        [{SSL| X509}]
        [CIPHER 'cipher' [AND]]
        [ISSUER 'issuer' [AND]]
        [SUBJECT 'subject']]
    [WITH [GRANT OPTION | MAX_QUERIES_PER_HOUR count |
                          MAX_UPDATES_PER_HOUR count |
                          MAX_CONNECTIONS_PER_HOUR count |
                          MAX_USER_CONNECTIONS count]]
REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON {tbl_name | * | *.* | db_name.*}
    FROM user [, user] ...
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

Las sentencias GRANT y REVOKE permiten a los administradores del sistema crear cuentas de usuario MySQL y conceder y revocar derechos de esas cuentas. GRANT y REVOKE están disponibles a partir de MySQL 3.22.11. Para versiones anteriores de MySQL, estas sentencias no hacen nada.

La información sobre cuentas MySQL se almacena en las tablas de la base de datos mysql. Esta base de datos y el control de acceso se describen en detalle en la sección 5 "Database Administration", que se puede consultar para detalles adicionales.

Los privilegios pueden ser concedidos en varios niveles:

Nivel global

Los privilegios globales se aplican a todas las bases de datos de un servidor dado. Estos privilegios se almacenan en la tabla mysql.user. GRANT ALL ON *.* y REVOKE ALL ON *.* concenden y revocan sólo privilegios globales.

Nivel de base de datos

Los privilegios de base de datos se aplican a todos los objetos en una base de datos dada. Estos privilegios se almacenan en las tablas mysql.db y mysql.host. GRANT ALL ON db_name.* y REVOKE ALL ON db_name.* conceden y revocan sólo privilegios de base de datos.

Nivel de tabla

Los privilegios de tabla se aplican a todas las columnas de una tabla dada. Estos privilegios se almacenan en la tabla mysql.tables_priv. GRANT ALL ON db_name.tbl_name y REVOKE ALL ON db_name.tbl_name conceden y revocan únicamente privilegios de tabla.

Nivel de columna

Los privilegios de columna se aplican a una columna individual en una tabla dada. Estos privilegios se almacenan en la tabla mysql.columns_priv. Cuando se usa REVOKE, se deben especificar las mismas columnas que cuando se concedieron los privilegios.

Nivel de rutina

Los privilegios CREATE ROUTINE, ALTER ROUTINE, EXECUTE y GRANT se aplican a rutinas almacenadas. Pueden ser concedidos en los niveles global y de base de datos. Además, excepto para CREATE ROUTINE, estos privilegios pueden ser concedidos en el nivel de rutina para rutinas individuales y se almacenan en la tabla mysql.procs_priv.

Para hacer más sencillo revocar todos los privilegios, MySQL 4.1.2 ha añadido la siguiente sintaxis, que elimina todos los privilegios de los niveles de global, de base de datos, tabla y columna para los usuarios nombrados:

mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

Antes de la versión 4.1.2 de MySQL, no es posible eliminar todos los privilegios de una vez. Se necesitan dos sentencias:

mysql> REVOKE ALL PRIVILEGES ON *.* FROM user [, user] ...
mysql> REVOKE GRANT OPTION ON *.* FROM user [, user] ...

Para las sentencias GRANT y REVOKE, se puede usar cualquiera de los siguientes valores para priv_type:

Privilegio Significado
ALL [PRIVILEGES] Activa todos los privilegios excepto GRANT OPTION.
ALTER Permite el uso de ALTER TABLE.
CREATE Permite el uso de CREATE TABLE.
CREATE ROUTINE Crear rutinas almacenadas.
CREATE TEMPORARY TABLES Permite el uso de CREATE TEMPORARY TABLE.
CREATE VIEW Permite el uso de CREATE VIEW.
DELETE Permite el uso de DELETE.
DROP Permite el uso de DROP TABLE.
EXECUTE Permite al usuario ejecutar procedimientos almacenados.
FILE Permite el uso de SELECT ... INTO OUTFILE y LOAD DATA INFILE.
INDEX Permite el uso de CREATE INDEX y DROP INDEX.
INSERT Permite el uso de INSERT.
LOCK TABLES Permite el uso de LOCK TABLES en tablas sobre las que ya se posea el privilegio SELECT.
PROCESS Permite el uso de SHOW FULL PROCESSLIST.
REFERENCES No implementado.
RELOAD Permite el uso de FLUSH.
REPLICATION CLIENT Permite al usuario preguntar dónde estan el los servidores esclavo o maestro.
REPLICATION SLAVE Necesario para la replicación esclava (para leer eventos del diario binario desde el maestro).
SELECT Permite el uso de SELECT.
SHOW DATABASES La sentencia SHOW DATABASES muestra todas las bases de datos.
SHOW VIEW Permite el uso de SHOW CREATE VIEW.
SHUTDOWN Permite el uso del apagado de mysqladmin shutdown.
SUPER Permite el uso de las sentencias CHANGE MASTER, KILL, PURGE MASTER LOGS y SET GLOBAL, el comando depurador de mysqladmin debug; permite conectar (una vez) aunque se haya alcanzado el número de conexiones max_connections.
UPDATE Permite el uso de UPDATE.
USAGE Sinónimo de "sin privilegios".
GRANT OPTION Permite conceder privilegios.

Los privilegios CREATE TEMPORARY TABLES, EXECUTE, LOCK TABLES, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES y SUPER fueron añadidos en MySQL 4.0.2. (EXECUTE no estará activo hasta MySQL 5.0.3.) CREATE VIEW y SHOW VIEW se añadirán en MySQL 5.0.1. CREATE ROUTINE y ALTER ROUTINE en MySQL 5.0.3. Para usar estos privilegios cuando se actualice a partir de una versión anterior de MySQL que no los tenga, se deben actualizar las tablas de concesiones.

El privilegio REFERENCES no se usa actualmente.

En versiones más antiguas de MySQL que no tienen el privilegio SUPER, hay que especificar el privilegio PROCESS en su lugar.

USAGE se puede usar cuando se quiere crear un usuario que no tenga privilegios.

Usar SHOW GRANTS para determinar qué privilegios tiene una cuenta.

Se pueden asignar privilegios globales mediante el uso de la sintaxis ON *.* o privilegios de base de datos mediante la sintaxis ON db_name.*. Si se especifica ON * y se tiene seleccionada una base de datos por defecto, los privilegios se conceden a esa base de datos. (Cuidado: si se especifica ON * y no se tiene ninguna base de datos seleccionada por defecto, los privilegios se conceden globalmente.)

Los privilegios EXECUTION, FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES, SHUTDOWN y SUPER son privilegios administrativos que sólo pueden ser concedidos de forma global (usando la sintaxis ON *.*).

Otros privilegios pueden ser concedidos globalmente o en niveles más específicos.

Los únicos valores priv_type que se pueden especificar para una tabla son SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT OPTION, INDEX y ALTER.

Los únicos valores priv_type que se pueden especificar para una columna (esto es, cuando se usa una cláusula column_list) son SELECT, INSERT y UPDATE.

Los únicos valores priv_type que se pueden especificar en el nivel de rutina son ALTER ROUTINE, EXECUTE y GRANT. CREATE ROUTINE no es un privilegio de nivel de rutina porque se debe tener este privilegio para que sea posible crear una rutina en primer lugar.

Para los nilveles global, de base de datos, tabla y rutina, GRANT ALL sólo asigna privilegios que existan en el nivel en que se están concediendo. Por ejemplo, si se usa GRANT ALL ON db_name.*, que es una sentencia de nivel de base de datos, ningún privilegio exclusivo del nivel global, como FILE será concedido.

Para privilegios de nivel de columna (esto es, cuando se especifica column_list), se deben nombrar los privilegios a conceder explícitamente. No se puede usa ALL como especificador de privilegio.

MySQL permite conceder privilegios de nivel de base de datos aunque la base de datos no exista, para hacer más sencilla la preparación de una base de datos para su uso. Sin embargo, MySQL no permite actualmente conceder privilegios a nivel de tabla o columna si la tabla no existe. De forma similar, no se pueden conceder privilegios de nivel de rutina a procedimientos que no existan.

MySQL no revoca ningún privilegio automáticamente aunque se elimine una tabla o una base de datos. Si se elimina una rutina y se han concedido privilegios de nivel de rutina para ella, estos serán revocados.

Nota: los comodines '_' y '%' están permitidos cuando se especifican nombres de bases de datos en sentencias GRANT que concedan privilegios en los niveles global o de base de datos. Esto significa, por ejemplo, que si se quiere usar un carácter '_' como parte de un nombre de base de datos, se debe especificar como '\_' en la sentencia GRANT, para prevenir que el usuario al que se están concediendo pueda acceder a otras bases de datos que coincidan con el patrón definido por el comodín; por ejemplo, GRANT ... ON `foo\_bar`.* TO ....

Para albergar derechos concedidos a usuarios para máquinas arbitrarias, MySQL soporta la especificación para el valor de usuario en el formato user_name@host_name. Si un nombre de usuario user_name o de máquina host_name es un valor legal como identificador sin entrecomillar, no será necesario entrecomillarlo. Sin embargo, las comillas serán necesarias para especificar una cadena user_name que contenga caracteres especiales (como '-'), o una cadena de host_name que contenga caracteres especiales o caracteres comodín (como '%'); por ejemplo, 'test-user'@'test-hostname'. Hay que entrecomillar el nombre de usuario y el de la máquina separadamente.

Se pueden especificar comodines en el nombre de máquina. Por ejemplo, user_name@'%.loc.gov' se aplica a user_name para cualquier máquina en el dominio loc.gov y user_name@'144.155.166.%' se aplica a user_name para cualquier máquina en la clase C subred 144.155.166.

El formato simplificado user_name es sinónimo de user_name@'%'.

MySQL no soporta comodines en nombres de usuario. Los usuarios anónimos se definen mediante la inserción de entradas con User='' en la tabla mysql.user o creando un usuario con un nombre vacío con la sentencia GRANT:

mysql> GRANT ALL ON test.* TO ''@'localhost' ...

Cuando se especifican valores entre comillas para base de datos, tablas, columnas y nombres de rutina como identificadores, se usan tildes a izquieda ('`'). Los nombres de máquina, de usuario y contraseñas como cadenas, se usan apóstrofes (''').

Aviso: si se permite la conexión al servidor MySQL de usuarios anónimos, también se deben conceder privilegios a todos los usuarios locales como user_name@localhost. En caso contrario, se usará la cuenta del usuario anónimo para la máquina local en la tabla mysql.user cuando usuarios con nombre intenten conectarse al servidor MySQL desde la máquina local. (Esta cuenta de usuario anónimo se crea durante la instalación de MySQL.)

Se puede determinar si esto se aplica a cada caso mediante la ejecución de la siguiente sentencia:

mysql> SELECT Host, User FROM mysql.user WHERE User='';

Si se quiere borrar la cuenta de usuario anónimo local para evitar el problema descrito, usar estas sentencias:

mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User='';
mysql> FLUSH PRIVILEGES;

GRANT soporta nombres de máquina de hasta 60 caracteres. Los nombres de base de datos, tabla, columna y rutina pueden tener hasta 64 caracteres. Los nombres de usuario hasta 16 caracteres.

Los privilegios para una tabla o columna se forman aditivamente con el O lógico de los privilegios de cada uno de los cuatro niveles de provilegios. Por ejemplo, si la tabla mysql.user especifica que un usuario tiene un privilegio global SELECT, el privilegio no puede ser denegado por una entrada en el nivel de base de datos, tabla o columna.

Los privilegios para una columna se pueden calcular de este modo:

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges

En la mayoría de los casos, sólo se conceden privilegios a un usuario en uno de los niveles de privilegio, de modo que la vida no suele tener esta complicación.

Si se conceden privilegios para una combinación de usuario/máquina que no existe en la tabla mysql.user, se añade una entrada y se conserva hasta que se elimina con una sentencia DELETE. En otras palabras, GRANT puede crear entradas en la tabla de usuarios, pero REVOKE no las eliminará; se debe hacer explícitamente usando DROP USER o DELETE.

A partir de MySQL 3.22.12, si se crea un nuevo usuario o si se posee privilegios globales, la contraseña del usuario se asigna con la contraseña especificada por la cláusula IDENTIFIED BY, si se proporciona una. Si el usuario tiene una contraseña, se remplaza con la nueva.

Aviso: si se crea un nuevo usuario pero no se especifica una cláusula IDENTIFIED BY, el usuario no tiene contraseña. Esto es inseguro. A partir de MySQL 5.0.2, se puede activar el modo SQL NO_AUTO_CREATE_USER para evitar que GRANT cree nuevos usuarios si de otro modo los haría, a no ser que se proporcione una contraseña en IDENTIFIED BY.

Las contraseñas también se pueden asignar mediante la sentencia SET PASSWORD.

En la cláusula IDENTIFIED BY, la contraseña puede ser proporcionada como un valor de contraseña literal. No es necesario usar la función PASSWORD() como sí lo es para la sentencia SET PASSWORD. Por ejemplo:

GRANT ... IDENTIFIED BY 'mypass';

Si no se quiere enviar la contraseña en texto claro y se conoce el valor que se devuelve por la función PASSWORD() para la contraseña, se puede especificar tal valor precedido por la palabra clave PASSWORD:

GRANT ... IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';

En un programa C, se puede obtener ese valor mediante el uso de la función del API C make_scrambled_password().

Si se conceden privilegios para una base de datos, se crea una entrada en la tabla mysql.db si es necesario. Si todos los privilegios para una base de datos se eliminan con REVOKE, esa estrada será eliminada.

Si un usuario no tiene privilegios para una tabla, el nombre de la tabla no se muestra cuando el usuario pide una lista de tablas (por ejemplo, con una sentencia SHOW TABLES).

El privilegio SHOW DATABASES permite a una cuenta ver los nombres de bases de datos mediante la sentencia SHOW DATABASES. Las cuentas que no tienen este privilegio sólo ven las bases de datos para las que tienen algún privilegio, y no pueden usar la sentencia en ningún caso si el servidor fue arrancado con la opción --skip-show-database.

La cláusula WITH GRANT OPTION proporciona al usuario la oportunidad de dar a otros usuarios cualquier privilegio que que éste tenga en el nivel de privilegios especificado. Se debe ser cuidadoso con a quien se le da el privilegio GRANT OPTION, porque dos usuarios con privilegios diferentes pueden unirlos.

No se puede conceder a otro usuario un privilegio que no se posee; el privilegio GRANT OPTION permite dar sólo aquellos privilegios que se poseen.

Hay que saber que cuando se concede a un usuario el privilegio GRANT OPTION en un nivel particular, cualquier privilegio que posea el usuario (o que se le conceda en el fututo) en ese nivel, también se puede conceder por ese usuario. Dupongamos que se concede a un usuario el privilegio INSERT en una base de datos. Si se concede a continuación el privilegio SELECT en la base de datos y se especifica WITH GRANT OPTION, el usuarui puede dar a otros no sólo el privilegio SELECT, sino también el INSERT. Si a continuación se concede el privilegio UPDATE al usuario en la base de datos, puede conceder a otros los privilegios INSERT, SELECT y UPDATE.

No se deben conceder privilegios ALTER a un usuario normal. Si se hace, el usuario puede intentar transtornar el sistema de privilegios mediante el renombrado de tablas.

Las opciones MAX_QUERIES_PER_HOUR count, MAX_UPDATES_PER_HOUR count y MAX_CONNECTIONS_PER_HOUR count son nuevas en MySQL 4.0.2. Sirven para limitar el número de consultas, actualizaciones y entradas que un usuario puede realizar durante una hora. Si el contador se pone a 0 (el valor por defecto), significa que no hay límite para ese usuario.

La opción MAX_USER_CONNECTIONS count es nueva en MySQL 5.0.3. Limita el número máximo de conexiones simultáneas que puede hacer la cuenta. Si count es 0 (valor por defecto), la variable de sistema max_user_connections determina el número de conexiones simultáneas para la cuenta.

Nota: para especificar cualquiera de estas opciones de limitación de recursos para un usuario sin que se afecten los prvilegios ya existextentes, usar GRANT USAGE ON *.* ... WITH MAX_....

MySQL puede verificar los atributos de certificado X509 además de la autentificación habitual que se basa en nombre de usuario y contraseña. Para especificar opciones relacionadas con SSL para una cuenta MySQL, usar la cláusula REQUIRE para la sentencias GRANT.

Existen distintas posibilidades para limitar tipos de conexión para una cuenta:

  • Si una cuenta no tiene los requerimientos SSL o X509, se permiten conexiones sin encriptar si el nombre de usuario y contraseña son válidos. Sin embargo, las conexiones encriptadas también se pueden usar en la opción del cliente, si éste tiene el certificado apropiado y los ficheros de clave.
  • La opción REQUIRE SSL dice al servidoe que permita sólo conexiones encriptadas SSL para la cuenta. Hay que tener en cuenta que esta opción puede ser omitida si existe cualquier registro de control de acceso que permita conexiones no SSL.
    mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
        -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;
  • REQUIRE X509 significa que el cliente debe tener un certificado válido pero que el certificado exacto, emisor y condición no importan. El único requisito es que debe ser posible verificar su firma con uno de los certificados CA.
    mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
        -> IDENTIFIED BY 'goodsecret' REQUIRE X509;
  • REQUIRE ISSUER 'issuer' pone la restricción en los intentos de conexión de que el cliente debe presentar un certificado X509 válido emitido por el CA 'issuer'. Si el cliente presenta un certificado que es válido pero tiene un emisor diferente, el servidor rechaza la conexión. El uso de certificados X509 siempre implica encriptado, de modo que la opción SSL es innecesaria.
    mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
        -> IDENTIFIED BY 'goodsecret'
        -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
           O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';
    Notar que el valor ISSUER debe ser introducido como una única cadena.
  • REQUIRE SUBJECT 'subject' pone otra restricción en los intentos de conexión, la de que el cliente debe presentar un certificado válido X509 con la condición 'subject' en él. Si el cliente presenta un certificado válido pero que tiene una condición diferente, el servidor rechaza la conexión.
    mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
    -> IDENTIFIED BY 'goodsecret' -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/ O=MySQL demo client certificate/ CN=Tonu Samuel/Email=tonu@example.com';
    Notar que el valor SUBJECT debe ser introducido como una única cadena.
  • REQUIRE CIPHER 'cipher' es necesario para asegurar que se usa un cifrado lo bastante fuerte y claves lo suficientemente largas. SSL mismo puede ser débil si se usan algoritmos antiguos con claves de encriptado cortas. Usando esta opción, se puede preguntar por un método de cifrado concreto para permitir la conexión.
    mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
        -> IDENTIFIED BY 'goodsecret'
        -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';

Las opciones SUBJECT, ISSUER y CIPHER pueden combinarse en la cláusula REQUIRE así:

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
    -> IDENTIFIED BY 'goodsecret'
    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
       O=MySQL demo client certificate/
       CN=Tonu Samuel/Email=tonu@example.com'
    -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
       O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
    -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';

Notar que cada valor SUBJECT e ISSUER deben ser introducidos como una única cadena.

A partir de MySQL 4.0.4, la palabra clave AND es opcional entre las opciones REQUIRE.

El orden de las opciones no es importante, pero ninguna opción se puede especificar dos veces.

Cuando mysqld arranca, todos los privilegios se leen en memoria. Los privielgios de base de datos, tabla y columna tienen efecto en seguida, y los privilegios de nivel de usuario tienen efecto la vez siguiente que el usuario se conecte. Las modificaciones en las tablas de concesiones que se realicen usando GRANT o REVOKE se notifican al servidor inmediatamente. Si se modifican las tablas de concesiones manualmente (usando INSERT, UPDATE, etc), se debe ejectuar una sentencia FLUSH PRIVILEGES o ejecutar mysqladmin flush-privileges para indicar al servidor que recargue las tablas de concesiones.

Si se están usando privilegios de tabla o columna para un único usuario, el servidor examina los privilegios de tabla y columna para todos los usuarios y esto ralentiza MySQL un poco. De forma similar, si se limita el número de consultas, actualizaciones o conexiones para algunos usuarios, el servidor debe monitorizar esos valores.

Las mayores diferencias entre las versiones de GRANT de SQL estándar y de MySQL son:

  • En MySQL, los privilegios están asociados con una combinación de usuario/contraseña y no sólo con un usuario.
  • SQL estándar no tiene provilegios de nivel global o de base de datos, ni soporta todos los tipos de privilegio que soporta MySQL.
  • MySQL no soporta los privilegios de SQL estándar TRIGGER o UNDER.
  • Los privilegios de SQL estándar están estructurados de forma jerárquica. Si se elimina un usuario, todos los privilegios que tiene concedidos se revocan. Esto también es cierto en MySQL 5.0.2 y siguientes si se usar DROP USER. Antes de 5.0.2, los privilegios concedidos no son revocados automáticamente; deben ser revocados directamente.
  • Con SQL estándar, cuando se elimina una tabla, todos los privilegios para la tabla son revocados. Con SQL estándar, cuando se revoca un privilegio, todos los privilegios concedidos basados en él son revocados también. En MySQL, los privilegios pueden ser eliminados sólo con la sentencia REVOKE explícita o mediante la manipulación de las tablas de concesiones de MySQL.
  • En MySQL, si sólo se posee el privilegio INSERT en algunas de las columnas de una tabla, se pueden ejecutar sentecias INSERT en la tabla; las columnas para las que no se posee el privilegio INSERT serán asignadas a sus valores por defecto. SQL estádar requiere que se posea el privilegio INSERT en todas las columnas.